views:

239

answers:

3

This seems silly, but I don't understand how Django Templates access nested data in Contexts. I can access the values of dictionaries nested in the context data structure with the . notation -- {{ aDictionary.i_am_a_key }} works fine. But if I try to iterate over a list of keys and get their value from that same dictionary, I get nothing. So

{% for key in keys_list %}{{ aDictionary.key }}{% endfor}}

just generates blanks.

What am I missing here? Does Django not support key access to context dictionaries on the fly? Do I need to write a custom tag to do this?

EDIT

My examples assume these data structures:

aDictionary = {'i_am_a_key': 'all good', 'i_am_another_key': 'okay'}
keys_list = ['i_am_a_key', 'i_am_another_key']
+2  A: 

It's not the same question, but the answer is similar to #844746.

You end up with a filter which you can do...

{% load getattribute %}
{% for key in keys_list %}
    {{ aDictionary|attr:key }}
{% endfor %}
T. Stone
Saw that. I'd prefer to avoid writing a custom tag.
chernevik
Meh. If you're that averse to custom tags/filters, you'd better switch to Jinja. Writing custom tags and filters is how you make the Django template language fit your needs.
Carl Meyer
You're probably right, but I'm balancing "learn new tools / find most elegant solution" against "get stuff done".
chernevik
+4  A: 

This is a fundamental limitation of the Django templating language.

Three solutions:

  1. Use {% for key,value in foo.items %} to get key and value.
  2. Use Jinja2 -- an almost Django-like templating system.
  3. User the expr djangosnippet to do the access math.
Peter Rowell
So the templating can't access the dictionary by key on-the-fly? I think Django's great, but I could wish that limitation were more clearly documented.
chernevik
Short answer: No. The explanation is that it is a deliberately restrictive programming language so that "template designers" don't ... something. Personally, I've never met a "template designer," just programmers who have to do the template programming because the actual designers can't handle nested includes, for loops, etc. It does tend to force you to keep business logic out of the templates. I recommend options 2 or 3 above. Jinja2 gives you all of Python, and the expr tag does much the same thing within Django's template tag framework.
Peter Rowell
Thanks. I'm probably going to go with brianz's approach -- select the data I need and put in an object, then pass that to the template, rather than try to select the data items in the template. I suppose it's kludgier, but should serve, and won't be that hard to read.
chernevik
+1  A: 

This is a different approach, but based on what you want to accomplish this is the angle I'd take.

If you want to keep a subset of some dictionary and you want to iterate around it's values in some ordered fashion, I'd copy the element you're interested in into a SortedDict (django/utils/datastructures.py).

In my mind, stuff like this should live in the view (all of this is untested):

sorted_dict = SortedDict()
for key in orig_dict:
    if interested(key):
        sorted_dict[key] = orig_dict[val]

and the templates should just be very dumb:

{% for key, val in sorted_dict.items %}{{ val }}{% endfor}}
brianz
Thanks. I'm probably going to use this to solve the problem at hand.
chernevik