28👍
A little more digging and I found the answer.
From Django’s templates documentation:
Technically, when the template system encounters a dot, it tries the following lookups, in this order:
Dictionary lookup
Attribute or method lookup
Numeric index lookup
If the resulting value is callable, it is called with no arguments. The result of the call becomes the template value.
That last line should say:
If any of the resulting/intermediate values is callable, …
Stepping through that process:
-
lookup
'DEMOS'
in thecontext
, get<enum 'DEMOS'>
-
check if it is callable (it is)
-
call it with no arguments
-
get a
TypeError
So the problem is that an Enum
class is callable, and the templating system will try to call it, which will raise an error and abort (returning an empty string: ''
).
However, there is a way around that problem.
django.templates.base
‘s calling code contains the following
guard condition:
if getattr(current, 'do_not_call_in_templates', False):
pass
The code checks for an attribute called do_not_call_in_templates
, and if True
then it will skip the call portion, which should solve the problem.
Using Python’s Enum
(or the enum34
backport) the simplest way will be to use a decorator. If Django doesn’t already have one for this purpose, you can roll your own easily enough:
def forDjango(cls):
cls.do_not_call_in_templates = True
return cls
and then decorate your Enum
:
@forDjango
class DEMOS(Enum):
eggs = 'runny'
spam = 'hard'
cheese = 'smelly'
The additional attribute does not interfere with your set of
Enum constants, because Enums are fixed once defined.
11👍
Using Django’s Enum
you can use __members__
property:
context['DEMOS'] = DEMOS.__members__
- [Django]-How to add a cancel button to DeleteView in django
- [Django]-Dynamic choices field in Django Models
- [Django]-How does the get_or_create function in Django return two values?