当Django模板系统遇到一个无效的字典查找时,它会被一个空字符串默默地替换。不过,对于特定的字典查找,我希望Django能引发一个异常来帮助调试。假设一个字典是这样的:
colors = {"red": 1, "green 2, "blue": 3}
字符串这里应该提出一个例外:
{{ colors.orange }}
型当Django模板系统遇到无效的字典查找时,我如何强制它引发异常?
qq24tv8q1#
Django模板引擎并不是真的这样做的。但我们可以“破解”它。事实上,我们可以定义自己的InvalidVarException,例如记录,或引发异常:
InvalidVarException
import inspect import logging from itertools import islice from django.template.base import FilterExpression UNKNOWN = object() MISSING = object() def all_in_stack(type_filter, var_name='self'): for item in islice(inspect.stack(), 1): obj = item.frame.f_locals.get(var_name, MISSING) if obj is not MISSING and isinstance(obj, type_filter): yield obj def look_in_stack(type_filter, var_name='self'): for item in all_in_stack(type_filter=type_filter, var_name=var_name): return item return MISSING def or_unknown( f, *args, _unknown=UNKNOWN, _exception_type_filter=BaseException, **kwargs ): try: result = f(*args, **kwargs) if result is MISSING: return _unknown return result except _exception_type_filter: return _unknown def get_request_from_stack(type_filter: HttpRequest, var_name='request'): return look_in_stack(type_filter=type_filter, var_name=var_name) def get_template_node_from_stack(var_name='self'): return look_in_stack(Node, var_name=var_name) def get_template_location_from_stack(var_name='self'): return get_node_file_loc(get_template_node_from_stack(var_name=var_name)) logger = logging.getLogger('templates') class InvalidVarException(str): already = set() def __mod__(self, missing, *args, **kwargs): missing_str = or_unknown(str, missing) request = or_unknown(get_request_from_stack) path = request.path full_path = request.get_full_path() loc = or_unknown(get_template_location_from_stack) key = (path, loc, missing_str) show = key not in self.already if show: self.already.add(key) try: message = f'Missing variable {{{{ {missing_str} }}}} at {loc} for path {full_path}' logger.error(message) except: pass return self def __bool__(self): return True def __contains__(self, search): return '%s' in search or super().__contains__(search) def is_simple_constant(expr): if not expr.is_var and (not expr.filters): return expr.var
字符串然后我们可以将InvalidVarException注册为string_if_invalid选项:
string_if_invalid
# settings.py TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', # … 'OPTIONS': { # … 'string_if_invalid': InvalidVarException(), # … }, }, ]
型我们的想法是,Django通常会在找不到变量的情况下渲染string_if_invalid,从而使引擎静默。但在这里,我们使用了一个技巧来格式化字符串,并使用它来查找模板和变量,然后记录结果。
gblwokeq2#
你不能直接从django的模板系统中引发异常。它被设计成静默失败。但你可以做的是定义一个自定义的模板标签来验证字典,如果缺少键(无效查找),它会引发异常。
2条答案
按热度按时间qq24tv8q1#
Django模板引擎并不是真的这样做的。但我们可以“破解”它。事实上,我们可以定义自己的
InvalidVarException
,例如记录,或引发异常:字符串
然后我们可以将
InvalidVarException
注册为string_if_invalid
选项:型
我们的想法是,Django通常会在找不到变量的情况下渲染
string_if_invalid
,从而使引擎静默。但在这里,我们使用了一个技巧来格式化字符串,并使用它来查找模板和变量,然后记录结果。gblwokeq2#
你不能直接从django的模板系统中引发异常。它被设计成静默失败。但你可以做的是定义一个自定义的模板标签来验证字典,如果缺少键(无效查找),它会引发异常。