From 911b5223c816fe036e50e269dd59722b5a2b4a96 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Mon, 26 Apr 2010 22:30:01 +0200 Subject: [PATCH] Fixed bug which prevented the StatusModel and TimeframedModel to get the appropriate QueryManager instances added dynamically before instantiation. --- model_utils/models.py | 64 ++++++++++++++++++++++--------------- model_utils/tests/models.py | 10 ++++++ model_utils/tests/tests.py | 14 ++++++-- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/model_utils/models.py b/model_utils/models.py index c47c209..8142a1d 100644 --- a/model_utils/models.py +++ b/model_utils/models.py @@ -4,6 +4,7 @@ from django.db import models from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext_lazy as _ from django.db.models.fields import FieldDoesNotExist +from django.core.exceptions import ImproperlyConfigured from model_utils.managers import QueryManager from model_utils.fields import AutoCreatedField, AutoLastModifiedField, \ @@ -56,19 +57,6 @@ class TimeFramedModel(models.Model): start = models.DateTimeField(_('start'), null=True, blank=True) end = models.DateTimeField(_('end'), null=True, blank=True) - def __init__(self, *args, **kwargs): - super(TimeFramedModel, self).__init__(*args, **kwargs) - try: - self._meta.get_field('timeframed') - raise ValueError("Model '%s' has a field named 'timeframed' which " - "conflicts with the TimeFramedModel manager." % self.__name__) - except FieldDoesNotExist: - pass - self.__class__.add_to_class('timeframed', QueryManager( - (models.Q(start__lte=datetime.now()) | models.Q(start__isnull=True)) & - (models.Q(end__gte=datetime.now()) | models.Q(end__isnull=True)) - )) - class Meta: abstract = True @@ -84,19 +72,43 @@ class StatusModel(models.Model): status = StatusField(_('status')) status_changed = MonitorField(_('status changed'), monitor='status') - def __init__(self, *args, **kwargs): - super(StatusModel, self).__init__(*args, **kwargs) - for value, name in getattr(self, 'STATUS', ()): - try: - self._meta.get_field(name) - from django.core.exceptions import ImproperlyConfigured - raise ImproperlyConfigured("StatusModel: Model '%s' has a field named '%s' which " - "conflicts with a status of the same name." - % (self.__name__, name)) - except FieldDoesNotExist: - pass - self.__class__.add_to_class(value, QueryManager(status=value)) - class Meta: abstract = True +def add_status_query_managers(sender, **kwargs): + """ + Add a Querymanager for each status item dynamically. + """ + if not issubclass(sender, StatusModel): + return + for value, name in getattr(sender, 'STATUS', ()): + try: + sender._meta.get_field(name) + raise ImproperlyConfigured("StatusModel: Model '%s' has a field " + "named '%s' which conflicts with a " + "status of the same name." + % (sender.__name__, name)) + except FieldDoesNotExist: + pass + sender.add_to_class(value, QueryManager(status=value)) + +def add_timeframed_query_manager(sender, **kwargs): + """ + Addds a QueryManager for a specific timeframe + """ + if not issubclass(sender, TimeFramedModel): + return + try: + sender._meta.get_field('timeframed') + raise ValueError("Model '%s' has a field named 'timeframed' which " + "conflicts with the TimeFramedModel manager." % sender.__name__) + except FieldDoesNotExist: + pass + sender.add_to_class('timeframed', QueryManager( + (models.Q(start__lte=datetime.now) | models.Q(start__isnull=True)) & + (models.Q(end__gte=datetime.now) | models.Q(end__isnull=True)) + )) + + +models.signals.class_prepared.connect(add_status_query_managers) +models.signals.class_prepared.connect(add_timeframed_query_manager) diff --git a/model_utils/tests/models.py b/model_utils/tests/models.py index 298200e..5ebfe6f 100644 --- a/model_utils/tests/models.py +++ b/model_utils/tests/models.py @@ -18,6 +18,9 @@ class TimeStamp(TimeStampedModel): class TimeFrame(TimeFramedModel): pass +class TimeFrameManagerAdded(TimeFramedModel): + pass + class Monitored(models.Model): name = models.CharField(max_length=25) name_changed = MonitorField(monitor='name') @@ -36,6 +39,13 @@ class StatusPlainTuple(StatusModel): ('on_hold', _('on hold')), ) +class StatusManagerAdded(StatusModel): + STATUS = ( + ('active', _('active')), + ('deleted', _('deleted')), + ('on_hold', _('on hold')), + ) + class Post(models.Model): published = models.BooleanField() confirmed = models.BooleanField() diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index 2b3fef9..a025b13 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -7,8 +7,10 @@ from django.db.models.fields import FieldDoesNotExist from model_utils import ChoiceEnum, Choices from model_utils.fields import get_excerpt -from model_utils.tests.models import InheritParent, InheritChild, TimeStamp, \ - Post, Article, Status, StatusPlainTuple, TimeFrame, Monitored +from model_utils.managers import QueryManager +from model_utils.tests.models import (InheritParent, InheritChild, TimeStamp, + Post, Article, Status, StatusPlainTuple, TimeFrame, Monitored, + StatusManagerAdded, TimeFrameManagerAdded) class GetExcerptTests(TestCase): @@ -234,6 +236,10 @@ class TimeFramedModelTests(TestCase): end=self.now+timedelta(days=1)) self.assertEquals(TimeFrame.timeframed.count(), 1) +class TimeFrameManagerAddedTests(TestCase): + + def test_manager_avaiable(self): + self.assert_(isinstance(TimeFrameManagerAdded.timeframed, QueryManager)) class StatusModelTests(TestCase): def setUp(self): @@ -271,6 +277,10 @@ class StatusModelPlainTupleTests(StatusModelTests): self.on_hold = StatusPlainTuple.STATUS[2][0] self.active = StatusPlainTuple.STATUS[0][0] +class StatusManagerAddedTests(TestCase): + + def test_manager_avaiable(self): + self.assert_(isinstance(StatusManagerAdded.active, QueryManager)) class QueryManagerTests(TestCase): def setUp(self):