Breaking out of a for loop from a nested if statement in Django - django

is there a way to break out of this for loop from inside the if statement. Currently our database is incorrectly storing multiple primary phones and I would like to break out of the for loop after the first primary phone is found. Thank you in advance for any help.
{% for phone in user_phones %}
{% if phone.primary %}
<div>{% if phone.type %}{{ phone.type|title }}: {% endif %}<span itemprop="telephone">{{ phone.phone_format }}</span></div>
{% endif %}
{% endfor %}
Updated:
Or just fail the if condition by creating a variable within the if true branch

If you have to stay within the template layer you could use regroup.
{% regroup user_phones|dictsort:"primary" by primary as phones_list %}
{% for phone in phones_list %}
{% if phone.grouper %}
{{ phone.list.0.type }}
{% endif %}
{% endfor %}
What it does
regroup together with the dictsort filter (which also works on querysets) groups the instances in user_phones by the value of primary.
regroup will add an attribute named grouper, which when grouping by a bool (the value of primary) will either be True or False.
for then iterates over the variable phones_list, which is provided by regroup. Since we have sorted the results by primary, {% if phone.grouper %} will tell us when we hit the group of items with primary == True.
regroup packs the items that belong to a group into the attribute list. So the first item can be accessed with phone.list.0.type, phone.list.0.phone_format, etc.
Note:
if you need to access foo.list.0 many times it can be assigned to a variable (using with):
{% regroup user_phones|dictsort:"primary" by primary as phones_list %}
{% for items in phones_list %}
{% if items.grouper %}
{% with items.list.0 as phone %}
<div>{% if phone.type %}{{ phone.type|title }}: {% endif %}<span itemprop="telephone">{{ phone.phone_format }}</span></div>
{% endwith %}
{% endif %}
{% endfor %}

There is no break in Django templates. You may handle it in your view by storing the primary phone that you are looking for to a variable and then calling it in your template.

Related

How we identify repeat value of variable in django templates

IN DJango cms template i want to display track name and course.
{% for c in courses %}
{% if c.domain|stringformat:"s" == d.domain_nm %}
{% if c.track != None %}
<h3>{{ c.track }}</h3>
{% endif %}
{{ c.course_nm }}
{% endif %}
{% endfor %}
here from courses table "c.track" is heading and course name in list when i add same track in course so it display twice .
Now,i suppose to do that same track name is there so don't print it's track name again
i think it has a way that we store {{ c.track }} in list and match current track value with previous track value if same so can't display it ,but the problem is we can't convert {{ c.track }} variable in list in template in django
Is there any another way for do that?
pls help !!!!
Thanks in adcvance!!!
This is what the ifchanged tag does.
{% ifchanged c.track %}
<h3>{{ c.track }}</h3>
{% endifchanged %}

Django Templates: how flexible are variables?

I need to have a variable in a teplate that is basically a counter for a for-loop. The problem is: I need to manipulate it, depending on the for-element I am dealing with, I will have to reset the counter (an IF inside the for-loop).
Is this doable inside a Django template?
This is basically what I would like:
{% i = 0 %}
{% for l in list %}
{% if i == 5 %}
{% i = 0 %}
Do Something
<br>
{% else %}
{% i = i + 1 %}
{% endif %}
{% endfor %}
You can't with the builtin tags:
http://www.mail-archive.com/django-users#googlegroups.com/msg27399.html
The following snippets might be a good starting point:
Template counters
Access by index
EDIT: For the record, OP needed a conditional with divisibleby. See the accepted answer here plus the comments in this answer.
What you want is the forloop.counter variable that Django's template language provides.
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
You would do something like:
{% for element in list %}
{% if forloop.counter > 5 %}
Do something
{% else %}
Do something else
{% endif %}
{% endfor %}
If you want to do something cyclically, you're basically doing a modulo operator (http://en.wikipedia.org/wiki/Modulo_operation), unfortunately, Django Template doesn't quite have this, but it does allow a 'divisible by' operator.
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#divisibleby
So you'll add:
{% if {{ forloop.counter|divisibleby:"5" }} %}
{{ whatever }}
{% endif %}

Django template: check for empty query set

