Seá*_*yes 11 python django enums django-templates
我遇到了一个问题,无论我做什么,我都无法访问我的Django模板中的IntEnum(来自enum34 lib).
通过将其转换为dict,我能够绕过它:
def get_context_data(self, **kwargs):
context = super(MyView, self).get_context_data(**kwargs)
# Django templates don't play nice with Enums
context['DEMOS'] = {d.name: d for d in DEMOS}
# `context['DEMOS'] = DEMOS` doesn't work
return context
Run Code Online (Sandbox Code Playgroud)
当DEMO是IntEnum时这些不起作用,但是当DEMO转换为dict时这样做:
{{ DEMO.FOO }} # outputs nothing
{{ DEMO.FOO|default_if_none:'foo' }} # outputs nothing
{{ DEMO.FOO.value }} # outputs nothing
{% if DEMO.FOO == 1 %} # no matter what I compare to, always False
Run Code Online (Sandbox Code Playgroud)
有什么想法吗?这是一个已知的问题?
Eth*_*man 12
多挖一点,我找到了答案.
来自网站:
从技术上讲,当模板系统遇到一个点时,它会按以下顺序尝试以下查找:
字典查找
属性或方法查找
数字索引查找
如果结果值是可调用的,则调用它时不带参数.调用的结果成为模板值.
最后一行应该说:
如果任何结果/中间值可以调用,...
逐步完成该过程:
查找'DEMOS'的context,得到<enum 'DEMOS'>
检查它是否可调用(它是)
不带参数调用它
得到 TypeError
所以问题是一个Enum类是可调用的,模板系统会尝试调用它,这将引发错误并中止(返回一个空字符串:) ''.
但是,有一种方法可以解决这个问题.
django.templates.base的调用代码包含以下保护条件:
if getattr(current, 'do_not_call_in_templates', False):
pass
Run Code Online (Sandbox Code Playgroud)
代码检查一个被调用的属性do_not_call_in_templates,如果True那么它将跳过调用部分,这应解决问题.
使用Python Enum(或enum34backport)最简单的方法是使用装饰器.如果Django还没有用于此目的,你可以轻松地自己动手:
def forDjango(cls):
cls.do_not_call_in_templates = True
return cls
Run Code Online (Sandbox Code Playgroud)
然后装饰你的Enum:
@forDjango
class DEMOS(Enum):
eggs = 'runny'
spam = 'hard'
cheese = 'smelly'
Run Code Online (Sandbox Code Playgroud)
附加属性不会干扰您的枚举常量集,因为枚举一旦定义就会被修复.
使用 Django,Enum您可以使用__members__属性:
context['DEMOS'] = DEMOS.__members__
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4276 次 |
| 最近记录: |