[Fixed]-Make django templates strict

8👍

Django<=1.9

Set TEMPLATE_STRING_IF_INVALID = 'DEBUG WARNING: undefined template variable [%s] not found' in your settings.py.

See docs:
https://docs.djangoproject.com/en/1.9/ref/settings/#template-string-if-invalid

Django>=1.10

Set string_if_invalid = 'DEBUG WARNING: undefined template variable [%s] not found' template option in your settings.py.

See docs: https://docs.djangoproject.com/en/2.0/topics/templates/#module-django.template.backends.django

Also read:
http://docs.djangoproject.com/en/dev/ref/templates/api/#invalid-template-variables

👤seler

4👍

This hack from djangosnippets will raise an exception when an undefined variable is encountered in a template.

# settings.py
class InvalidVarException(object):
    def __mod__(self, missing):
        try:
            missing_str = unicode(missing)
        except:
            missing_str = 'Failed to create string representation'
        raise Exception('Unknown template variable %r %s' % (missing, missing_str))
    def __contains__(self, search):
        if search == '%s':
            return True
        return False

TEMPLATE_DEBUG = True
TEMPLATE_STRING_IF_INVALID = InvalidVarException()

1👍

Consider using the django-shouty-templates app: https://pypi.org/project/django-shouty-templates/

This app applies a monkeypatch which forces Django’s template language to error far more loudly about invalid assumptions. Specifically:

  • chef would raise an exception if the variable were called sous_chef.
  • chef.can_add_cakes would raise an exception if can_add_cakes was not a valid attribute/property/method of chef

It ain’t compile time safety, but it’s better than silently swallowing errors because you forgot something!

👤Kris

0👍

I use this pytest-django config:

[pytest]
FAIL_INVALID_TEMPLATE_VARS = True

This way I get an exception if I run the tests.

-2👍

That’s part of the design. It allows you to provide defaults and switch based on whether or not a variable exists in the context. It also allows templates to be very flexible and promotes re-usability of templates instead of a strict “each view must have it’s own template” approach.

More to the point, templates are not really supposed to be “debugged”. The idea is to put as much of your logic as possible outside the template, in the views or models. If you want to figure out why a variable that’s supposed to be passed to the context isn’t, the place to debug that is in your view. Just drop import pdb;pdb.set_trace() somewhere before your view returns and poke around.

Leave a comment