Is there a way to check for an empty query set in the Django template? In the example below, I only want the NOTES header to be displayed if there are notes.
If I put an {% empty %} inside the "for" then it does display whatever is inside the empty tag, so it knows it's empty.
I'm hoping for something that does not involve running the query twice.
{% if notes - want something here that works %}
NOTES:
{% for note in notes %}
{{note.text}}
{% endfor %}
{% endif %}
Clarification: the above example "if notes" does not work - it still displays the header even with an empty query set.
Here's a simplified version of the view
sql = "select * from app_notes, app_trips where"
notes = trip_notes.objects.raw(sql,(user_id,))
return render_to_response(template, {"notes":notes},context_instance=RequestContext(request))
Edit: the view select selects from multiple tables.
Have a look at the {% empty %} tag.
Example from the documentation
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>
Link: https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#for-empty
If you are interested in a table, or some kind of heading if there are results, add the forloop.first:
{% for athlete in athlete_list %}
{% if forloop.first %}
Athlete Name:
{% endif %}
{{ athlete.name }}
{% empty %}
Sorry, no athletes in this list.
{% endfor %}
Try {% if notes.all %}. It works for me.
In your view check whether notes is empty or not. If it is then you pass None instead:
{"notes": None}
In your template you use {% if notes %} as normal.
It's unfortunate that you're stuck using a raw query set - they're missing a lot of useful behavior.
You could convert the raw query set into a list in the view:
notes_as_list = list(notes)
return render_to_response(template, {"notes":notes_as_list},context_instance=RequestContext(request))
Then check it as a boolean in the template:
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
You could also make it happen without conversions using forloop.first:
{% for note in notes %}
{% if forloop.first %}
Header
{% endif %}
{{ note.text }}
{% endfor %}
What about:
{% if notes != None %}
{% if notes %}
NOTES:
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
{% else %}
NO NOTES AT ALL
{% endif %}
Your original solution
{% if notes %}
Header
{% for note in notes %}
{{ note.text }}
{% endfor %}
{% endif %}
Works now with Django 1.7 and thanks to QuerySet caching, it does not cost and extra query.
Often the right way to do this is to use the {% with ... %} tag. This caches the query so it runs only once and also gives you more flexibility with your markup than using {% empty %}.
{% with notes as my_notes %}
{% if my_notes %}
<ul>
{% for note in my_notes %}
<li>{{ note }}</li>
{% endfor %}
</ul>
{% else %}
<p>Sorry, no notes available</p>
{% endif %}
{% endwith %}
With this particular example I'm not sure how useful it is but if you're querying Many-to-Many field, for instance, it's likely what you want to do.
Use {% empty %} in django templates
{% if list_data %}
{% for data in list_data %}
{{ data.field_1 }}
{% endfor %}
{% else %}
<p>No data found!</p>
{% endif %}
We can write above code with {% empty %}.
{% for data in list_data %}
{{ data.field_1 }}
{% empty %}
<p>No data found!</p>
{% endfor %}

django addition

how to increment value of a variable in a template..??
{% for s in list%}
{% for subject in s%}
{% for sub in subject %}
<div id="{{ sub| getid:i }}"></div>
# here i want to increment the value of i
{% endfor %}
{% endfor %}
{% endfor %}
If you want to increase i over all nested loops, you can pass another stateful context variable, such as i=itertools.count(), and in the template, you use
<div id="{{ sub| getid:i.next }}"></div>
The Django documentation on the template language design states the philosophy of the template language is that
the template system is meant to express presentation, not program logic.
And this often means you cannot manipulate state directly with filters. To achieve state changes, you will have to create your own stateful variables whose state can be altered via a function call.
Using a template for loop? You may try this using:
forloop.counter
see the docs here: http://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs
Implementation:
{% for s in list%}
{% for subject in s%}
{% for sub in subject %}
<div id="{{ sub| getid:forloop.counter+(forloop.parentloop.counter - 1)*total_iterations_inner_loop+(forloop.parentloop.parentloop.counter-1)*total_iterations_mid_loop*total_iterations_inner_loop }}"></div>
{% endfor %}
{% endfor %}
{% endfor %}
check out http://docs.djangoproject.com/en/dev/ref/templates/builtins/#add

Is there any way to reuse template tag value in Django templates?

For example, let's say there is a custom template tag
{% custom_tag "parameter" %}
This tag requires some serious database work to calculate.
Now I need to have something like that (pseudocode):
if {% custom_tag "parameter" %}
....
else
....
I know that with context variables I can do just:
{% with variable.x.y.z as v %}
{% if v %}
Blah-Blah-Blah {{ v }}
{% else %}
No value
{% endif %}
{% endwith %}
But is there any way do achieve this with template tag value?
EDIT:
The only option I've came up with so far is to make a filter out of my template tag:
{% if "parameter" | custom_tag %}
Blah {{ "parameter" | custom_tag }}
{% else %}
....
{% endif %}
But this option makes custom_tag execute twice, and that's not good performance-wise
i haven't test it but i guess that you can add a variable to the context from your custom tag.. maybe this will help you
http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#setting-a-variable-in-the-context
I believe you can assign the results of filtering to a variable and use it. This way the filter will only get called once. From the docs: with: Caches a complex variable under a simpler name. This is useful when accessing an "expensive" method (e.g., one that hits the database) multiple times.
{% with "parameter" | custom_tag as result %}
{% if result %}
Blah {{ result }}
{% else %}
....
{% endif %}
{% endwith %}