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 database is:
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
Is this cause for concern?
Side question: in my admin tool, those two fields aren't showing up. Is that expected?
I think the easiest (and maybe most elegant) solution here is to leverage the fact that you can set
default
to a callable. So, to get around admin's special handling of auto_now, you can just declare the field like so:It's important that you don't use
timezone.now()
as the default value wouldn't update (i.e., default gets set only when the code is loaded). If you find yourself doing this a lot, you could create a custom field. However, this is pretty DRY already I think.No, Django automatically adds it for you while saving the models, so, it is 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"
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
andauto_now_add
are there, I would use them rather than trying to write a method myself.I needed something similar today at work. Default value to be timezone.now(), but editable both in admin and class views inheriting from FormMixin, so for created in my models.py the following code fulfilled those requirements:
For DateTimeField, I guess remove the .date() from the function and change datetime.date to datetime.datetime or better timezone.datetime. I haven't tried it with DateTime, only with Date.
Here's the answer if you're using south and you want to default to the date you add the field to the database:
Choose option 2 then: datetime.datetime.now()
Looks like this:
Any field with the
auto_now
attribute set will also inheriteditable=False
and therefore will not show up in the admin panel. There has been talk in the past about making theauto_now
andauto_now_add
arguments go away, and although they still exist, I feel you're better off just using a customsave()
method.So, to make this work properly, I would recommend not using
auto_now
orauto_now_add
and instead define your ownsave()
method to make sure thatcreated
is only updated ifid
is not set (such as when the item is first created), and have it updatemodified
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: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:django.utils.timezone.now()
vs.datetime.datetime.now()
, because it will return a TZ-aware or naivedatetime.datetime
object depending onsettings.USE_TZ
.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 havingauto_now_add=True
. To me it stands out as a bug, and underscores item #1 in my little list above:auto_now
andauto_now_add
are flaky at best.If you alter your model class like this:
Then this field will show up in my admin change page