14

In a django template, a call to {{ var }} will silently fail if var is undefined. That makes templates hard to debug. Is there a setting I can switch so django will throw an exception in this case?

The only hint at a solution I've found online is http://groups.google.com/group/google-appengine/browse_thread/thread/86a5b12ff868038d and that sounds awfully hacky.

pseudosudo
  • 6,270
  • 9
  • 40
  • 53
  • Method 1 in your specified link looks good. Since, custom template tags are legitimate option for extending template functionality. – Gagandeep Singh Jan 24 '12 at 16:24

5 Answers5

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
  • 8,803
  • 4
  • 41
  • 54
  • 1
    `TEMPLATE_STRING_IF_INVALID = '%s'` would be more appropriate as that will print the variable name that isn't defined instead of some random text. However read the admonition box on the second link very carefully. This is really for one-off debugging instances, *not* something you should just leave on all the time in development. – Chris Pratt Jan 24 '12 at 16:33
  • 2
    The TEMPLATE_STRING_IF_INVALID settings will help with finding invalid variables, when we attempt to print them in a template, but if the variable is used in an if-statement or as the collection in a for-loop, there is no help to be found... Is there any way to catch these cases as well? – Eldamir Jul 29 '15 at 10:39
  • 2
    Is there a way to raise an exception if a variable is undefined? – utapyngo Aug 10 '15 at 14:42
  • 1
    Please update your answer to take into account django 1.10+ where `TEMPLATE_STRING_IF_INVALID` has been deprecated. – Flux Jan 07 '18 at 07:25
  • 'OPTIONS': { 'string_if_invalid': 'Invalid varialbe!', } – Gobrisebane Aug 03 '20 at 10:31
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()
utapyngo
  • 6,946
  • 3
  • 44
  • 65
  • This does not seem to detect undefined foobar in `{% if foobar %}` or `{% for foo in foobar %}` – azmeuk Sep 15 '15 at 08:14
  • 1
    After upgrade from 1.9.x > 1.10.1 I get: `?: (templates.E002) 'string_if_invalid' in TEMPLATES OPTIONS must be a string but got: (InvalidVarException).` So this hack doesn't work any more. – allcaps Sep 28 '16 at 13:48
  • @allcaps what if you inherit it from `basestring` or `unicode`? – utapyngo Sep 30 '16 at 08:46
  • @utapyngo I silenced the system check: `SILENCED_SYSTEM_CHECKS = ['templates.E002']`. – allcaps Sep 30 '16 at 13:10
  • Another way to do it without silencing system checks is: Changing superclass of InvalidVarException to unicode instead of object, setting parameter to InvalidVarException("%s") instead. Btw it works, but I am not getting correct line of template where it crashes anymore. Any way around this? – K.H. Oct 29 '16 at 17:50
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
  • 193
  • 1
  • 8
0

I use this pytest-django config:

[pytest]
FAIL_INVALID_TEMPLATE_VARS = True

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

guettli
  • 25,042
  • 81
  • 346
  • 663
-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.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • @Marcin: I'm speaking in the sense of Django's perspective. If you're relying on template debug errors in development for things not related to fumble-fingering a templatetag or other simple mistakes, you've likely got too much logic in your template. – Chris Pratt Jan 24 '12 at 16:37
  • Well, that's a matter of opinion :) But it is the 'Django Opinion', and it if matters enough to you, use a different template engine! I do, for this reason among others. – AdamKG Jan 24 '12 at 16:54
  • @AdamKG, what other engine can use strict templates? Goes Jinja2 have that feature? – Eldamir Jul 29 '15 at 10:38
  • 1
    @Eldamir: apparently so http://stackoverflow.com/questions/3983581/raise-an-exception-in-jinja-if-we-passed-in-a-variable-that-is-not-present-in-th – Mark May 09 '16 at 12:34