【问题标题】:Make django templates strict使 django 模板严格
【发布时间】:2012-02-17 21:35:50
【问题描述】:

在 django 模板中,如果 var 未定义,则对 {{ var }} 的调用将静默失败。这使得模板难以调试。有没有我可以切换的设置,所以 django 在这种情况下会抛出异常?

我在网上找到的解决方案的唯一提示是 http://groups.google.com/group/google-appengine/browse_thread/thread/86a5b12ff868038d,这听起来非常老套。

【问题讨论】:

  • 您指定链接中的方法 1 看起来不错。因为,自定义模板标签是扩展模板功能的合法选择。

标签: django django-templates django-errors


【解决方案1】:

Django

在您的settings.py 中设置TEMPLATE_STRING_IF_INVALID = 'DEBUG WARNING: undefined template variable [%s] not found'

请参阅文档:
https://docs.djangoproject.com/en/1.9/ref/settings/#template-string-if-invalid

Django>=1.10

settings.py 中设置string_if_invalid = 'DEBUG WARNING: undefined template variable [%s] not found' 模板选项。

参见文档:https://docs.djangoproject.com/en/2.0/topics/templates/#module-django.template.backends.django

另请阅读: http://docs.djangoproject.com/en/dev/ref/templates/api/#invalid-template-variables

【讨论】:

  • TEMPLATE_STRING_IF_INVALID = '%s' 会更合适,因为它将打印未定义的变量名称而不是一些随机文本。但是,请仔细阅读第二个链接上的警告框。这确实适用于一次性调试实例,不是您应该在开发过程中一直保留的东西。
  • TEMPLATE_STRING_IF_INVALID 设置将有助于查找无效变量,当我们尝试在模板中打印它们时,但如果该变量用于 if 语句或作为 for 循环中的集合,则找不到任何帮助...有什么办法可以抓住这些案例吗?
  • 如果变量未定义,有没有办法引发异常?
  • 请更新您的答案以考虑到 django 1.10+,其中 TEMPLATE_STRING_IF_INVALID 已被弃用。
  • 'OPTIONS': { 'string_if_invalid': '无效变量!', }
【解决方案2】:

djangosnippets 的这个 hack 将在模板中遇到未定义的变量时引发异常。

# 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()

【讨论】:

  • 这似乎没有检测到 {% if foobar %}{% for foo in foobar %} 中未定义的 foobar
  • 从 1.9.x > 1.10.1 升级后,我得到:?: (templates.E002) 'string_if_invalid' in TEMPLATES OPTIONS must be a string but got: <ia_django.settings.local.InvalidVarException object at 0x10566a490> (InvalidVarException). 所以这个 hack 不再起作用了。
  • @allcaps 如果你从basestringunicode 继承它会怎样?
  • @utapyngo 我关闭了系统检查:SILENCED_SYSTEM_CHECKS = ['templates.E002']
  • 另一种无需静默系统检查的方法是:将 InvalidVarException 的超类更改为 unicode 而不是 object,将参数设置为 InvalidVarException("%s")。顺便说一句,它可以工作,但我没有得到正确的模板行,它不再崩溃了。有什么办法吗?
【解决方案3】:

考虑使用 django-shouty-templates 应用程序:https://pypi.org/project/django-shouty-templates/

这个应用程序应用了一个猴子补丁,它强制 Django 的模板语言在无效假设方面发出更大的错误。具体来说:

  • 如果变量被称为sous_chefchef 将引发异常。
  • 如果can_add_cakes 不是厨师的有效属性/属性/方法,chef.can_add_cakes 将引发异常

这不是编译时安全,但总比因为忘记了什么而默默吞下错误要好!

【讨论】:

  • 感谢您的提示!
【解决方案4】:

我用这个pytest-django config

[pytest]
FAIL_INVALID_TEMPLATE_VARS = True

这样,如果我运行测试,我会得到一个异常。

【讨论】:

    【解决方案5】:

    这是设计的一部分。它允许您提供默认值并根据上下文中是否存在变量进行切换。它还允许模板非常灵活并促进模板的可重用性,而不是严格的“每个视图必须有自己的模板”的方法。

    更重要的是,模板实际上不应该被“调试”。我们的想法是将尽可能多的逻辑放在模板之外的视图或模型中。如果您想弄清楚为什么不应该传递给上下文的变量,那么调试的地方就在您的视图中。只需在您的视图返回之前将import pdb;pdb.set_trace() 放在某处并四处寻找。

    【讨论】:

    • @Marcin:我说的是 Django 的观点。如果您在开发中依赖模板调试错误来解决与摸索模板标签或其他简单错误无关的事情,那么您的模板中可能有太多逻辑。
    • 嗯,这是一个见仁见智的问题 :) 但这是“Django 意见”,如果对你来说足够重要,请使用不同的模板引擎!出于这个原因,我愿意。
    • @AdamKG,还有哪些引擎可以使用严格的模板? Go Jinja2 有这个功能吗?
    • @Eldamir:显然是这样stackoverflow.com/questions/3983581/…
    猜你喜欢
    • 2021-03-24
    • 1970-01-01
    • 2018-07-19
    • 2013-10-08
    • 2016-10-16
    • 2011-03-09
    • 1970-01-01
    • 2011-06-22
    相关资源
    最近更新 更多