Django template {% if x.number == 0 %} does not work - django

This {% if x.number == 1 %} and {% if x.number == 2 %} work good
but {% if x.number == 0 %} does not work. Why?
{% for d in data %}
{% for x in d.animalnumber_set.all %}
{{ x.number }} <!-- Nothing displays. ->
{% if x.number == 1 %}
<p>Something</p>
{% endif %}
{% if x.number == 2 %}
<p>Something 2</p>
{% endif %}
{% if x.number == 0 %}
<p>Nothing</p>
{% endif %}
{% endfor %}
{% endfor %}
EDIT:
In database number filed is choices. How to replace {% if x.number == 0 %}? == None also does not work.
----
1
2
3
4

if the data has no value or 0, use not
{% if not x.number %}

If the avaialble choices are between 1-6, why do you check for x.number == 0? This will never occur.
If the user doesn't have any animalnumber the d.animalnumber_set.all will return None. So the control would be to check if x is empty
{% for d in data %}
{% for x in d.animalnumber_set.all %}
{% if x.number == 1 %}
<p>Something</p>
{% endif %}
{% if x.number == 2 %}
<p>Something 2</p>
{% endif %}
{% empty %}
<p>Nothing</p>
{% endfor %}
{% endfor %}

Related

Multiple django 'with' statements inside 'if' statement

I have a Django multiple 'with' statements inside 'if/elif' statement.
The blocks of code inside if/elif are the same except for one variable 'slide1_line2'.
I am wondering if there is a way to re-write code to avoid repetition.
{% if country == 'England' or country == 'Wales'%}
{% with graphic='map.png' %}
{% with classes='color-1' %}
{% with slide1_line1='Your constituency is '|add:name %}
{% with slide1_line2='Heading1' %}
{% with slide1_line3='text' %}
{% with icon='keyboard_arrow_down' %}
{% include 'slide_map.html' %}
{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}
{% elif country == 'Scotland' or country == 'Northern Ireland' %}
{% with graphic='map.png' %}
{% with classes='color-1' %}
{% with slide1_line1='Your constituency is '|add:name %}
{% with slide1_line2='Heading2' %}
{% with slide1_line3='text' %}
{% with icon='keyboard_arrow_down' %}
{% include 'slide_map.html' %}
{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}
{% endif %}
You can factor out the common values outside the if statement:
{% with graphic='map.png' classes='color-1' slide1_line1='Your constituency is '|add:name slide1_line3='text' icon='keyboard_arrow_down' %}
{% if country == 'England' or country == 'Wales' %}
{% include 'slide_map.html' with slide1_line2='Heading1' %}
{% else %}
{% include 'slide_map.html' with slide1_line2='Heading2' %}
{% endif %}
{% endwith %}
Note that:
you can define multiple variables in the same {% with … %} template tag [Django-doc]; and
the {% include … %} template tag [Django-doc] can have a {% include … with … %} clause to pass certain extra parameters.

How to do a FOR or loop that start on X and end Y index of a list on Django Template Languge?

