mirror of
https://github.com/Hopiu/django-model-utils.git
synced 2026-05-28 19:28:16 +00:00
Merge pull request #93 from tucarga/choices-name
Added choices_name parameter to StatusField
This commit is contained in:
commit
ccd7086112
5 changed files with 36 additions and 9 deletions
|
|
@ -4,6 +4,9 @@ CHANGES
|
||||||
master (unreleased)
|
master (unreleased)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* Can pass `choices_name` to `StatusField` to use a different name for
|
||||||
|
choices class attribute. ``STATUS`` is used by default.
|
||||||
|
|
||||||
* Can pass model subclasses, rather than strings, into
|
* Can pass model subclasses, rather than strings, into
|
||||||
`select_subclasses()`. Thanks Keryn Knight. Merge of GH-79.
|
`select_subclasses()`. Thanks Keryn Knight. Merge of GH-79.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,10 @@ StatusField
|
||||||
|
|
||||||
A simple convenience for giving a model a set of "states."
|
A simple convenience for giving a model a set of "states."
|
||||||
``StatusField`` is a ``CharField`` subclass that expects to find a
|
``StatusField`` is a ``CharField`` subclass that expects to find a
|
||||||
``STATUS`` class attribute on its model, and uses that as its
|
class attribute called ``STATUS`` on its model or you can pass
|
||||||
``choices``. Also sets a default ``max_length`` of 100, and sets its
|
``choices_name`` to use a different attribute name, and uses that as
|
||||||
default value to the first item in the ``STATUS`` choices:
|
its ``choices``. Also sets a default ``max_length`` of 100, and sets
|
||||||
|
its default value to the first item in the ``STATUS`` choices:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
@ -25,6 +26,18 @@ default value to the first item in the ``STATUS`` choices:
|
||||||
(The ``STATUS`` class attribute does not have to be a :ref:`Choices`
|
(The ``STATUS`` class attribute does not have to be a :ref:`Choices`
|
||||||
instance, it can be an ordinary list of two-tuples).
|
instance, it can be an ordinary list of two-tuples).
|
||||||
|
|
||||||
|
Using a different name for the model's choices class attribute
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from model_utils.fields import StatusField
|
||||||
|
from model_utils import Choices
|
||||||
|
|
||||||
|
class Article(models.Model):
|
||||||
|
ANOTHER_CHOICES = Choices('draft', 'published')
|
||||||
|
# ...
|
||||||
|
another_field = StatusField(choices_name='ANOTHER_CHOICES')
|
||||||
|
|
||||||
``StatusField`` does not set ``db_index=True`` automatically; if you
|
``StatusField`` does not set ``db_index=True`` automatically; if you
|
||||||
expect to frequently filter on your status field (and it will have
|
expect to frequently filter on your status field (and it will have
|
||||||
enough selectivity to make an index worthwhile) you may want to add this
|
enough selectivity to make an index worthwhile) you may want to add this
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ from django.conf import settings
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
from django.utils.encoding import python_2_unicode_compatible
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
|
DEFAULT_CHOICES_NAME = 'STATUS'
|
||||||
|
|
||||||
|
|
||||||
class AutoCreatedField(models.DateTimeField):
|
class AutoCreatedField(models.DateTimeField):
|
||||||
"""
|
"""
|
||||||
|
|
@ -48,16 +50,17 @@ class StatusField(models.CharField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs.setdefault('max_length', 100)
|
kwargs.setdefault('max_length', 100)
|
||||||
self.check_for_status = not kwargs.pop('no_check_for_status', False)
|
self.check_for_status = not kwargs.pop('no_check_for_status', False)
|
||||||
|
self.choices_name = kwargs.pop('choices_name', DEFAULT_CHOICES_NAME)
|
||||||
super(StatusField, self).__init__(*args, **kwargs)
|
super(StatusField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def prepare_class(self, sender, **kwargs):
|
def prepare_class(self, sender, **kwargs):
|
||||||
if not sender._meta.abstract and self.check_for_status:
|
if not sender._meta.abstract and self.check_for_status:
|
||||||
assert hasattr(sender, 'STATUS'), \
|
assert hasattr(sender, self.choices_name), \
|
||||||
"To use StatusField, the model '%s' must have a STATUS choices class attribute." \
|
"To use StatusField, the model '%s' must have a %s choices class attribute." \
|
||||||
% sender.__name__
|
% (sender.__name__, self.choices_name)
|
||||||
self._choices = sender.STATUS
|
self._choices = getattr(sender, self.choices_name)
|
||||||
if not self.has_default():
|
if not self.has_default():
|
||||||
self.default = tuple(sender.STATUS)[0][0] # set first as default
|
self.default = tuple(getattr(sender, self.choices_name))[0][0] # set first as default
|
||||||
|
|
||||||
def contribute_to_class(self, cls, name):
|
def contribute_to_class(self, cls, name):
|
||||||
models.signals.class_prepared.connect(self.prepare_class, sender=cls)
|
models.signals.class_prepared.connect(self.prepare_class, sender=cls)
|
||||||
|
|
|
||||||
|
|
@ -352,3 +352,8 @@ class StatusFieldDefaultFilled(models.Model):
|
||||||
class StatusFieldDefaultNotFilled(models.Model):
|
class StatusFieldDefaultNotFilled(models.Model):
|
||||||
STATUS = Choices((0, "no", "No"), (1, "yes", "Yes"))
|
STATUS = Choices((0, "no", "No"), (1, "yes", "Yes"))
|
||||||
status = StatusField()
|
status = StatusField()
|
||||||
|
|
||||||
|
|
||||||
|
class StatusFieldChoicesName(models.Model):
|
||||||
|
NAMED_STATUS = Choices((0, "no", "No"), (1, "yes", "Yes"))
|
||||||
|
status = StatusField(choices_name='NAMED_STATUS')
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ from model_utils.tests.models import (
|
||||||
ModelTracked, ModelTrackedFK, ModelTrackedNotDefault, ModelTrackedMultiple, InheritedModelTracked,
|
ModelTracked, ModelTrackedFK, ModelTrackedNotDefault, ModelTrackedMultiple, InheritedModelTracked,
|
||||||
Tracked, TrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple,
|
Tracked, TrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple,
|
||||||
InheritedTracked, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled,
|
InheritedTracked, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled,
|
||||||
InheritanceManagerTestChild3)
|
InheritanceManagerTestChild3, StatusFieldChoicesName)
|
||||||
|
|
||||||
|
|
||||||
class GetExcerptTests(TestCase):
|
class GetExcerptTests(TestCase):
|
||||||
|
|
@ -259,6 +259,9 @@ class StatusFieldTests(TestCase):
|
||||||
instance = StatusFieldDefaultFilled()
|
instance = StatusFieldDefaultFilled()
|
||||||
self.assertEqual(instance.get_status_display(), "Yes")
|
self.assertEqual(instance.get_status_display(), "Yes")
|
||||||
|
|
||||||
|
def test_choices_name(self):
|
||||||
|
StatusFieldChoicesName()
|
||||||
|
|
||||||
|
|
||||||
class ChoicesTests(TestCase):
|
class ChoicesTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue