Python 如何访问Django模板中的枚举类型

Python 如何访问Django模板中的枚举类型,python,django,enums,django-templates,Python,Django,Enums,Django Templates,我遇到了一个问题,无论我做什么,我都无法访问Django模板中的IntEnum(来自enum34库) 通过将其转换为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

我遇到了一个问题,无论我做什么,我都无法访问Django模板中的IntEnum(来自enum34库)

通过将其转换为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
{{ 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
当DEMO是IntEnum时,这些命令不起作用,但当DEMO转换为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
{{ 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

你知道为什么吗?这是一个已知的问题吗?

再深入一点,我找到了答案

发件人:

从技术上讲,当模板系统遇到点时,它会按以下顺序尝试查找:

查字典

属性或方法查找

数字索引查找

如果结果值是可调用的,则调用时不带参数。调用的结果将成为模板值

最后一行应该是:

如果任何结果/中间值都是可调用的

在这一过程中:

  • 上下文中查找
    'DEMOS'
    ,获取

  • 检查它是否可调用(它是)

  • 不带任何参数地调用它

  • 获取一个
    TypeError

因此,问题在于
枚举
类是可调用的,模板系统将尝试调用它,这将引发错误并中止(返回空字符串:
'

然而,有一种方法可以解决这个问题。
django.templates.base
的调用代码包含以下内容 防护条件:

if getattr(current, 'do_not_call_in_templates', False):
    pass
代码检查模板中名为
do\u not\u call\u的属性,如果
True
,它将跳过调用部分,这将解决问题

使用Python的
Enum
(或最简单的方法)最简单的方法是使用装饰器。如果Django还没有用于此目的的,您可以轻松地推出自己的:

def forDjango(cls):
    cls.do_not_call_in_templates = True
    return cls
然后装饰您的
Enum

@forDjango
class DEMOS(Enum):
    eggs = 'runny'
    spam = 'hard'
    cheese = 'smelly'
附加属性不会干扰您的属性集
枚举常量,因为枚举一经定义就固定了。

使用Django的
Enum
可以使用
\uuuu成员\uuuu
属性:

context['DEMOS'] = DEMOS.__members__

@EthanFurman如果您想
演示.eggs.name
?Django似乎试图调用下一个
?不要介意前面的问题,它会按预期工作。谢谢你的回答。