4

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?

Deano
  • 1,136
  • 10
  • 19

4 Answers4

4

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
  • 4,479
  • 1
  • 21
  • 20
  • 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 Jul 16 '10 at 09:15
4

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 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.

nikola
  • 2,241
  • 4
  • 30
  • 42
  • thanks prometheus, i was not aware of command extensions. I heart python/django ... however, there are many ways to do things! – Deano Dec 28 '09 at 17:43
2

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
  • 17,605
  • 2
  • 49
  • 65
  • 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 Dec 24 '09 at 18:43
  • You're right, I was moving to fast without enough caffeine. Kibitzer's answer is dead-on. – Peter Rowell Dec 24 '09 at 19:49
1

Note that auto_now_add and auto_now uses pre_save, which not working when bulk_create or update. Thus in your MySQL, for example, date_added field will be '0000-00-00 00:00:00' and it is possible to get warning: 'Warning: Column 'date_added' cannot be null'. So you can use auto_now* but you should be careful.

znotdead
  • 161
  • 2
  • 5