在Django模板中显示未定义的变量错误?

时间:2010-11-29 02:36:12

标签: django django-templates

如何让Django在遇到时告诉我,例如,在呈现模板时出现未定义的变量错误?

我尝试了显而易见的DEBUG = TrueTEMPLATE_DEBUG = True,但他们没有帮助。

9 个答案:

答案 0 :(得分:26)

将其放入调试设置中:

class InvalidString(str):
    def __mod__(self, other):
        from django.template.base import TemplateSyntaxError
        raise TemplateSyntaxError(
            "Undefined variable or unknown value for: \"%s\"" % other)

TEMPLATE_STRING_IF_INVALID = InvalidString("%s")

当模板引擎看到或发现未定义的值时,这会引发错误。

答案 1 :(得分:10)

根据django文档, 默认情况下,未定义的变量被视为''(空字符串)。在 if for regroup 时,它是 None 。 如果要识别变量undefined,请在设置中更改TEMPLATE_STRING_IF_INVALID。 '%s'使无效变量呈现为其变量名,这样,您就可以轻松识别。 how-invalid-variables-are-handled

答案 2 :(得分:4)

如何在模板

中记录未定义变量的警告

似乎Django依赖于未定义的变量是一个简单的空字符串。因此,不要改变这种行为或使其抛出异常,而是让它保持相同,但让它记录警告!

settings.py文件中:

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

string_if_invalid替换了较新的Django版本中的TEMPLATE_STRING_IF_INVALID。)

更进一步说,你需要定义InvalidStringShowWarning类,使其在记录警告时表现出来:

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

您应该能够在python manage.py runserver的输出中看到警告。

答案 3 :(得分:2)

在模板中阅读how invalid variable are handled。基本上,只需将TEMPLATE_STRING_IF_INVALID设置为settings.py中的内容即可。

TEMPLATE_STRING_IF_INVALID = "He's dead Jim! [%s]"

答案 4 :(得分:2)

我认为这是对Django的主要疏忽,也是我不想使用默认模板引擎的主要原因。可悲的事实是,至少现在(Django 1.9),你无法可靠地实现这种效果

  • 可以让Django在遇到{{ undefined_variable }}时引发异常 - 使用slacy的答案中描述的“hack”。

  • 无法让Django在{% if undefined_variable %}{% for x in undefined_variable %}等处引发相同的异常。“hack”在这种情况下不起作用。< / p>

  • 即使在你可以的情况下,Django作者强烈反对在生产环境中使用这种技术。除非您确定不在应用中使用Django的内置模板,否则您应该在DEBUG模式下使用“hack”

但是,如果您暂时停留在Django的模板中,我建议您使用slacy的答案,只需确保您处于DEBUG模式。

答案 5 :(得分:2)

查找上下文中不存在的模板变量对我来说非常重要,因为有几次错误使其生成,因为视图已更改但模板没有。

我在manage.py中使用了这种技术,以便在使用上下文中找不到模板变量时实现破解测试的效果。请注意,此技术适用于for循环和if语句,而不仅仅是{{ 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

答案 6 :(得分:0)

我下次使用

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

在设置文件中使用(默认情况下为settings.py):

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

    },
]

或直接

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

如果DEBUG = True:

的结果

在页面上

enter image description here

在控制台中

> 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.

答案 7 :(得分:0)

您可以使用 pytest-django setting FAIL_INVALID_TEMPLATE_VARS

如果 pytest 执行代码,则检查无效变量。

[pytest]
DJANGO_SETTINGS_MODULE = mysite.settings
FAIL_INVALID_TEMPLATE_VARS = True

答案 8 :(得分:-3)

如果模板中有未定义的变量,django将不会告诉你。

您可以在视图中打印此变量。