jinja2:如何像djangotemplate一样静默失败
我找不到答案,我相信这很简单,但我就是不知道怎么让它像Django那样在找不到变量时工作。
我尝试使用Undefined并自己创建一个undefined,但这给我带来了属性错误等问题。
def silently(*args, **kwargs):
return u''
class UndefinedSilently(Undefined):
__unicode__ = silently
__str__ = silently
__call__ = silently
__getattr__ = silently
但是当我在这里尝试这个时,它失败了,出现了 TypeError: 'unicode' object is not callable
:
{%for dir_name, links in menu_links.items()%}
2 个回答
1
这是一个老问题,但它涉及到一个相关的主题。我重新提出来是为了帮助其他人,特别是关于Django 3.1/3.2/4.0的内容:
首先,找到你的
settings.py
文件。在里面添加以下内容到 'OPTIONS' 部分:
'undefined': jinja2.Undefined
这样做后,当你渲染页面时,未定义的变量就不会出现了,也就是说它们会“安静”地消失。完整的代码应该像这样:
{ 'BACKEND': 'django.template.backends.jinja2.Jinja2', 'DIRS': [ BASE_DIR / 'templates-jinja2' ], 'APP_DIRS': True, 'OPTIONS': { 'environment': 'config.jinja2.environment', 'context_processors': [], 'undefined': jinja2.DebugUndefined }, },
另外,你可以使用
DebugUndefined
来查看未定义的变量,或者使用'StrictUndefined'
来在使用未定义变量时抛出异常。
10
你正在尝试深入访问一个未定义的数据。menu_links
是未定义的,所以 Jinja2 创建了一个新的 UndefinedSilently
类的实例。接着,它调用这个对象的 __getattr__
方法来获取 items
属性。这个方法返回的是一个空的 Unicode 字符串。然后,Python 试图调用这个字符串(也就是 menu_links.items()
后面的 ()
),结果就出现了错误,因为 Unicode 对象是不能被调用的。
也就是说:
menu_links.items() # becomes
UndefinedSilently().items() # becomes
UndefinedSilently().u''() # from UndefinedSilently.__getattr__
如果你想要能够深入访问超过一层,你可以创建一个类,让它在每次访问时都返回自己,除了在 __str__
和 __unicode__
方法的调用。
def silently(*args, **kwargs):
return u''
return_new = lambda *args, **kwargs: UndefinedSilently()
class UndefinedSilently(Undefined):
__unicode__ = silently
__str__ = silently
__call__ = return_new
__getattr__ = return_new