I saw this thread so wanted to share a bit of a gotcha we had with enums 
internally for anyone trying to handle this stuff

Internally, we have a wrapper around CharField to work with enums (we go 
further than just choices and actually have the values be enums), but 
there's unfortunately still a good amount of issues in certain use cases 
that make it not a great fit to be put into general usage for Django. I do 
think it's possible to get things right, but you have to establish certain 
rules because the way enums work in Django can sometimes be surprising.

We notably had an issue with translations, and I believe the problem would 
occur with other context-sensitive values. Because database operations will 
often copy values before using them to save to the database, you're 
beholden to (what I believe to be) slightly busted semantics on `copy.copy` 
for enums. Probably defining a django-y enum subclass that requires 
identity/lookup helpers would make this more usable for the general public 
(much like what other people have said). 

In [10]: from enum import Enum
In [11]: from django.utils.translation import ugettext_lazy, override
In [12]: class C(Enum):
    ...:     a = ugettext_lazy("Some Word")

In [13]: with override('en'):
    ...:     elt = C.a
    ...: with override('ja'):
    ...:     copy.copy(elt)
    ...:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-9c36cbd82121> in <module>
      2     elt = C.a
      3 with override('ja'):
----> 4     copy.copy(elt)
      5

/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/copy.py
 
in copy(x)
    104     if isinstance(rv, str):
    105         return x
--> 106     return _reconstruct(x, None, *rv)
    107
    108

/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/copy.py
 
in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    272     if deep and args:
    273         args = (deepcopy(arg, memo) for arg in args)
--> 274     y = func(*args)
    275     if deep:
    276         memo[id(x)] = y

/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/enum.py
 
in __call__(cls, value, names, module, qualname, type, start)
    289         """
    290         if names is None:  # simple value lookup
--> 291             return cls.__new__(cls, value)
    292         # otherwise, functional API: we're creating a new Enum type
    293         return cls._create_(value, names, module=module, 
qualname=qualname, type=type, start=start)

/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/enum.py
 
in __new__(cls, value)
    531                     return member
    532         # still not found -- try _missing_ hook
--> 533         return cls._missing_(value)
    534
    535     def _generate_next_value_(name, start, count, last_values):

/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/enum.py
 
in _missing_(cls, value)
    544     @classmethod
    545     def _missing_(cls, value):
--> 546         raise ValueError("%r is not a valid %s" % (value, 
cls.__name__))
    547
    548     def __repr__(self):

ValueError: 'Japanese Version of Some Word' is not a valid C

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/ad1b1890-3ce3-46fb-9801-6408de4ed256%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to