Template Language for Django which does not silently fail on exception?

Viewed 258

I like django, the ORM, the admin, the community. But I don't like the handling of exception in the template language, like documented here: invalid template variables.

Is there an alternative template variable where I always get an exception if something is wrong (even in production)?

I prefer exceptions to "silently ignore errors".

1 Answers

One solution would be to change your template backend to jinja2 (which is supported "natively" by Django) following the documentation.

An in-depth explanation on how jinja2 django backend handles the undefined variable issue, can be found here (notation mine):

Invalid template variables

You can set various behaviors when an invalid variable is encountered in Jinja templates. Django sets Jinja with two default behaviors, one for when DEBUG=True -- a common setting in development -- and the other for when DEBUG=False -- a common setting in production.

If DEBUG=True and an invalid variable is set in a Jinja template, Jinja uses the jinja2.DebugUndefined class to process it. The jinja2.DebugUndefined class outputs the variable verbatim for rendering (e.g. if the template has the {{foo}} statement and the variable doesn't exist in the context, Jinja outputs {{foo}}, making it easier to spot an invalid variable).

If DEBUG=False and an invalid variable is set in a Jinja template, Jinja uses the jinja2.Undefined class to process it. The jinja2.Undefined class outputs a blank space in the position of the variable for rendering (e.g. if the template has the {{bar}} statement and the variable doesn't exist in the context, Jinja outputs a blank space). It's worth mentioning this last behavior aligns with the default behavior of invalid variables in Django templates.

In addition to the jinja2.DebugUndefined and jinja2.Undefined classes, Jinja also supports the jinja2.StrictUndefined class. The jinja2.StrictUndefined class is used to generate an immediate error instead of proceeding with rendering, which is helpful for quicker diagnosis of invalid variables. However, be aware this last class changes its behavior based on the DEBUG variable, it either generates a stack error with the invalid variable name (i.e. when DEBUG=True) or it generates a standard HTTP 500 error page (i.e. when DEBUG=False).

If you like to set the StrictUndefined option on your template you can use the following example from the same source:

Listing 4-4. Generate error for invalid variables in Jinja with jinja2.StrictUndefined

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))

import jinja2

TEMPLATES = [    
    { 
        'BACKEND':'django.template.backends.jinja2.Jinja2',
        'DIRS': ['%s/jinjatemplates/'% (PROJECT_DIR),],
        'APP_DIRS': True,
        'OPTIONS': {
            'undefined':jinja2.StrictUndefined
        },
    }            
]

As you can see in Listing 4-4, we first declare import jinja2 to gain access to Jinja's classes in settings.py. Next, we declare the undefined key inside the OPTIONS parameter and assign it the Jinja class to process invalid variables. In this case, we use the jinja2.StrictUndefined class to get errors when invalid templates variables are encountered, but you could equally use any of the other two Jinja classes to handle invalid variables (i.e. jinja2.DebugUndefined or jinja2.Undefined).

Finally, if you want to have a different behavior between DEBUG=True or DEBUG=False you can change the following in the TEMPLATES settings:

'OPTIONS': {
    'undefined': jinja2.DebugUndefined if DEBUG else jinja2.StrictUndefined
},

Utilizing jinja2's debugging option on development and strict options on production (raising errors as is mentioned in the question).

Related