383

I have the below db model:

from datetime import datetime    

class TermPayment(models.Model):
    # I have excluded fields that are irrelevant to the question
    date = models.DateTimeField(default=datetime.now(), blank=True)

I add a new instance by using the below:

tp = TermPayment.objects.create(**kwargs)

My issue: all records in database have the same value in date field, which is the date of the first payment. After the server restarts, one record has the new date and the other records have the same as the first. It looks as if some data is cached, but I can't find where.

database: mysql 5.1.25

django v1.1.1

Shamanu4
  • 5,296
  • 2
  • 27
  • 31
  • 1
    Isn't possible to default to a function such as this?: `default=datetime.now` -- note, without calling as in `now()` Not the standard for DateTimeField, but... handy anycase. – viridis Apr 12 '13 at 11:50

10 Answers10

762

it looks like datetime.now() is being evaluated when the model is defined, and not each time you add a record.

Django has a feature to accomplish what you are trying to do already:

date = models.DateTimeField(auto_now_add=True, blank=True)

or

date = models.DateTimeField(default=datetime.now, blank=True)

The difference between the second example and what you currently have is the lack of parentheses. By passing datetime.now without the parentheses, you are passing the actual function, which will be called each time a record is added. If you pass it datetime.now(), then you are just evaluating the function and passing it the return value.

More information is available at Django's model field reference

