views:

168

answers:

3

I am adding date_added and date_modified fields to a bunch of common models in my current project. I am subclassing models.Model and adding the appropriate fields, but I want to add automated save behavior (i.e: evey time anyone calls MyModel.save(), the date_modified field gets updated. I see two approaches: overriding the save() method or adding a pre_save signal handler in the abstract base class.

class CommonData(models.Model):
    date_added = models.DateTimeField(default=datetime.datetime.today,null=False,blank=False)
    date_modified = models.DateTimeField(default=datetime.datetime.today,null=True,blank=True)

    # register a handler for the pre_save to update date_modified
    def pre_save_handler(sender, **kwargs):
        date_modified = datetime.datetime.today

    def __init__():
        pre_save.connect(pre_save_handler, sender=self)

or

class CommonData(models.Model):
    date_added = models.DateTimeField(default=datetime.datetime.today,null=False,blank=False)
    date_modified = models.DateTimeField(default=datetime.datetime.today,null=True,blank=True)

    # overriding save 
    def save(force_insert=False,force_update=False):
        date_modified = datetime.datetime.now
        return models.Model.save(force_insert, force_update)

I'm new to Django and Python and wondered which approach was more "django"? Which is more efficient? which is the "right" way to do this?

+2  A: 

You can define these in an Abstract Base Class and then inherit from that. It's sort of like having a MixIn that also defines model fields.

Peter Rowell
Thanks Peter, that's what I was doing, my question was a wee bit more about the best way to implement the default functionality: signals verus method overrides. I guess the signal is more like a mixin and the method override is more like having default functionality no?
Deano
You're right, I was moving to fast without enough caffeine. Kibitzer's answer is dead-on.
Peter Rowell
+3  A: 

Did you try looking at DateTimeField's auto_now=True and auto_now_add=True? They do just what you need automatically. Otherwise, there is no real difference between doing save override and signal handling - in fact, pre_save signal is being called from django model's save method.

Docs: http://docs.djangoproject.com/en/dev/ref/models/fields/#datefield

kibitzer
awesome, thanks kibitzer! yes i guess i shoulda rtfm'd
Deano
auto_now and auto_now_add are considered unreliable now. Better to set the dates in the save method. That is what the other suggested solutions (with ABCs) use.
hopla
+3  A: 

Since you're new to Django, you might find the Django Command Extensions useful:

http://code.google.com/p/django-command-extensions/

... which conveniently includes a TimeStampedModel which you can derive your Models from:

http://code.google.com/p/django-command-extensions/wiki/ModelExtensions

An abstract base class model that provides self-managed "created" and "modified" fields.

prometheus
thanks prometheus, i was not aware of command extensions. I heart python/django ... however, there are many ways to do things!
Deano