Get the first element in the for loops in the Django template - django

Template:
{% for code in group_codes %}
*_{{ code.build }}_*<br />
{% if test_info.test_type = 0 %}
{{ code.pre_testing_fail }}/{{ code.pre_testing_total }} failed pre-test<br />
{% else %}
{% for shelf in final_shelf_info %}
{{ shelf.build }} <br/>
{% if shelf.build = code.build %}
{{ mr_script_count_func }}/{{ code.script_total }}
<span>MR</span> failed during script<br />
{{gw_script_count_func}}/{{ code.script_total }}
<span>GW</span> failed during script<br />
{{ mr_post_count_func }}/{{ code.post_testing_total }}
MR failed during post-test<br/>
{{ gw_post_count_func }}/{{ code.post_testing_total }}
GW failed during post-test<br/>
{% endif %}
{% endfor %}
<br/>
<br/>
{% endif %}
{% endfor %}
View
def final_shelf_info(self):
shelves = self.bugs_stbs()
shelfList = list()
for shelf in shelves:
shelfList.append(shelf.results_stb_id)
final_info = ResultsStbs.objects.select_related(
'build',
'pre_testing_result',
'script_result',
'post_result',
).filter(
results_stb_id__in=shelfList,
tr_test_case_id=self.kwargs['trTestCaseID'],
).order_by(
'pair_no','shelf_no',
)
for info in final_info:
if info.stb_hw_info_ids:
info.stb_type = info.stb_hw_info_ids.stb_hw_info.stb_type
else:
info.stb_type = None
return final_info
I would like to get the first element in the for loop
{% for shelf in final_shelf_info %}
and compare with another data.
How can I get the first element in the first loop.
First element : Q004.01.55.01.55.19_9423
{{ shelf[0].build }} I tried like that, it did not work.
The output of the for loop:
1234.xx.xx.xx.xx.xx
Any helps would be appreciated.

{% for shelf in final_shelf_info %}
{% if forloop.first %}
Do something with {{ shelf }} since its the first item iterated
{% endif %}
{% endfor %}
More on the {% for %} template loop in the docs.

You could do something like this:
{% for t in things %}
{% if forloop.first %}
// do something
{% endif %}
// do stuff
{% if forloop.last or things.count == 1 %}
// do something
{% endif %}
{% endfor %}
More documentation is available at Django documentation

{% if final_shelf_info.0 == shelf %}
or
{% if final_shelf_info.first == shelf %}

Related

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 %}

How can i check if values of models are the same in django loop?

I've a loop:
{% for addimg in post.addimg_set.all %}
<p>
{{ addimg.execution }}<br>
{{ addimg.width }} cm x {{ addimg.height }} cm<br>
{{ addimg.year }}
</p>
{% endfor %}
I want to display some data as long as they are different. If they are equal i want it only to display once like:
{% if addimg.execution == addimg.execution %}
{{ addimg.execution }}<br>
{% endif %}
forgive me my python/django still young.
Any suggestions?
You may find your answer in documentation.
Check this out:
https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#ifchanged
I think you are looking for the {% ifchanged %} template tag.
{% ifchanged addimg.execution %}
{{ addimg.execution }}<br>
{% endifchanged %}

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

Why doesn't django like my dictionary?

I'm new to django, and desperately trying to figure out why I can't get a set of dictionary objects to render. Here is a snippet of the template--with some pprints for debugging:
<ul>
{% with req.requirement_id as reqid %}
req.requirement_id: {{ req.requirement_id|pprint }}<br />
reqid: {{ reqid|pprint }}<br />
e_quals: {{ e_quals|pprint }}<br />
e_quals.reqid: {{ e_quals.reqid|pprint }}<br />
{% for qual in e_quals.reqid %}
qual.qual_type: {{ qual.qual_type }}
{% if qual.qual_type == "self" %}
<li>Only self-endorsements.</li>
{% endif %}
{% if qual.qual_type == "other" %}
<li>No self-endoresements.</li>
{% endif %}
{% if qual.qual_type == "hasa" %}
<li>Endorser must hold an active {{ qual.qual_data }} badge.</li>
{% endif %}
{% endfor %}
{% endwith %}
</ul>
And here is what I get as an output:
req.requirement_id: u'man_keephead'
reqid: u'man_keephead'
e_quals: {u'man_keephead': [<EndorsementQual: man_keephead_others>, <EndorsementQual: man_keephead_man>], u'man_trustself': [<EndorsementQual: man_trustself_self>], u'man_waiting': [<EndorsementQual: man_waiting_other>]}
e_quals.reqid: ''
I really seems like--given that reqid and that e_quals dictionary, e_quals.reqid should produce that list of objects. I'm not sure what I'm missing.
You can't do this sort of indirect variable resolution in Django's template language. It will always interpret e_quals.req_id as e_quals["req_id"] - ie as a literal key.
You'll need to create a simple template filter:
#register.filter
def dict_get(my_dict, key):
return my_dict.get(key)
{{ e_quals|dict_get:req_id }}

How do I check for last loop iteration in Django template?

I have a basic question, in the Django template language how can you tell if you are at the last loop iteration in a for loop?
You would use forloop.last. For example:
<ul>
{% for item in menu_items %}
<li{% if forloop.last %} class='last'{% endif %}>{{ item }}</li>
{% endfor %}
</ul>
{{ forloop.last }}
You can basically use this logic in a for loop:
{% if forloop.last %}
# Do something here
{% endif %}
For example, if you need to put a comma after each item except for the last one, you can use this snippet:
{% for item in item_list %}
{% if forloop.last %}
{{ item }}
{% else %}
{{ item }},
{% endif %}
{% endfor %}
which will become for a list with three items:
first_item, second_item, third_item