Thursday, January 12, 2017

Django - 024 - Context Variable Lookup

In the examples so far, we have passed simple values in the contexts - mostly strings, plus a datetime.date example. However, the template system elegantly handles more complex data structures, such as lists, dictionaries and custom objects. The key to traversing complex data structures in Django templates is the dot character ("."):

Use a dot to access dictionary keys, attributes, methods, or indices of an object. This is best illustrated with a few examples. For instance, suppose you are passing a Python dictionary to a template. To access the values of that dictionary by dictionary key, use a dot:

 $ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> person = {'name': 'Lakshmi', 'age':32}
>>> t = Template('{{person.name}} is {{person.age}} years old.')
>>> c = Context({'person':person})
>>> print t.render(c)
Lakshmi is 32 years old.
>>>

Similarly, dots also allow access to object attributes. For example, a Python datetime.date  object has year, month and day attributes, and you can use a dot to access those attributes in a Django template:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(2014,4,1)
>>> d.year
2014
>>> d.month
4
>>> d.day
1
>>> t = Template('The month is {{date.month}} and the year is {{date.year}}.')
>>> c = Context({'date':d})
>>> t.render(c)
The month is 4 and the year is 2014.
>>> 

This example uses a custom class, demonstrating that variable dots also allow attribute access on arbitrary objects:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> class Person(object):
...    def __init__(self, first_name, last_name):
...        self.first_name, self.last_name = first_name, last_name
...
>>> t = Template('Hello, {{person.first_name}} {{person.last_name}}.')
>>> c = Context({'person':Person('Sandhya','Kulkarni')})
>>> print t.render(c)
Hello, Sandhya Kulkarni.
>>> 

Dots can also refer to methods of objects. For example, each Python string has the methods upper() and isdigit() , and you can call those in Django templates using the same dot syntax:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> t = Template('{{var}} -- {{var.upper}}  -- {{var.isdigit}}')    
>>> t.render(Context({'var':'123'}))
u'123 -- 123  -- True'
>>>

Note that you do not include parenthesis in the method calls. Also, it is not possible to pass arguments to the methods; you can only call methods that have no required arguments. 

Finally, dots are also used to access list indices, for example:
$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> t = Template('Item 2 is {{items.2}}.')
>>> c = Context({'items':['apples','bananas','carrots']})
>>> print t.render(c)
Item 2 is carrots.
>>>
Negative list indices are not allowed. For example, the template variable

{{items.-1}} would cause a TemplateSyntaxError.

Python Lists
A reminder, Python lists have 0-based indices. The first item is at index 0, the second is at index 1, and so on.
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 (for example, foo["bar"])
  • Attribute Lookup (for example, foo.bar)
  • Method Call (for example, foo.bar())
  • List-index lookup (for example, foo[2])

The system uses the first lookup type that works. It is short-circuit logic. Dot lookups can be nested multiple levels deep. For instance, the following example uses {{person.name.upper}} , which translates into a dictionary lookup (person['name']) and then a method call (upper()):

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> person = {'name':'Sandhya','age':'32'}
>>> t = Template('{{ person.name.upper }} is {{person.age}} years old.')
>>> c = Context({'person':person})
>>> print t.render(c)
SANDHYA is 32 years old.


No comments:

Post a Comment