diff --git a/django_enumfield/item.py b/django_enumfield/item.py index ea47e4b..5632e2e 100644 --- a/django_enumfield/item.py +++ b/django_enumfield/item.py @@ -1,6 +1,7 @@ import six import functools +from .utils import is_lazy_translation from .app_settings import app_settings @@ -34,9 +35,15 @@ def __init__(self, value, slug, display=None): if not isinstance(slug, str): raise TypeError("item slug should be a str, not %r" % type(slug)) - if display is not None and not isinstance(display, six.string_types): - raise TypeError("item display name should be a basestring, not %r" \ - % type(display)) + if ( + display is not None and + not isinstance(display, six.string_types) and + not is_lazy_translation(display) + ): + raise TypeError( + "item display name should be a string or lazily evaluated " + "string, not %r" % type(display), + ) self.value = value self.slug = slug diff --git a/django_enumfield/utils.py b/django_enumfield/utils.py index 3f2e349..0a393f7 100644 --- a/django_enumfield/utils.py +++ b/django_enumfield/utils.py @@ -1,4 +1,7 @@ +import six + from django.http import Http404 +from django.utils.functional import Promise def get_enum_or_404(enum, slug): try: @@ -25,3 +28,14 @@ def __getitem__(self, key): class TemplateErrorException(RuntimeError): silent_variable_failure = False + +def is_lazy_translation(obj): + # There's no public API to figure out the type of a "Promise"/"__proxy__" + # object, so we look at whether the object has a string type in its set + # of resultclasses. We do this so that we don't have to force the lazy + # object as that may be expensive and we're likely working at import time. + if not isinstance(obj, Promise): + return False + + resultclasses = obj.__reduce__()[1][3:] + return any(issubclass(x, six.string_types) for x in resultclasses) diff --git a/tests/tests.py b/tests/tests.py index ac535b0..2f25551 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -9,6 +9,7 @@ from django.template import RequestContext from django.template.loader import render_to_string from django.db.models.fields import NOT_PROVIDED +from django.utils.translation import gettext_lazy as _ from django_enumfield import Enum, Item, get_enum_or_404 from django_enumfield.utils import TemplateErrorException @@ -68,6 +69,10 @@ def test_comparison(self): self.assertGreater(item2, item1) self.assertGreaterEqual(item2, item2_copy) self.assertLessEqual(item2, item2_copy) + + def test_lazy_translation_in_display(self): + item = Item(10, 'slug', _("Display")) + self.assertEqual(item.display, "Display") class EnumConstructionTests(unittest.TestCase):