For example i have a list of 10 objects but i just want to get last 5 or the first 5 objects.
{% for x in objects %}
.....first 5 objects......
{% endfor %}
{% for x in objects %}
.....last 5 objects......
{% endfor %}
First method (forloop.counter):
{% for x in objects %}
{% if forloop.counter <= 5 %}
access first 5 objects
{% else %}
access last 5 objects
{% endif %}
{% endfor %}
Second method:
# views.py
def my_view(request):
first_five_obj = MyModel.objects.all()[:5]
last_five_obj = MyModel.objects.all()[-5:]
return render(request, 'template.html', locals())
<!-- template.html -->
{% for x in first_five_obj %}
.....first 5 objects......
{% endfor %}
{% for x in last_five_obj %}
.....last 5 objects......
{% endfor %}
You could consider using a custom template tag.
Could loop through objects:
{% for x in objects %}
{% if forloop.counter <= 5 %}
# ....do something....
{% endif %}
{% endfor %}
{% for x in objects %}
{% if forloop.revcounter <= 5 %}
# ....do something....
{% endif %}
{% endfor %}
You could get the items directly (Assuming the length of objects doesn't change when displaying last 5 in list.):
{{ objects.0 }}
{{ objects.1 }}
{{ objects.2 }}
...
{{ objects.7 }}
{{ objects.8 }}
{{ objects.9 }}

How do I implement a recursive and extensible Twig template?

I'm implementing a simple website menu, but this time I'm using Twig as my template language. The depth of the menu tree is one or greater. Here's my Twig code so far (sanitized and simplified):
{# file menu1.html.twig #}
<ul>
{% import _self as renderer %}
{% for item in menu.items %}
{{ renderer.renderItem(item) }}
{% endfor %}
</ul>
{% macro renderItem(item) %}
{% block itemtag %}
<li>
{% endblock %}
{{ item.name }}
{% if item.hasItems() %}
<ul>
{% import _self as renderer %}
{% for subitem in item.items %}
{{ renderer.renderItem(subitem) }}
{% endfor %}
</ul>
{% endif %}
</li>
{% endmacro %}
Now I need to override the "itemtag" element in another template:
{# file menu2.html.twig #}
{% extends "menu1.html.twig" %}
{% block itemtag %}
<li data-foo="bar">
{% endblock %}
This will not work, as explained very well here: https://stackoverflow.com/a/26650103/220817
So how do I write a Twig template that can traverse and render a tree structure, and still allow extending templates to override certain elements in the rendered markup?
You need to use macro's if you want to do something recursive as macro's can self import themself. Here is an example of a recursive macro:
{% macro menu(m, class, currentLevel, maxLevel) %}
{%if not class is defined %}
{% set class = '' %}
{% endif %}
{%if not currentLevel is defined or currentLevel is null %}
{% set currentLevel = 1 %}
{% endif %}
{%if m is iterable%}
{% set links = m %}
{% else %}
{% set links = m.getLinks() %}
{% if m.showRoot() and m.hasRoot() %}
<li class="root{%if class != ''%} {{class}}{%endif%}">
<a href="{%if m.getRoot().getTreeLeft() > 1 %}{{ m.getRoot().getRoute() }}{% else %}#site_url#{% endif %}" {% if m.getRoot().PageId in selected_page_ids %} class="selected"{% endif %}>{{ m.getRoot().name }}</a>
</li>
{% endif %}
{% if maxLevel is null %}{% set maxLevel = m.getLevel() %}{% endif %}
{% endif %}
{% if not links is empty %}
{% for link in links %}
{% if link['selected'] is defined and link['selected'] %}
{% set is_selected = true %}
{% else %}
{% set is_selected = false %}
{% endif %}
{% set anchor_class = '' %}
{% if link.PageId in selected_page_ids or is_selected %}
{% set anchor_class='selected' %}
{% endif %}
{% if method_exists(link, 'getPageCssClass') and link.getPageCssClass() != null %}
{% set class= class~' '~link.getPageCssClass().getTitle() %}
{% endif %}
<li{%if (class|trim) != '' %} class="{{ (class|trim) }}"{% endif %}>
<a href="{{ link.getRoute }}"{%if (anchor_class|trim) != '' %} class="{{ (anchor_class|trim) }}" {% endif %} {% if link.PageId > 0 %}data-page-id="{{ link.PageId }}"{% endif %}>{{ link.name }}</a>
{% if link.hasPublicChildren and currentLevel < maxLevel %}
<ul>
{{ _self.menu(link.getPublicChildren, 'sec', (currentLevel+1), maxLevel) }}
</ul>
{% endif %}
</li>
{% endfor %}
{% endif %}
{% endmacro %}

Multiple condition When statement in Big Cartel

I am trying to make a multiple condition statement on Big Cartel and I keep getting an error telling me that there is an unknown tag in my When statement. I feel like this is very simple. What am I doing wrong? Thank you for looking.
{% case product.status %}
{% when 'sold-out' %}
{% if product.id = '25027747' %}
RESULT 1
{% else %}
{% if product.id = '25027993' %}
RESULT 2
{% else %}
{% endif %}
You'll want to use this code:
{% case product.status %}
{% when 'sold-out' %}
{% if product.id = '25027747' %}
RESULT 1
{% elsif product.id = '25027993' %}
RESULT 2
{% endif %}
{% endcase %}

Django loop – remove last comma

I have the following loop set up, but need to remove the comma on the last item (it's to replicate a JSON array for cycle2)
{% for product_in_series in series.get_products %}{%spaceless%}
{% with product_in_series.product as product %}
{%if not forloop.first%}
"<img src='{% version product.get_overview 'page_image' %}'>",
{%endif%}
{% endwith %}
{%endspaceless%}{% endfor %}
Cheers,
R
What about this?
{% for product_in_series in series.get_products %}{%spaceless%}
{% with product_in_series.product as product %}
{%if not forloop.first%}
"<img src='{% version product.get_overview 'page_image' %}'>"
{%if not forloop.last%},{%endif%}
{%endif%}
{% endwith %}
{%endspaceless%}{% endfor %}
{{ forloop.last|yesno:",,"|safe }}
, - is a comma
None of the above works for me.
The correct syntax, as in Django 3.0, is as such
{% with querythisandthat as A %}
{% for u in A %} {{ u.interesting_stuff }}
{% if u == A.last %} . {% else %} ; {% endif %}
{% endfor %}
{% endwith %}
The reason is that A.last is not True/False, but it is the last element of the queryset
https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django.db.models.query.QuerySet.first