May 21, 2012

Django auto_now Removal Gotcha

classical guitar Django auto now Removal GotchaThe latest Django revisions have removed the shortcut handlers "auto_now&quot and "auto_now_add". This didn’t look like a very big deal to replace. I simply did what was suggested in a django-users thread.

The problem was that after I did that, my live code seemed to work fine, but my test cases had several repeatable errors that I just couldn’t reproduce on the live server or at the command line.

The Fix

The fix involves overriding the "save" method, like so (quoting the thread)


class MyModel(models.Model):
    self.created = models.DatetimeField()
    self.modified = models.DatetimeField()

    def save(self):
        if not self.id:
            self.created = datetime.datetime.now()
        else:
            self.modified = datetime.datetime.now()

        super(MyModel, self).save()

What went wrong

After a lot of debugging and shrewd guessing, I finally had the eureka moment. The problem is that some of the test code was directly instantiating objects via calls like MyModel.objects.get_or_create(name="this", field="that"). In some places the test cases were using the even simpler MyModel.objects.create(name="this", field="that").

It finally occurred to me while walking the dog this morning that creating objects this way will skip the overridden "save()" method. I rushed to the computer to test my theory, and found that if I replaced:


MyModel.objects.get_or_create(name="this", field="that")

with this:


try:
    m = MyModel.objects.get(name="this", field="that")
except MyModel.DoesNotExist:
    m = MyModel(name="this", field="that")
    m.save()

everything worked perfectly.

So, watch out for that gotcha now that you can’t use auto_now in models any more.

Share and Enjoy:
  • services sprite Django auto now Removal Gotcha
  • services sprite Django auto now Removal Gotcha
  • services sprite Django auto now Removal Gotcha
  • services sprite Django auto now Removal Gotcha
  • services sprite Django auto now Removal Gotcha
  • services sprite Django auto now Removal Gotcha
  • services sprite Django auto now Removal Gotcha
  • services sprite Django auto now Removal Gotcha

Related posts:

  1. First use of the Django Magic Removal Last night I took a break from my most recent...
  2. Django Magic Removal, this time for real Despite my earlier initial successes using the Django Magic-Removal Branch,...
  3. Django Formatter Mixin Class I've always disliked having to write __repr__ methods for my...
  4. Howto Reset The Admin Password in Django I keep needing to do this, darn it! I leave...
  5. A Django Killer App – Web Table Data Yet another great use for Django is to make trivial...

About Bruce Kroeze

Comments

  1. There’s something else going on here, I suspect. Both the create() and get_or_create() method do call your model’s save() method. In fact, get_or_create() is implemented more or less exactly as in your second example.

    If you want to trace throught the code, MyModel.objects.get_or_create() calls django.db.models.manager.Manager.get_or_create() which just passes off the real work to django.db.models.query.QuerySet.get_or_create() and you can see that calling obj.save() when required.

    So it would be interesting to understand what is really changing when you make the substitution you suggest above.

  2. Ramin says:

    Minor typo.

    models.DatetimeField() should be models.DateTimeField() (with capitalized ‘T’).

  3. Nice to be visiting your blog again, it may be months for me. Well this post that i’ve been waited for so long. I need this post to total my assignment in the college, and it has exact same topic with your article. Many thanks, excellent write about.

Speak Your Mind

*