I have this array:
scores = [45.62, 51.87, 33.12, 39.37, 33.12]
I want to iterate through the list, and pass each item to an html template.
Using jinga, i tried the following:
{% for items in scores %}
{{ items }}
<br>
{% endfor %}
I hoped that the above would print out each item in the list like so:
45.62
51.87
33.12
etc...
but it didn't, it just prints the entire list, as a list, on one line.
I also tried this:
{% for items in scores %}
{{ scores.0 }}
<br>
{% endfor %}
This printed out just the first score of the list, but not the others. I want to print out each score individually. Please help! I'm using django 1.9. I know this is jinja, not sure if it's jinja2?
Feels like list is not as you put in question.Try this
{% for items in scores.0 %}
{{ items }}
<br>
{% endfor %}
Try changing up the variable names. Maybe you have another variable called items in your context. It would make more sense to use a variable name that's not plural for the loop.
{% for score in scores %}
{{ score }}
<br>
{% endfor %}
Related
I have a context dictionary entry objectives that maps objective query objects to a list of tests that belong to that objective. Example code:
objectives = Objective.objects.filter(requirement=requirement)
context_dict["requirements"][requirement] = objectives
for objective in objectives:
tests = Test.objects.filter(objective=objective)
context_dict["objectives"][objective] = tests
In my django html template, I iterate over objectives and display them. I then want to iterate over the tests that belong to these objectives. When I do this:
{% for test in {{ objectives|get_item:objective }} %}
I get a TemplateSyntaxError: 'for' statements should use the format 'for x in y':
In the application/templatetags directory, I have:
from django.template.defaulttags import register
...
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
If instead I make {{ objectives|get_item:objective }} a JS variable, I see that it does indeed produce a list, which I should be able to iterate over. Of course, I can't mix JS variables and the django template tags, so this is only for debugging:
var tests = {{ objectives|get_item:objective }}
var tests = [<Test: AT399_8_1>, <Test: AT399_8_2>, <Test: AT399_8_3>, <Test: AT399_8_4>, <Test: AT399_8_5> '...(remaining elements truncated)...']
How do I iterate over this list in the django template tag?
You cannot user {{...}} inside the {%...%}
What you can try is changing your filter to an assignment tag and using that value in the loop
#register.assignment_tag
def get_item(dictionary, key):
return dictionary.get(key)
And then in your template use it as
{% get_item objectives objective as tests %}
{% for test in test %}
....
{% endfor %}
Instead of all this if your models are proper with foreign keys I would do something like
{% for objective in requirement.objective_set.all %}
{% for test in objective.test_set.all %}
....
{% endfor %}
{% endfor %}
In my context I would pass only the requirement
You already have an answer, but note that dropping the {{ }} tags and keeping everything else the same would have worked fine.
{% for test in objectives|get_item:objective %}
**This is Right Answer for Using Django if else and for loop **
Note :- We Have to Put Key in " " string (Double quotes) some time produce an error so That is good way bcz i faced that problem whwn i Learned
{% if 'numbers'|length > 0 %}
{% for i in numbers %}
{% if i > 20 %}
{{i}}
{% endif %}
{% endfor %}
{% else %}
Empty
{% endif %}
I have a HTML template in django. It get's two variables: list of categories (queryset, as it it returned by .objects.all() function on model in django) and dictionary of contestants. As a key of the dictionary, I'm using id of category, and value is list of contestats.
I want to print name of the category and then all the contestants. Now I have this:
{% for category in categories_list %}
<h1>category.category_name</h1>
{% for contestant in contestants_dict[category.id] %}
{{ contestant }} </br>
{% endfor %}
{% endfor %}
However, when I run it, I get error:
TemplateSyntaxError at /olympiada/contestants/
Could not parse the remainder: '[category.id]' from 'contestants_dict[category.id]'
What I know so far is that I can't use index in template. I thought that {% something %} contains pure Python, but it shoved up it's just a tag. I know that I have to create my own simple_tag, but I don't know how. I read the docs Writing custom template tags, but there is such a little information and I wasn't able to fiqure out how to create (and mainly use in a for loop) a tag, that will take dict, key and return the value. What I tried is:
templatetags/custom_tags.py:
from django import template
register = template.Library()
#register.simple_tag
def list_index(a, b):
return a[b]
and in template:
{% for contestant in list_index contestants_dict category.id %}
But I get TemplateSyntaxError.
Could you please explain/show me how to create the tag, or is there a better way to do this?
Thanks.
//EDIT:
I managed to do it this way:
{% list_index contestants_list category.id as cont %}
{% for contestant in cont %}
it works, but it takes 2 lines and I need to create another variable. Is there any way to do it without it?
If you don't want 2 lines like that you should be able to use a filter i think
#register.filter
def list_index(a, b):
return a[b]
Then the usage like this
{% for contestant in contestants_dict|list_index:category.id %}
{{ contestant }} </br>
{% endfor %}
I have the following thing in a jinja2 for loop:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal' }) }}
I need to have an index on the data-target like:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-item' }) }}
item is the index needed in this case. Is there a way to escape item out of this "ad-hoc dictionary"? So that it takes on the same values as in meal[item]?
I need the 'data-target' attribute to render as '#myModal-0', '#myModal-1', etc.. As it stands each 'data-target' attribute gets set as '#myModal-item' for each item in the loop. In other words it sets item in the second line of code as a string.
In case it is ever helpful for someone, what wound up solving my problem was:
<form method="POST">
{{ meal[item]['open-modal'].csrf_token }}
{{ meal[item]['open-modal'].submit( **{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-' +
item|string } ) }}
</form>
Keep in mind that this is nested inside of two for loops in jinja2.
{% for meal in menu_dict %}
{% for item in meal %}
....
{% endfor %}
{% endfor %}
The point is summarized with this, basically:
'data-target':'#myModal-' + item|string
adds the postfix.
How can I break out of a for loop in jinja2?
my code is like this:
<a href="#">
{% for page in pages if page.tags['foo'] == bar %}
{{page.title}}
{% break %}
{% endfor %}
</a>
I have more than one page that has this condition and I want to end the loop, once the condition has been met.
You can't use break, you'd filter instead. From the Jinja2 documentation on {% for %}:
Unlike in Python it’s not possible to break or continue in a loop. You can however filter the sequence during iteration which allows you to skip items. The following example skips all the users which are hidden:
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
In your case, however, you appear to only need the first element; just filter and pick the first:
{{ (pages|selectattr('tags.foo', 'eq', bar)|first).title }}
This filters the list using the selectattr() filter, the result of which is passed to the first filter.
The selectattr() filter produces an iterator, so using first here will only iterate over the input up to the first matching element, and no further.
Break and Continue can be added to Jinja2 using the loop controls extension.
Jinja Loop Control
Just add the extension to the jinja environment.
jinja_env = Environment(extensions=['jinja2.ext.loopcontrols'])
as per sb32134 comment
But if you for some reason need a loop you can check the loop index inside for-loop block using "loop.first":
{% for dict in list_of_dict %}
{% for key, value in dict.items() if loop.first %}
<th>{{ key }}</th>
{% endfor %}
{% endfor %}
I am rather new to django templates and have an impression that I have not understood some basics.
I have a list of elements and I need to render an element of the list based on conditions against the the previous and the next elements (in case the following or the previous elements are hidden, I need to mark the current element as border element).
How can I reference the previous and the following elements within a for loop in Django templates?
You could write a custom template filter for next and previous:
def next(value, arg):
try:
return value[int(arg)+1]
except:
return None
and in the template:
{% for ... %}
{% with list|next:forloop.counter0 as next %}
{% if next.is_hidden %}
...
{% endif %}
{% endwith %}
{% endfor %}
but like others have said, there are probably more elegants solutions doing this via your view
You can't do this strictly with built-in template tags. You need to involve some Python.
One method would be to zip the list with itself:
new = ([(None, orig[0], orig[1])] +
zip(orig, orig[1:], orig[2:]) +
[(orig[-2], orig[-1], None)])
and pass that to the template, then loop over it like this:
{% for prev, current, next in new %}
{% if prev.hidden or next.hidden %}
BORDER
{% endif %}
{{ current }}
{% endfor %}
You really shouldn't use the Django templates for this kind of logic. You have your views to handle it. I would figure out which elements of the list are borders and pass in an extra parameter that I can handle in the template using a simple if statement. For example:
{% for element,is_border in data.items %}
{% if is_border %}
do something
{% endif %}
{% endfor %}
There are tons of similar ways you can do this. I presented just one example.
You can create an external tag which does that but django templating system which was build to be lightweight has no such feature in for loops.