Как сделать так, чтобы цикл for прерывался по счетчику в jinja2?
Как сделать так, чтобы цикл for product in products
прерывался после того, как условие if выполнится 3 раза. Я пытался установить счетчик, но это не работает... потому что set
не принимается внутри циклов for. Хотя я проверил его еще немного, он не принимается нигде.
Когда я использую set
, он выбрасывает это исключение или его разновидность: Invalid block tag on line 11: 'set', expected 'endblock'. Did you forget to register or load this tag?
Я знаю, что я должен поместить всю логику, для которой я использую jinja2, внутрь представления и затем передать ее через словарь, но это займет слишком много времени, чтобы исследовать все об этом, а я просто хочу закончить с этим.
Честно говоря, я очень устал, сейчас 6 утра, и я не знаю, что делать. Заранее спасибо за помощь. :)
Edit: Я знаю, что должен использовать namespace() для того, чтобы set мог распространяться по диапазонам. Но само set
по-прежнему вызывает то же исключение, что и выше.
HTML
{% for category in categories %}
<div>
<h5 class="text-line"><a href="" class="store-category"><span>{{category.name}}</span></a></h5>
</div>
<!-- Cards Container -->
<div class="shop-cards">
{% set counter = 0 %}
{% for product in products %}
{% if product.category.categoryID == category.categoryID %}
<!-- CARD 1 -->
<div class="card">
<image class="product-image" src="{% static 'images/product-4.png' %}"></image>
<div class="card-category-price">
<h3 class="product-name">{{product.name}}</h3>
<h3 class="product-price">{{product.price}}</h3>
</div>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
Проблема, по-видимому, возникает из-за неправильного понимания функциональности шаблонов. Она должна использоваться в основном для отображения, а не для фильтрации, а вы столкнулись с проблемой фильтрации:
Я хочу отфильтровать 3 первых элемента списка, которые удовлетворяют определенному условию
это ваша основная проблема, и шаблонизаторы будут плохо решать ее, в то время как это именно то, с чем хорошо справляются Python и ORM Django.
Почему бы вам сначала не отфильтровать в Django, а затем отобразить в шаблоне? Например, следующим образом:
...
products = queryset.filter(abc=condition)[:3]
context = Context({ 'products': products })
return HttpResponse(template.render(context))
Вы не можете (по дизайну). Django по дизайну ориентирован на мнения, а язык шаблонов предназначен для отображения, а не для логики.
Вместо этого вы можете использовать Jinja.
Или вы можете делать сложные вещи в Python и передавать результаты в язык шаблонов через контекст. Имейте в виду, что добавление произвольных объектов в список в Python - дешевая операция. Поэтому (в CBV) что-то вроде
context['first_three'] = self.get_first_three( whatever)
...
def get_first_three(self, whatever):
first_three = []
for obj in ...:
if complicated stuff ...
first_three.append( obj)
if len(first_three) == 3:
break
return first_three
BTW вы не можете (легко?) реализовать break в шаблонизаторе Django, но вы можете легко дать ему возможность считать:
class Counter( object):
def __init__(self):
self.n = 0
def value(self):
return self.n
def incr(self):
self.n += 1
return ''
В контексте передают context['counter'] = Counter()
В шаблоне ссылайтесь на {{counter.value}}
сколько угодно, а в условных выражениях, где нужно подсчитать случаи, используйте {{counter.incr}}
. Но это халтура, и, вероятно, ее лучше избегать.