Commits

Anonymous committed bcc288b

deprecate ChoiceEnum and document Choices

Comments (0)

Files changed (3)

 Installation
 ============
 
-Install from PyPI with ``easy_install`` or ``pip``::
+Install from PyPI with ``pip``::
 
     pip install django-model-utils
 
 
 .. _Django: http://www.djangoproject.com/
 
-ChoiceEnum
-==========
+Choices
+=======
 
-``ChoiceEnum`` makes setting ``choices`` on a Django model field way
+``Choices`` makes setting ``choices`` on a Django model field way
 too easy::
 
-    from model_utils import ChoiceEnum
+    from model_utils import Choices
 
     class Article(models.Model):
-        STATUS = ChoiceEnum('draft', 'published')
+        STATUS = Choices('draft', 'published')
         # ...
-        status = models.PositiveIntegerField(choices=STATUS, default=STATUS.draft)
+        status = models.CharField(choices=STATUS, default=STATUS.draft, max_length=20)
 
-        def status_desc(self):
-            return self.STATUS[self.status]
+A ``Choices`` object is initialized with any number of choices, which
+can either be a string ID or a tuple of (string ID, human-readable
+version). If a string ID is given alone, the ID itself is used as the
+human-readable version.  Accessing the string ID as an attribute on
+the ``Choices`` object returns the human-readable version. If iterated
+over, a ``ChoiceEnum`` object yields a tuple of two-tuples linking id
+to text names, the format expected by the ``choices`` attribute of
+Django models.
 
-A ``ChoiceEnum`` object is initialized with any number of choices,
-which should be strings. It assigns a sequential id to each
-choice. The numerical id for a choice is available through attribute
-access (``STATUS.draft``), and the text name for a choice can be
-obtained by indexing with the numerical id
-(``self.STATUS[self.status]``). If iterated over, a ``ChoiceEnum``
-object yields a tuple of two-tuples linking id to text names, the
-format expected by the ``choices`` attribute of Django models.
-
-Be careful not to add new choices in the middle of the list, as that
-will change the numerical ids for all subsequent choices, which could
-impact existing data.
+.. note::
+    Whither ``ChoiceEnum``? It's been deprecated in favor of ``Choices``.
 
 fields.SplitField
 =================

model_utils/__init__.py

 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.
 
     
     """
     def __init__(self, *choices):
+        import warnings
+        warnings.warn("ChoiceEnum is deprecated, use Choices instead.",
+                      PendingDeprecationWarning)
         self._choices = tuple(enumerate(choices))
         self._choice_dict = dict(self._choices)
         self._reverse_dict = dict(((i[1], i[0]) for i in self._choices))
     A class to encapsulate handy functionality for lists of choices
     for a Django model field.
 
-    Accepts as arguments either tuples mapping choice IDs (numeric or
-    text) to human-readable names, or simply choice IDs (in which case
-    the ID is also used as the human-readable name). When iterated
-    over, behaves as the standard Django choices tuple of two-tuples.
+    Accepts as arguments either tuples mapping choice IDs (strings) to
+    human-readable names, or simply choice IDs (in which case the ID
+    is also used as the human-readable name). When iterated over,
+    behaves as the standard Django choices tuple of two-tuples.
 
     Attribute access allows conversion of choice ID to human-readable
     name.

model_utils/tests/tests.py

         self.assertRaises(AttributeError, _invalid_assignment)
 
 
-class ChoiceEnumTests(TestCase):
-    def setUp(self):
-        self.STATUS = ChoiceEnum('DRAFT', 'PUBLISHED')
-
-    def test_getattr(self):
-        self.assertEquals(self.STATUS.DRAFT, 0)
-
-    def test_getitem(self):
-        self.assertEquals(self.STATUS[1], 'PUBLISHED')
-
-    def test_iteration(self):
-        self.assertEquals(tuple(self.STATUS), ((0, 'DRAFT'), (1, 'PUBLISHED')))
-
-
 class ChoicesTests(TestCase):
     def setUp(self):
         self.STATUS = Choices('DRAFT', 'PUBLISHED')
 class LabelChoicesTests(ChoicesTests):
     def setUp(self):
         self.STATUS = Choices(
-            ('DRAFT', 'draft'),
-            ('PUBLISHED', 'published'),
+            ('DRAFT', 'is draft'),
+            ('PUBLISHED', 'is published'),
             'DELETED',
         )
 
     def test_iteration(self):
         self.assertEquals(tuple(self.STATUS), (
-            ('DRAFT', 'draft'),
-            ('PUBLISHED', 'published'),
+            ('DRAFT', 'is draft'),
+            ('PUBLISHED', 'is published'),
             ('DELETED', 'DELETED'))
         )
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.