30

This issue has been occurring on and off for a few weeks now, and it's unlike any that has come up with my project.

Two of the models that are used have a timestamp field, which is by default set to timezone.now().

This is the sequence that raises error flags:


  • Model one is created at time 7:30 PM

  • Model two is created at time 10:00 PM, but in the MySQL database it's stored as 7:30 PM!

Every model that is created has its time stamp saved under 7:30 PM, not the actual time, until a certain duration passes. Then a new time is set and all the following models have that new time... Bizzare


Some extra details which may help in discovering the issue:

I have a bunch of methods that I use to strip my timezones of their tzinfo's and replace them with UTC.

This is because I'm doing a timezone.now() - creationTime calculation to create a: "model was posted this long ago" feature in the project. However, this really should not be the cause of the problem.

I don't think using datetime.datetime.now() will make any difference either.

Anyway, thanks for the help!

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Lucas Ou-Yang
  • 5,505
  • 13
  • 43
  • 62
  • 2
    I bet the problem "is fixed" for the first record *after* the server process restarts (and perhaps only/all new records inserted the same minute of the server restart). Please show the code that uses/sets/establishes this default value. I suspect that it is only evaluated *once* (when the first record is created) and not updated for subsequent records. –  Nov 05 '12 at 04:39
  • Your prediction is correct! What makes you think this and why would it be happening? – Lucas Ou-Yang Nov 05 '12 at 06:04

3 Answers3

70

Just ran into this last week for a field that had default=date.today(). If you remove the parentheses (in this case, try default=timezone.now) then you're passing a callable to the model and it will be called each time a new instance is saved. With the parentheses, it's only being called once when models.py loads.

Jamey Sharp
  • 8,363
  • 2
  • 29
  • 42
  • 1
    This is very cool, thanks for the response. The function pass is rather misleading because since starting out with django as an amateaur, every single guide that I've read and the books even all have had datetime.datetime.now() or timezone.now() set as default for timestamps, it's just become something i've done automatically for all my timestamps! – Lucas Ou-Yang Nov 05 '12 at 06:05
  • I suppose doing it wrong this way would appear to work if you only deployed your Django apps with old-fashioned CGI; and of course you have to test over a period of hours or days to notice these timestamps not updating... But if this is widespread advice it doesn't give me confidence in those authors' testing. :-/ – Jamey Sharp Nov 05 '12 at 06:09
  • 3
    I'm not sure what examples would ever suggest calling `datetime.now()`. By the time the field function receives that argument, it's just a datetime object. – Yuji 'Tomita' Tomita Nov 05 '12 at 06:54
  • what if i am calling timezone.now() in views.py file to use in queryset – Vinay Jul 26 '20 at 17:16
23

Just set the parameter auto_now_add like this.

timestamp = models.DateTimeField(auto_now_add=True)

Update:

Please don't use auto_now_add. It is not the recommended way, instead do this:

from django.utils import timezone

timestamp = models.DateTimeField(default=timezone.now)
Rag Sagar
  • 2,314
  • 1
  • 18
  • 21
0

You should set timezone.now without () to DateTimeField() as a default value as shown below. *Don't set timezone.now() with () because the default date and time become when the Django server starts (Unchanged) and don't set datetime.now because UTC is not saved correctly in database when TIME_ZONE = 'UTC' which is default in settings.py:

from django.utils import timezone
# Don't set "timezone.now()" and "datetime.now" ↓ 
timestamp = models.DateTimeField(default=timezone.now)
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129