From 16297e7d5e3a6b0287d114e95d1d544995618c93 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 9 Jan 2020 15:41:54 +0000 Subject: [PATCH] [3.0.x] Fixed #31154 -- Added support for using enumeration types in templates. Enumeration helpers are callables, so the template system tried to call them with no arguments. Thanks Rupert Baker for helping discover this. Backport of 5166097d7c80cab757e44f2d02f3d148fbbc2ff6 from master --- django/db/models/enums.py | 1 + docs/releases/3.0.3.txt | 3 +++ tests/model_enums/tests.py | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/django/db/models/enums.py b/django/db/models/enums.py index ae20ef6d93..c76e4863d7 100644 --- a/django/db/models/enums.py +++ b/django/db/models/enums.py @@ -31,6 +31,7 @@ class ChoicesMeta(enum.EnumMeta): # that is passed in as "self" as the value to use when looking up the # label in the choices. cls.label = property(lambda self: cls._value2label_map_.get(self.value)) + cls.do_not_call_in_templates = True return enum.unique(cls) def __contains__(cls, member): diff --git a/docs/releases/3.0.3.txt b/docs/releases/3.0.3.txt index 27ace475d1..ab5a2fd84b 100644 --- a/docs/releases/3.0.3.txt +++ b/docs/releases/3.0.3.txt @@ -20,3 +20,6 @@ Bugfixes * Relaxed the system check added in Django 3.0 to reallow use of a sublanguage in the :setting:`LANGUAGE_CODE` setting, when a base language is available in Django but the sublanguage is not (:ticket:`31141`). + +* Added support for using enumeration types ``TextChoices``, + ``IntegerChoices``, and ``Choices`` in templates (:ticket:`31154`). diff --git a/tests/model_enums/tests.py b/tests/model_enums/tests.py index e1810e673a..1136114807 100644 --- a/tests/model_enums/tests.py +++ b/tests/model_enums/tests.py @@ -4,6 +4,7 @@ import ipaddress import uuid from django.db import models +from django.template import Context, Template from django.test import SimpleTestCase from django.utils.functional import Promise from django.utils.translation import gettext_lazy as _ @@ -149,6 +150,11 @@ class ChoicesTests(SimpleTestCase): with self.subTest(member=member): self.assertEqual(str(test[member.name]), str(member.value)) + def test_templates(self): + template = Template('{{ Suit.DIAMOND.label }}|{{ Suit.DIAMOND.value }}') + output = template.render(Context({'Suit': Suit})) + self.assertEqual(output, 'Diamond|1') + class Separator(bytes, models.Choices): FS = b'\x1c', 'File Separator'