added TimeStampedModel

--HG--
extra : convert_revision : carl%40dirtcircle.com-20090702201429-hph32omqgfgrga52
This commit is contained in:
Carl Meyer 2009-07-02 16:14:29 -04:00
parent ed72ca3aba
commit 2d018ca847
5 changed files with 82 additions and 3 deletions

View file

@ -22,10 +22,29 @@ But when you iterate over ``nearby_places``, you'll get only ``Place``
instances back, even for objects that are "really" ``Restaurant`` or
``Bar``. If you have ``Place`` inherit from ``InheritanceCastModel``,
you can just call the ``cast()`` method on each ``Place`` and it will
return an instance of the proper subtype, ``Restaurant`` or ``Bar``.
return an instance of the proper subtype, ``Restaurant`` or ``Bar``::
from model_utils.models import InheritanceCastModel
class Place(InheritanceCastModel):
...
class Restaurant(Place):
...
nearby_places = Place.objects.filter(location='here')
for place in nearby_places:
restaurant_or_bar = place.cast()
...
.. note::
This is inefficient for large querysets, as it results in n
queries to the subtype tables. It would be possible to write a
QuerySet subclass that could reduce this to k queries, where there
are k subtypes in the inheritance tree.
TimeStampedModel
================
This abstract base class just provides self-updating ``created`` and
``modified`` fields on any model that inherits it.

29
model_utils/fields.py Normal file
View file

@ -0,0 +1,29 @@
from datetime import datetime
from django.db import models
class AutoCreatedField (models.DateTimeField):
"""
A DateTimeField that automatically populates itself at
object creation.
By default, sets editable=False, default=datetime.now.
"""
def __init__ (self, *args, **kwargs):
kwargs.setdefault('editable', False)
kwargs.setdefault('default', datetime.now)
super(AutoCreatedField, self).__init__(*args, **kwargs)
class AutoLastModifiedField (AutoCreatedField):
"""
A DateTimeField that updates itself on each save() of the model.
By default, sets editable=False and default=datetime.now.
"""
def pre_save (self, model_instance, add):
value = datetime.now()
setattr(model_instance, self.attname, value)
return value

View file

@ -1,6 +1,8 @@
from django.db import models
from django.contrib.contenttypes.models import ContentType
from model_utils.fields import AutoCreatedField, AutoLastModifiedField
class InheritanceCastModel(models.Model):
"""
An abstract base class that provides a ``real_type`` FK to ContentType.
@ -24,3 +26,17 @@ class InheritanceCastModel(models.Model):
class Meta:
abstract = True
class TimeStampedModel (models.Model):
"""
An abstract base class model that provides self-updating
``created`` and ``modified`` fields.
"""
created = AutoCreatedField()
modified = AutoLastModifiedField()
class Meta:
abstract = True

View file

@ -1,6 +1,6 @@
from django.db import models
from model_utils.models import InheritanceCastModel
from model_utils.models import InheritanceCastModel, TimeStampedModel
class InheritParent(InheritanceCastModel):
pass
@ -8,3 +8,5 @@ class InheritParent(InheritanceCastModel):
class InheritChild(InheritParent):
pass
class TimeStamp(TimeStampedModel):
pass

View file

@ -1,7 +1,7 @@
from django.test import TestCase
from django.contrib.contenttypes.models import ContentType
from model_utils.tests.models import InheritParent, InheritChild
from model_utils.tests.models import InheritParent, InheritChild, TimeStamp
class InheritanceCastModelTests(TestCase):
def setUp(self):
@ -19,3 +19,16 @@ class InheritanceCastModelTests(TestCase):
def testCast(self):
obj = InheritParent.objects.get(pk=self.child.pk).cast()
self.assertEquals(obj.__class__, InheritChild)
class TimeStampedModelTests(TestCase):
def testCreated(self):
t1 = TimeStamp.objects.create()
t2 = TimeStamp.objects.create()
self.assert_(t2.created > t1.created)
def testModified(self):
t1 = TimeStamp.objects.create()
t2 = TimeStamp.objects.create()
t1.save()
self.assert_(t2.modified < t1.modified)