Django - 一个即使嵌套for标签也能正常工作的计数模板标签
我正在尝试制作一个自定义的模板标签,用来增加一个变量的值。使用方法大概是这样的:
{% 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)
这个方法在正常情况下很好用,但如果你在一个循环里使用这个计数标签,就会出现问题。循环内部的计数变量会正常增加,但当你在循环外部调用这个变量时,它又会被重置为1。
这个问题和模板.defaulttags.ForNode类的render()方法有关,这个方法在结束时会调用context.pop(),但我不太明白这样做的原因,以及我该如何在我的自定义模板标签中处理这个问题。
所以我的问题是:我该如何让我的计数标签在循环中也能继续增加呢?
3 个回答
0
我有一个技巧,可以在嵌套循环中限制行为,而且不需要使用任何特殊标签。唯一的限制是,你必须提前知道你想要设置的上限。在我们的例子中,我们知道只想显示前六个图片画廊,而这些画廊来自不同的发布者,发布者的数量是随意的。这只是一个展示层面的限制,所以我们不想特别处理这个视图。一个主要的注意事项是,你在循环标签中必须有 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 %}
1
我发现了一个叫做 django-templateaddons 的库,它里面有一个 {% counter %} 标签,这个标签可以在模板中使用,而且不受嵌套循环的影响。
4
别用计数标签了,可以创建一个模型方法来计算水果的数量,或者通过视图方法传递这个数量。模板其实不太适合用来处理业务逻辑,即使是像计数这么简单的事情。