Search code examples
pythonflaskjinja2

Difference between dot notation and square brackets in Flask templates


What's the difference between using square brackets or dot notation in the Flask web framework? Both seem to work, for example:

In the Python script I can set session['username'] = 'Geraint'. I can then access it the template using {{ session['username'] }} or {{ session.username }}

What's the difference between the two? The docs seem to favour the dot notation so should that be used in all cases?


Solution

  • This is a feature of Jinja2, see the Variables section of the Template Designer documentation:

    You can use a dot (.) to access attributes of a variable in addition to the standard Python __getitem__ “subscript” syntax ([]).

    This is a convenience feature:

    For the sake of convenience, foo.bar in Jinja2 does the following things on the Python layer:

    • check for an attribute called bar on foo (getattr(foo, 'bar'))
    • if there is not, check for an item 'bar' in foo (foo.__getitem__('bar'))
    • if there is not, return an undefined object.

    foo['bar'] works mostly the same with a small difference in sequence:

    • check for an item 'bar' in foo. (foo.__getitem__('bar'))
    • if there is not, check for an attribute called bar on foo. (getattr(foo, 'bar'))
    • if there is not, return an undefined object.

    This is important if an object has an item and attribute with the same name. Additionally, the attr() filter only looks up attributes.

    So if you use the attribute access ({{ session.username }}) then Jinja2 will first look for the attribute, then for the key. Since the Flask session object is a dictionary, this means you could potentially end up with the wrong result; if you have stored data under the key get in the session, session.get returns a dictionary method, but session['get'] would return the actual value associated with the 'get' key.