mirror of
https://github.com/Hopiu/django-model-utils.git
synced 2026-03-19 13:00:25 +00:00
Changes: - Use unicode_literals from the future for Python 2.6.5+ - Use six's text_type for proper unicode use in Python 2/3
78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
from __future__ import unicode_literals
|
|
|
|
|
|
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" % repr(i) for i in self._full)))
|