Show undefined variable errors in Django templates?

后端 未结 8 872
长情又很酷
长情又很酷 2020-12-24 08:50

How can I ask Django to tell me when it encounters, for example, an undefined variable error while it\'s rendering templates?

I\'ve tried the obvious DEBUG = T

相关标签:
8条回答
  • 2020-12-24 09:05

    According to the django documentation, undefined variables are treated as ''(empty string) by default. While in if for regroup, it's None. If you are going to identify the variable undefined, change TEMPLATE_STRING_IF_INVALID in settings. '%s' makes the invalid variable to be rendered as its variable name, in this way, u can identify easily. how-invalid-variables-are-handled

    0 讨论(0)
  • 2020-12-24 09:05

    Read up on how invalid variable are handled in templates. Basically, just set TEMPLATE_STRING_IF_INVALID to something in your settings.py.

    TEMPLATE_STRING_IF_INVALID = "He's dead Jim! [%s]"
    
    0 讨论(0)
  • 2020-12-24 09:10

    Finding template variables that didn't exist in the context was important to me as several times bugs made it into production because views had changed but templates had not.

    I used this technique, implemented in manage.py, to achieve the effect of breaking tests when template variables not found in the context were used. Note that this technique works with for loops and if statements and not just {{ variables }}.

    import sys
    
    # sometimes it's OK if a variable is undefined:
    allowed_undefined_variables = [
        'variable_1',
        'variable_2',
    ]
    
    if 'test' in sys.argv:
        import django.template.base as template_base
    
        old_resolve = template_base.Variable.resolve
    
        def new_resolve(self, context):
            try:
                value = old_resolve(self, context)
            except template_base.VariableDoesNotExist as e:
                # if it's not a variable that's allowed to not exist then raise a
                # base Exception so Nodes can't catch it (which will make the test
                # fail)
                if self.var not in allowed_undefined_variables:
                    raise Exception(e)
    
                # re-raise the original and let the individual Nodes deal with it
                # however they'd like
                raise e
    
            return value
    
        template_base.Variable.resolve = new_resolve
    
    0 讨论(0)
  • 2020-12-24 09:15

    How to log a warning on undefined variable in a template

    It seems that Django relies on undefined variables being a simple empty string. So instead of changing this behaviour or making it throw an exception, let's keep it the same but have it log a warning instead!

    In your settings.py file:

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            # ...
            'OPTIONS': {
                # ...
                'string_if_invalid': InvalidStringShowWarning("%s"),
            },
        }
    ]
    

    (string_if_invalid replaces TEMPLATE_STRING_IF_INVALID in newer Django versions.)

    And further up, you'll need to define the InvalidStringShowWarning class, making it behave while logging a warning:

    class InvalidStringShowWarning(str):
        def __mod__(self, other):
            import logging
            logger = logging.getLogger(__name__)
            logger.warning("In template, undefined variable or unknown value for: '%s'" % (other,))
            return ""
    

    You should be able to see the warning in the output of python manage.py runserver.

    0 讨论(0)
  • 2020-12-24 09:15

    If there is a undefined variable in templates, django won't tell you.

    You can print this variable in view.

    0 讨论(0)
  • 2020-12-24 09:18

    I am use next:

    import logging
    
    from django.utils.html import format_html
    from django.utils.safestring import mark_safe
    
    
    class InvalidTemplateVariable(str):
        """
        Class for override output that the Django template system
        determinated as invalid (e.g. misspelled) variables.
        """
    
        # styles for display message in HTML`s pages
        styles = mark_safe('style="color: red; font-weight: bold;"')
    
        def __mod__(self, variable):
            """Overide a standart output here."""
    
            # access to current settings
            from django.conf import settings
    
            # display the message on page in make log it only on stage development
            if settings.DEBUG is True:
    
                # format message with captured variable
                msg = 'Attention! A variable "{}" does not exists.'.format(variable)
    
                # get logger and make
                logger = self.get_logger()
                logger.warning(msg)
    
                # mark text as non-escaped in HTML
                return format_html('<i {}>{}</i>', self.styles, msg)
    
            # on production it will be not displayed
            return ''
    
        def get_logger(self):
            """Create own logger with advanced error`s details."""
    
            logger = logging.getLogger(self.__class__.__name__)
    
            logger.setLevel(logging.DEBUG)
    
            handler = logging.StreamHandler()
            handler.setLevel(logging.DEBUG)
    
            formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
            handler.setFormatter(formatter)
    
            logger.addHandler(handler)
    
            return logger
    

    Usage in settings file (by default it settings.py):

    TEMPLATES = [
        {
            ......
            'OPTIONS': {
                .....................
                'string_if_invalid': InvalidTemplateVariable('%s'),
                .....................
            },
    
        },
    ]
    

    or directly

    TEMPLATES[0]['OPTIONS']['string_if_invalid'] = InvalidTemplateVariable('%s')
    

    A result if DEBUG = True:

    On page

    In console

    > System check identified 1 issue (0 silenced). October 03, 2016 -
    > 12:21:40 Django version 1.10.1, using settings 'settings.development'
    > Starting development server at http://127.0.0.1:8000/ Quit the server
    > with CONTROL-C. 2016-10-03 12:21:44,472 - InvalidTemplateVariable -
    > WARNING - Attention! A variable "form.media" does not exists.
    
    0 讨论(0)
提交回复
热议问题