views:

1443

answers:

3

For Django 1.1.

I have this in my models.py:

class User(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

When updating a row I get :

[Sun Nov 15 02:18:12 2009] [error] /home/ptarjan/projects/twitter-meme/django/db/backends/mysql/base.py:84: Warning: Column 'created' cannot be null
[Sun Nov 15 02:18:12 2009] [error]   return self.cursor.execute(query, args)

the relevant part of my db is:

  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,

Is this cause for concern?

Side question: in my admin tool, those 2 fields aren't showing up. Is that expected?

+7  A: 

Any field with the auto_now attribute set will also inherit editable=False and therefore will not show up in the admin panel. There has been talk in the past about making the auto_now and auto_now_add arguments go away, and although they still exist, I feel you're better off just using a custom save() method.

So, to make this work properly, I would recommend not using auto_now or auto_now_add and instead define your own save() method to make sure that created is only updated if id is not set (such as when the item is first created), and have it update modified every time the item is saved.

I have done the exact same thing with other projects I have written using Django, and so your save() would look like this:

import datetime

class User(models.Model):
    created     = models.DateTimeField(editable=False)
    modified    = models.DateTimeField()

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        if not self.id:
            self.created = datetime.datetime.today()
        self.modified = datetime.datetime.today()
        super(User, self).save(*args, **kwargs)

Hope this helps!

Edit in response to comments:

The reason why I just stick with overloading save() vs. relying on these field arguments is two-fold:

  1. The aforementioned ups and downs with their reliability. These arguments are heavily reliant on the way each type of database that Django knows how to interact with treats a date/time stamp field, and seems to break and/or change between every release. (Which I believe is the impetus behind the call to have them removed altogether).
  2. The fact that they only work on DateField, DateTimeField, and TimeField, and by using this technique you are able to automatically populate any field type every time an item is saved.

To address why the OP saw the error, I don't know exactly, but it looks like created isn't even being populated at all, despite having auto_now_add=True. To me it stands out as a bug, and underscores item #1 in my little list above: auto_now and auto_now_add are flaky at best.

jathanism
But what is the source of author's problem? Does auto_now_add sometimes work improperly?
Dmitry Risenberg
I'm with you Dmitry. I'm curious as to why the two fields threw errors.. And I'm even more curious as to why you think writing your own custom save() method is better?
hora
Writing a custom `save()` on each of my models is much more pain than using the `auto_now` (as I like to have these fields on all my models). Why don't those params work?
Paul Tarjan
A: 

Is this cause for concern?

No, Django automatically adds it for you while saving the models, so, it is expected.

Side question: in my admin tool, those 2 fields aren't showing up. Is that expected?

Since these fields are auto added, they are not shown.

To add to the above, as synack said, there has been a debate on the django mailing list to remove this, because, it is "not designed well" and is "a hack"

Writing a custom save() on each of my models is much more pain than using the auto_now

Obviously you don't have to write it to every model. You can write it to one model and inherit others from it.

But, as auto_add and auto_now_add are there, I would use them rather than trying to write a method myself.

Lakshman Prasad
+2  A: 

Bah... Not enough reputation to comment... But I wanted to point out that the opinion expressed in the accepted answer is somewhat outdated. According to more recent discussions (django bugs #7634 and #12785; again, not enough reputation to link), auto_now and auto_now_add are not going anywhere, and even if you go to the original discussion, you'll find strong arguments against the RY (as in DRY) in custom save methods.

A better solution has been offered (custom field types), but didn't gain enough momentum to make it into django. You can write your own in three lines (it's Jacob Kaplan-Moss' suggestion).

Shai Berger