[Django]-How to access a dictionary element in a Django template?

68๐Ÿ‘

โœ…

To echo / extend upon Jeffโ€™s comment, what I think you should aim for is simply a property in your Choice class that calculates the number of votes associated with that object:

class Choice(models.Model):
    text = models.CharField(max_length=200)

    def calculateVotes(self):
        return Vote.objects.filter(choice=self).count()

    votes = property(calculateVotes)

And then in your template, you can do:

{% for choice in choices %}
    {{choice.choice}} - {{choice.votes}} <br />
{% endfor %}

The template tag, is IMHO a bit overkill for this solution, but itโ€™s not a terrible solution either. The goal of templates in Django is to insulate you from code in your templates and vice-versa.

Iโ€™d try the above method and see what SQL the ORM generates as Iโ€™m not sure off the top of my head if it will pre-cache the properties and just create a subselect for the property or if it will iteratively / on-demand run the query to calculate vote count. But if it generates atrocious queries, you could always populate the property in your view with data youโ€™ve collected yourself.

๐Ÿ‘คJohn Ewart

351๐Ÿ‘

choices = {'key1':'val1', 'key2':'val2'}

Hereโ€™s the template:

<ul>
{% for key, value in choices.items %} 
  <li>{{key}} - {{value}}</li>
{% endfor %}
</ul>

Basically, .items is a Django keyword that splits a dictionary into a list of (key, value) pairs, much like the Python method .items(). This enables iteration over a dictionary in a Django template.

๐Ÿ‘คrussian_spy

230๐Ÿ‘

you can use the dot notation:

Dot lookups can be summarized like
this: when the template system
encounters a dot in a variable name,
it tries the following lookups, in
this order:

  • Dictionary lookup (e.g., foo[โ€œbarโ€])
  • Attribute lookup (e.g., foo.bar)
  • Method call (e.g., foo.bar())
  • List-index lookup (e.g., foo[2])

The system uses the first lookup type
that works. Itโ€™s short-circuit logic.

๐Ÿ‘คWilhelm

39๐Ÿ‘

You need to find (or define) a โ€˜getโ€™ template tag, for example, here.

The tag definition:

@register.filter
def hash(h, key):
    return h[key]

And itโ€™s used like:

{% for o in objects %}
  <li>{{ dictionary|hash:o.id }}</li>
{% endfor %}
๐Ÿ‘คNed Batchelder

10๐Ÿ‘

django_template_filter
filter name get_value_from_dict

{{ your_dict|get_value_from_dict:your_key }}
๐Ÿ‘คNick Korolkov

8๐Ÿ‘

Similar to the answer by @russian_spy :

<ul>
{% for choice in choices.items %} 
  <li>{{choice.0}} - {{choice.1}}</li>
{% endfor %}
</ul>

This might be suitable for breaking down more complex dictionaries.

๐Ÿ‘คAdam Starrh

4๐Ÿ‘

Could find nothing simpler and better than this solution. Also see the doc.

@register.filter
def dictitem(dictionary, key):
    return dictionary.get(key)

But thereโ€™s a problem (also discussed here) that the returned item is an object and I need to reference a field of this object. Expressions like {{ (schema_dict|dictitem:schema_code).name }} are not supported, so the only solution I found was:

{% with schema=schema_dict|dictitem:schema_code %}
    <p>Selected schema: {{ schema.name }}</p>
{% endwith %}

UPDATE:

@register.filter
def member(obj, name):
    return getattr(obj, name, None)

So no need for a with tag:

{{ schema_dict|dictitem:schema_code|member:'name' }}
๐Ÿ‘คNick Legend

3๐Ÿ‘

Ideally, you would create a method on the choice object that found itself in votes, or create a relationship between the models. A template tag that performed the dictionary lookup would work, too.

๐Ÿ‘คJeff Ober

-4๐Ÿ‘

You could use a namedtuple instead of a dict. This is a shorthand for using a data class. Instead of

person = {'name':  'John', 'age':  14}

โ€ฆdo:

from collections import namedtuple
Person = namedtuple('person', ['name', 'age'])
p = Person(name='John', age=14)
p.name # 'John'

This is the same as writing a class that just holds data. In general I would avoid using dicts in django templates because they are awkward.

๐Ÿ‘คAaron

Leave a comment