Django - Пример простого пользовательского тега шаблона - PullRequest
52 голосов
/ 23 июня 2011

У меня пользователей , видео , тем , критериев и оценок

  • A видео имеет тему
  • A тему имеет критерии
  • A пользователь может создать видео для данной темы
  • A пользователь может оценить видео по каждому критериям , указанным для соответствующей темы .

Вы можете увидеть мое оригинальное сообщение Django - пример модели оценки DetailView Template toполучить подробную информацию об используемой модели

Я расширил шаблон DetailView на основе модели video , чтобы поместить список оценок для выбранного видео для данного пользователя в качестве дополнительного контекста.

class VideoFileDetailView(DetailView):
  model = VideoFile

  def get_context_data(self, **kwargs):
    context = super(VideoFileDetailView, self).get_context_data(**kwargs)
    context['rates'] = VideoRate.objects.filter(video=self.object, user=self.request.user)
    return context

В шаблоне, указанном DetailView, я хотел бы перечислить критерии видео , и для каждого критерия отображается текущий raзначение от пользователя .

<div id="rating">
  <ul>
{% for crit in videofile.topic.crits.all %}
    <li>
  {% for rate in rates %}
    {% if rate.crit.id == crit.id %}
      {{ rate.rate }}
    {% endif %}
  {% endfor %}
      <div class="rateit"
        data-rateit-value="{# The rating value #}"
        data-rateit-ispreset="true"
        crit-id="{{ crit.id }}"></div>
      {{ crit }}
    </li>
{% endfor %}
  </ul>
</div>

( rateit - это плагин jquery, который я использую для рисования элементов управления рейтингом красивых звезд)

На самом деле я получаю свои рейтинговые значения здесь во втором for, но я уверен, что есть лучший способ сделать это.На самом деле, я до сих пор не уверен в правильности моей модели .

Наконец, я бы хотел заменить {# The rating value #} на значение рейтинга от оценки для текущего крит (в цикле).Как я могу это сделать?

Ответы [ 2 ]

84 голосов
/ 27 июня 2011

Вот мое решение (на основе пользовательского тега ):

Сначала создайте структуру файла.Перейдите в каталог приложения, где требуется тег, и добавьте следующие файлы:

templatetags
templatetags/__init__.py
templatetags/video_tags.py

Файл templatetags / video_tags.py :

from django import template

register = template.Library()

@register.simple_tag
def get_rate(crit, rates):
    return rates.get(crit=crit).rate

Шаблончасть, с нашим тегом вызова:

{% load video_tags %}

<div id="rating">
  <ul>
{% for crit in videofile.topic.crits.all %}
    <li>
      <div class="rateit"
        data-rateit-value="{% get_rate crit rates %}"
        data-rateit-ispreset="true"
        crit-id="{{ crit.id }}"></div>
      {{ crit }}
    </li>
{% endfor %}
  </ul>
</div>
13 голосов

Встроенный HTML в теге

Если размер HTML небольшой, этот метод удобнее, чем создание отдельного файла.

В этом примере исключаются ссылки на профили пользователей.,Файл templatetags/somemodule.py содержит:

from django import template
from django.template import Template

register = template.Library()

@register.simple_tag(takes_context=True)
def user_link(context):
    return Template('<a href="{% url \'user_detail\' ' +
            'user.id %}">{{ user.username }}</a>').render(context)

Template#render уже возвращает безопасную строку, не экранированную XSS.Например, если бы мы только что сделали:

return '<br>'

, это бы сбежало.Возможно, вы захотите поиграть с mark_safe.

. Вы можете сделать этот тег доступным на всех видах с помощью:

TEMPLATES = [
    {
        'OPTIONS': {
            'builtins': [
                'myprojectname.templatetags.somemodule',

в settings.py.

.:

...