Carson Myers
  • 37,678
  • 39
  • 126
  • 176
  • 256
    **important note**: using auto_now_add renders the field un-editable in the admin – Jiaaro May 05 '10 at 13:56
  • 7
    Great answer, thanks. Is there a way to express a more complex expression with datetime.now as a default? e.g. now + 30 days (the following doesn't work) `expiry = models.DateTimeField(default=datetime.now + timedelta(days=30))` – michela May 05 '11 at 13:34
  • 36
    @michela datetime.now is a function, and you're trying to add a timedelta to a function. You'll have to define your own callback to set the default value, like `def now_plus_30(): return datetime.now() + timedelta(days = 30)`, and then use `models.DateTimeField(default=now_plus_30)` – Carson Myers May 06 '11 at 06:24
  • 62
    Or you can of course do `default=lambda: datetime.now()+timedelta(days=30)` – Michael Mior Dec 19 '11 at 22:02
  • 46
    **BE AWARE** that using auto_now_add is **NOT** the same as using a default because the field will be ALWAYS equal to now (uneditable).. I know that this was already said, but it's not just a metter of the 'admin' page – VAShhh Jul 05 '13 at 15:28
  • But how do I set the models.DateField to current date instead of DateTimeField instead in the above example. I have tried using date = models.DateField(default=datetime.datetime.now().date) , but it does not evaluate to current date each day in the modelform Pl. guide http://stackoverflow.com/users/84478/carson-myers – user956424 Jan 09 '15 at 05:00
  • @user956424 Probably because you're still evaluating `now()` when defining the field - you'd need to do something like `date = models.DateField(default=lambda: datetime.datetime.now().date)` – Carson Myers Jan 09 '15 at 18:21
  • It displays in the model form with the above http://stackoverflow.com/users/84478/carson-myers – user956424 Jan 10 '15 at 04:20
  • @user956424 Then `lambda: datetime.datetime.now().date()`; I didn't know `now().date` was a function, sorry – Carson Myers Jan 12 '15 at 17:37
  • There's nothing to be sorry http://stackoverflow.com/users/84478/carson-myers can u suggest any other solution? – user956424 Jan 13 '15 at 02:52
  • 1
    This errors with `ValueError: Cannot serialize function: lambda` – David Schumann Aug 14 '15 at 10:19
  • @DavidNathan Did you set `serialize=True` on the field? According to what I found in the source code, you _can_ use a default function on a serialized field but it must be top level since it gets serialized by path name: https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L390 – Carson Myers Aug 14 '15 at 16:20
  • 3
    be aware that mixing fields with `default=datetime.now` and `auto_now_add` can cause errors when, for example calculating the difference between the two - since their timezones may differ. Its better to use `from django.utils.timezone import now` instead of `datetime.now` – Iftah Aug 02 '16 at 10:12
  • there is a difference between two mentioned answer.if you set 'auto_now_add=True' ,you can not change the value of date anymore. – Negar37 Apr 24 '20 at 12:23
  • So `datetime.now` will update this field every time the queryset gets updated/saved, but `datetime.now()` will not do anything if the queryset gets updated and saved, it will only do something one time, and that is when **the object was created / brand new object.** So it will give a default value if there are no value added. – AnonymousUser Jul 18 '22 at 05:29
196

Instead of using datetime.now you should be really using from django.utils.timezone import now

Reference:

so go for something like this:

from django.utils.timezone import now


created_date = models.DateTimeField(default=now, editable=False)
andilabs
  • 22,159
  • 14
  • 114
  • 151
  • 29
    This is a very important note! if you use datetime.now you can a local datetime that isn't timezone aware. If you later compare it to a field that was timestamped using `auto_now_add` (which is timezone aware) you can get wrong calculations because of errous timezone differences. – Iftah Aug 02 '16 at 10:10
  • 2
    This is definitely very important but doesn't really answer the question by itself. – Czechnology Jan 11 '17 at 20:05
  • 1
    definitively better way – Carmine Tambascia Oct 31 '18 at 19:27
34

From the documentation on the django model default field:

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

Therefore following should work:

date = models.DateTimeField(default=datetime.now,blank=True)
mykhal
  • 19,175
  • 11
  • 72
  • 80
  • 1
    This is only possible in django 1.8+ – David Schumann Aug 14 '15 at 10:23
  • @DavidNathan why is that? I think both options have been around since 1.4 or before, including the use of a callable for `default` (https://django-chinese-docs-14.readthedocs.io/en/latest/ref/models/fields.html#default) – Mark Jan 01 '17 at 14:41
  • I get this error `AttributeError: module 'datetime' has no attribute 'now'`. Fixed it by using `default=datetime.datetime.now` – Kwaku Biney Sep 26 '21 at 08:17
22

David had the right answer. The parenthesis () makes it so that the callable timezone.now() is called every time the model is evaluated. If you remove the () from timezone.now() (or datetime.now(), if using the naive datetime object) to make it just this:

default=timezone.now

Then it will work as you expect:
New objects will receive the current date when they are created, but the date won't be overridden every time you do manage.py makemigrations/migrate.

I just encountered this. Much thanks to David.

MicahT
  • 383
  • 3
  • 6
13

The datetime.now() is evaluated when the class is created, not when new record is being added to the database.

To achieve what you want define this field as:

date = models.DateTimeField(auto_now_add=True)

This way the date field will be set to current date for each new record.

Bartosz
  • 6,055
  • 3
  • 27
  • 17
9

datetime.now() is being evaluated once, when your class is instantiated. Try removing the parenthesis so that the function datetime.now is returned and THEN evaluated. I had the same issue with setting default values for my DateTimeFields and wrote up my solution here.

vishes_shell
  • 22,409
  • 6
  • 71
  • 81
David
  • 247
  • 3
  • 9
7

The answer to this one is actually wrong.

Auto filling in the value (auto_now/auto_now_add isn't the same as default). The default value will actually be what the user sees if its a brand new object. What I typically do is:

date = models.DateTimeField(default=datetime.now, editable=False,)

Make sure, if your trying to represent this in an Admin page, that you list it as 'read_only' and reference the field name

read_only = 'date'

Again, I do this since my default value isn't typically editable, and Admin pages ignore non-editables unless specified otherwise. There is certainly a difference however between setting a default value and implementing the auto_add which is key here. Test it out!

Andrew Harris
  • 1,975
  • 2
  • 13
  • 8
7

From the Python language reference, under Function definitions:

Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that that same “pre-computed” value is used for each call.

Fortunately, Django has a way to do what you want, if you use the auto_now argument for the DateTimeField:

date = models.DateTimeField(auto_now=True)

See the Django docs for DateTimeField.

ars
  • 120,335
  • 23
  • 147
  • 134
3

In Django 3.0 auto_now_add seems to work with auto_now

reg_date=models.DateField(auto_now=True,blank=True)

Mayur Dhurpate
  • 1,112
  • 4
  • 16
  • 34
3

if you need only DateField try this

date = models.DateField(auto_now=False, auto_now_add=False, null=True, blank=True)

if you need Both Date and Time try this

date = models.DateTimeField(auto_now_add=True, null=True, blank=True)
Sven Eberth
  • 3,057
  • 12
  • 24
  • 29