Reference list item by index within Django template? - python

This may be simple, but I looked around and couldn't find an answer. What's the best way to reference a single item in a list from a Django template?
In other words, how do I do the equivalent of {{ data[0] }} within the template language?

It looks like {{ data.0 }}. See Variables and lookups.

A better way: custom template filter: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/
such as get my_list[x] in templates:
in template
{% load index %}
{{ my_list|index:x }}
templatetags/index.py
from django import template
register = template.Library()
#register.filter
def index(indexable, i):
return indexable[i]
if my_list = [['a','b','c'], ['d','e','f']], you can use {{ my_list|index:x|index:y }} in template to get my_list[x][y]
It works fine with "for"
{{ my_list|index:forloop.counter0 }}
Tested and works well ^_^

{{ data.0 }} should work.
Let's say you wrote data.obj django tries data.obj and data.obj(). If they don't work it tries data["obj"]. In your case data[0] can be written as {{ data.0 }}. But I recommend you to pull data[0] in the view and send it as separate variable.

#jennifer06262016, you can definitely add another filter to return the objects inside a django Queryset.
#register.filter
def get_item(Queryset):
return Queryset.your_item_key
In that case, you would type something like this {{ Queryset|index:x|get_item }} into your template to access some dictionary object. It works for me.

Related

Django template language unpacking a dict

I have a dictionary passed (as part of another object) to the django template language.
The object, called 'poll' has attributes self.text and self.votes, where the former is a string, and the latter is a dict.
The dict, looks like this:
{'a1': 45.92422502870264, 'a2': 53.50172215843857}
I am trying to list each label, with its accompanying number, using the following:
{% for l, x in poll.votes %}
<p>{{ l }} {{ x }}</p>
{% endfor %}
Django responds with
Exception Type: ValueError
Exception Value: Need 2 values to unpack in for loop; got 3.
I tried .iteritems - The docs explain that .iteritems is not the correct way to do this, but they don't explain what the correct way is.
You just iterate the same way you would in python, but in Djangos templating language (DTL) syntax
{% for key, value in dictionary.items %}
Your poll.votes is a dict but you're not iterating the items but the keys in your code.
You can find an overview of jinja here. Its worth noting that jinja isn't what django uses but its handy for a condensed reference since many things are the same (jinja is based upon DTL) instead of digging through djangos docs.
For Djangos tempaltes heres the documentation reference
you too can do this:
{% for variable in poll %}
{{ variable.name }} - {{ variable.votes }}
{% endfor %}

How to get the number of form fields in a django template?

I have a django form that I can iterate over, for example, through a for loop:
{% for field in form %}
...
{% endfor %}
Now I'm trying to find out the total number form fields outside of the for loop. I have tried the following, but it just returns 0, even though I have 2 form fields:
{{ form|length }}
Is there any way to do this?
PS: This is in the context of django-cms 3.1.3, if this helps.
You'll need to explicitly count the fields, rather than just the form itself, such as:
{{ form.fields|length }}
As seen in the Django form documentation
Try this :
{{ form.hidden_fields|length + form.visible_fields|length }}

Can I access specific key values in dictionary from django template?

Is there any get() function for this instead?
{% for key, value in choices.items %}
<li>{{key}} - {{value}}</li>
{% endfor %}
From python I have the get() function to get values from a specific key. But I couldn't find a corresponding way to do that with django template tags. So I wonder is it possible?
I need to get specific values since using loops adds a lot of new lines in the html source.
Or should take care of the output inside the view before sending it out to the template, which method is better?
You can use {{ choices.items.key }} to access a specific dict element.
There is no reason to care about whitespace in the HTML code though; the typical end-user has no real business in reading it and if he's curious he an always use a DOM viewer or run it through a HTML beautifier.
If you want a specific value, just add it to the dotted-path:
{{ choices.items.somekey }}
will get you the value of choices.items['somekey'] if choices.items is a dict.
I think you are way advance now, just to share my point. you could do this way as well
{% for value in dict %}
{{value}}
{% endfor %}
or with key, value like
{% for key,value in dict.items %}
{{key}} : {{ value }}
{% endfor %}
If choices type is DICT like {}.
{{choices.somekey|default:""}}
If choices.items is DICT type.
{{choices.items.somekey|default:""}}
Try See little example.
# In Views.py
def dict_test(request):
my_little_dict = {"hi": "Hello"}
....
# in Template
{{my_little_dict.hi}}
You can specify as {{ choices.key_name }}
It worked for me. Just simple
{{ choices.values }}
This gives you a list of all the values in the dictionary at once.

Accessing individual objects in a Django template file

I am editing a template to display an attribute of the first member in a list. I am trying to access it like so:
{{ food_list.index(0).id }}
I get an error that says Could not parse the remainder: '(0).id'.
What is the correct way to access an individual member in a list?
{{ food_list.0.id }}
Alternatively,
{% with f=food_list|first %}
{{ f.id }}
{% endwith %}
You can't call methods in a template. Either write a template tag for this, or do it in your view. If what you wanted to do was just index the list, then you don't use the index() method for that; just use normal dot notation instead.

zip(list1, list2) in Jinja2?

I'm doing code generation in Jinja2 and I frequently want to iterate through two lists together (i.e. variables names and types), is there a simple way to do this or do I need to just pass a pre-zipped list? I was unable to find such a function in the docs or googling.
Modify the jinja2.Environment global namespace itself if you see fit.
import jinja2
env = jinja2.Environment()
env.globals.update(zip=zip)
# use env to load template(s)
This may be helpful in separating view (template) logic from application logic, but it enables the reverse as well. #separationofconcerns
Since you didn't mention if you are using Flask or not I figured I'd add my findings.
To be used by a render_template() create the 'zip' filter using the zip() function in the Jinja2 environment used by Flask.
app = Flask(__name__)
...
app.jinja_env.filters['zip'] = zip
To use this within a template do it like this:
{% for value1, value2 in iterable1|zip(iterable2) %}
{{ value1 }} is paired with {{ value2 }}
{% endfor %}
Keep in mind that strings are iterable Jinja2 so if you try to zip to strings you'll get some crazy stuff. To make sure what you want to zip is iterable and not a string do this:
{% if iterable1 is iterable and iterable1 is not string
and iterable2 is iterable and iterable2 is not string %}
{% for value1, value2 in iterable1|zip(iterable2) %}
{{ value1 }} is paired with {{ value2 }}
{% endfor %}
{% else %}
{{ iterable1 }} is paired with {{ iterable2 }}
{% endif %}
For Flask, you can pass the zip in the render_template()
return render_template("home.html", zip=zip)
I don't think templating languages allow doing zip of two containers over for loop. Here is a similar question for django and jinja templating is very close to django's.
You would have prebuild zipped container and pass to your template.
>> for i,j in zip(range(10),range(20,30)):
... print i,j
...
Is equivalent to
>>> [(i,j) for i,j in zip(range(10),range(20,30))]

Categories