Django - тег шаблона счетчика, который хорошо работает даже с вложенным тегом - PullRequest
2 голосов
/ 01 октября 2011

Я пытаюсь создать собственный тег шаблона, который будет увеличивать переменную.Это можно было бы использовать так:

{% for fruit in basket %}
    {if fruit.is_apple %}{% count apples %}{% endif %}
{% endfor %}
<p>There are {{ apples }} apples in your basket</p>

Я придумал это:

#project/app/templatetags/counter.py

class CounterNode(template.Node):
    def __init__(self, varname):
        self.varname = varname

    def render(self, context):
        if self.varname in context:
            context[self.varname] += 1
        else:
            context[self.varname] = 1
        return ''


@register.tag
def counter(parser, token):
    try:
        tag_name, args = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError(
            "'counter' node requires a variable name.")
    return CounterNode(args)

Это прекрасно работает, пока вы не попытаетесь использовать тег счетчика в цикле for.Переменная count увеличивается внутри цикла, но сбрасывается в 1, когда переменная вызывается вне цикла.

Это связано с методом render () класса template.defaulttags.ForNode, который вызывает context.pop () в конце, но я не могу понять, почему это делается и как с этим можно справиться в моем пользовательском теге шаблона.

Итак, вопрос: как я могу получить свой счетчик теговувеличить даже на протяжении цикла?

Ответы [ 3 ]

4 голосов
/ 01 октября 2011

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

1 голос
/ 10 ноября 2011

Я нашел django-templateaddons библиотека, которая имеет {% counter%} tag , которая работает на уровне шаблона независимо от вложенных циклов.

0 голосов
/ 28 июня 2012

У меня есть методика, которая хорошо работает для ограничения поведения внутри вложенных циклов, для которых не требуются пользовательские теги. Единственное ограничение - вы должны заранее знать верхний предел, который вы пытаетесь установить. В нашем случае мы знали, что хотим отображать только первые шесть галерей изображений из произвольного числа издателей и количество галерей на издателя. Это строго лимит уровня представления, поэтому мы не хотели специально рассматривать представление. Главное предостережение в том, что у вас должно быть n + 1 значений в теге цикла, чтобы ничего не повторялось. Да, я знаю, что имею в виду «mycycle» до того, как он объявлен, но, поскольку вы не можете действительно объявить переменную в языке шаблонов Django, я думаю, что я могу быть прощен; это прекрасно работает.

{% for pubs in sortedpubs %}
    {% for gallery in pubs.publisher.galleries.all %}
        {# Code to count inside nested loops... #}
        {# Uses "cycle" from the next line to count up to 6, then stop rendering #}
        {% if mycycle < 6 %} 
            <!-- {% cycle 1 2 3 4 5 6 7 as mycycle %} -->
            {# ...Render Stuff here... #}
        {% endif %}
    {% endfor %} 
{% endfor %}
...