mirror of
https://github.com/Hopiu/django-model-utils.git
synced 2026-03-16 20:00:23 +00:00
Removed deprecated ChoiceEnum; moved Choices out of __init__.py.
This commit is contained in:
parent
45f7ae26fe
commit
a9ac3685fb
3 changed files with 78 additions and 138 deletions
|
|
@ -11,6 +11,8 @@ tip (unreleased)
|
|||
.. _BitBucket: https://bitbucket.org/carljm/django-model-utils/overview
|
||||
.. _GitHub: https://github.com/carljm/django-model-utils/
|
||||
|
||||
- Removed deprecated ``ChoiceEnum`` class.
|
||||
|
||||
- Added ``UpdateOrCreateMixin`` for custom queryset subclasses. Thanks Antti
|
||||
Kaihola.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,138 +1 @@
|
|||
from django import VERSION
|
||||
if VERSION < (1, 2):
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"Django 1.1 support in django-model-utils is pending deprecation.",
|
||||
PendingDeprecationWarning)
|
||||
|
||||
|
||||
|
||||
class ChoiceEnum(object):
|
||||
"""
|
||||
DEPRECATED: Use ``Choices`` (below) instead. This class has less
|
||||
flexibility for human-readable display, and greater potential for
|
||||
surprising data corruption if new choices are inserted in the
|
||||
middle of the list. Automatic assignment of numeric IDs is not
|
||||
such a great idea after all.
|
||||
|
||||
A class to encapsulate handy functionality for lists of choices
|
||||
for a Django model field.
|
||||
|
||||
Accepts verbose choice names as arguments, and automatically
|
||||
assigns numeric keys to them. When iterated over, behaves as the
|
||||
standard Django choices list of two-tuples.
|
||||
|
||||
Attribute access allows conversion of verbose choice name to
|
||||
choice key, dictionary access the reverse.
|
||||
|
||||
Example:
|
||||
|
||||
>>> STATUS = ChoiceEnum('DRAFT', 'PUBLISHED')
|
||||
>>> STATUS.DRAFT
|
||||
0
|
||||
>>> STATUS[1]
|
||||
'PUBLISHED'
|
||||
>>> tuple(STATUS)
|
||||
((0, 'DRAFT'), (1, 'PUBLISHED'))
|
||||
|
||||
"""
|
||||
def __init__(self, *choices):
|
||||
import warnings
|
||||
warnings.warn("ChoiceEnum is deprecated, use Choices instead.",
|
||||
DeprecationWarning)
|
||||
self._choices = tuple(enumerate(choices))
|
||||
self._choice_dict = dict(self._choices)
|
||||
self._reverse_dict = dict(((i[1], i[0]) for i in self._choices))
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._choices)
|
||||
|
||||
def __getattr__(self, attname):
|
||||
try:
|
||||
return self._reverse_dict[attname]
|
||||
except KeyError:
|
||||
raise AttributeError(attname)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._choice_dict[key]
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (self.__class__.__name__,
|
||||
', '.join(("'%s'" % i[1] for i in self._choices)))
|
||||
|
||||
|
||||
class Choices(object):
|
||||
"""
|
||||
A class to encapsulate handy functionality for lists of choices
|
||||
for a Django model field.
|
||||
|
||||
Each argument to ``Choices`` is a choice, represented as either a
|
||||
string, a two-tuple, or a three-tuple.
|
||||
|
||||
If a single string is provided, that string is used as the
|
||||
database representation of the choice as well as the
|
||||
human-readable presentation.
|
||||
|
||||
If a two-tuple is provided, the first item is used as the database
|
||||
representation and the second the human-readable presentation.
|
||||
|
||||
If a triple is provided, the first item is the database
|
||||
representation, the second a valid Python identifier that can be
|
||||
used as a readable label in code, and the third the human-readable
|
||||
presentation. This is most useful when the database representation
|
||||
must sacrifice readability for some reason: to achieve a specific
|
||||
ordering, to use an integer rather than a character field, etc.
|
||||
|
||||
Regardless of what representation of each choice is originally
|
||||
given, when iterated over or indexed into, a ``Choices`` object
|
||||
behaves as the standard Django choices list of two-tuples.
|
||||
|
||||
If the triple form is used, the Python identifier names can be
|
||||
accessed as attributes on the ``Choices`` object, returning the
|
||||
database representation. (If the single or two-tuple forms are
|
||||
used and the database representation happens to be a valid Python
|
||||
identifier, the database representation itself is available as an
|
||||
attribute on the ``Choices`` object, returning itself.)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *choices):
|
||||
self._full = []
|
||||
self._choices = []
|
||||
self._choice_dict = {}
|
||||
for choice in self.equalize(choices):
|
||||
self._full.append(choice)
|
||||
self._choices.append((choice[0], choice[2]))
|
||||
self._choice_dict[choice[1]] = choice[0]
|
||||
|
||||
def equalize(self, choices):
|
||||
for choice in choices:
|
||||
if isinstance(choice, (list, tuple)):
|
||||
if len(choice) == 3:
|
||||
yield choice
|
||||
elif len(choice) == 2:
|
||||
yield (choice[0], choice[0], choice[1])
|
||||
else:
|
||||
raise ValueError("Choices can't handle a list/tuple of length %s, only 2 or 3"
|
||||
% len(choice))
|
||||
else:
|
||||
yield (choice, choice, choice)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._choices)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._choices)
|
||||
|
||||
def __getattr__(self, attname):
|
||||
try:
|
||||
return self._choice_dict[attname]
|
||||
except KeyError:
|
||||
raise AttributeError(attname)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self._choices[index]
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (self.__class__.__name__,
|
||||
', '.join(("%s" % str(i) for i in self._full)))
|
||||
from .choices import Choices
|
||||
|
|
|
|||
75
model_utils/choices.py
Normal file
75
model_utils/choices.py
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
class Choices(object):
|
||||
"""
|
||||
A class to encapsulate handy functionality for lists of choices
|
||||
for a Django model field.
|
||||
|
||||
Each argument to ``Choices`` is a choice, represented as either a
|
||||
string, a two-tuple, or a three-tuple.
|
||||
|
||||
If a single string is provided, that string is used as the
|
||||
database representation of the choice as well as the
|
||||
human-readable presentation.
|
||||
|
||||
If a two-tuple is provided, the first item is used as the database
|
||||
representation and the second the human-readable presentation.
|
||||
|
||||
If a triple is provided, the first item is the database
|
||||
representation, the second a valid Python identifier that can be
|
||||
used as a readable label in code, and the third the human-readable
|
||||
presentation. This is most useful when the database representation
|
||||
must sacrifice readability for some reason: to achieve a specific
|
||||
ordering, to use an integer rather than a character field, etc.
|
||||
|
||||
Regardless of what representation of each choice is originally
|
||||
given, when iterated over or indexed into, a ``Choices`` object
|
||||
behaves as the standard Django choices list of two-tuples.
|
||||
|
||||
If the triple form is used, the Python identifier names can be
|
||||
accessed as attributes on the ``Choices`` object, returning the
|
||||
database representation. (If the single or two-tuple forms are
|
||||
used and the database representation happens to be a valid Python
|
||||
identifier, the database representation itself is available as an
|
||||
attribute on the ``Choices`` object, returning itself.)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *choices):
|
||||
self._full = []
|
||||
self._choices = []
|
||||
self._choice_dict = {}
|
||||
for choice in self.equalize(choices):
|
||||
self._full.append(choice)
|
||||
self._choices.append((choice[0], choice[2]))
|
||||
self._choice_dict[choice[1]] = choice[0]
|
||||
|
||||
def equalize(self, choices):
|
||||
for choice in choices:
|
||||
if isinstance(choice, (list, tuple)):
|
||||
if len(choice) == 3:
|
||||
yield choice
|
||||
elif len(choice) == 2:
|
||||
yield (choice[0], choice[0], choice[1])
|
||||
else:
|
||||
raise ValueError("Choices can't handle a list/tuple of length %s, only 2 or 3"
|
||||
% len(choice))
|
||||
else:
|
||||
yield (choice, choice, choice)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._choices)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._choices)
|
||||
|
||||
def __getattr__(self, attname):
|
||||
try:
|
||||
return self._choice_dict[attname]
|
||||
except KeyError:
|
||||
raise AttributeError(attname)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self._choices[index]
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (self.__class__.__name__,
|
||||
', '.join(("%s" % str(i) for i in self._full)))
|
||||
Loading…
Reference in a new issue