How to set a Django model field's default value to a function call / callable (e.g., a date relative to the time of model object creation)

The question is misguided. When creating a model field in Django, you are not defining a function, so function default values are irrelevant:

from datetime import datetime, timedelta
class MyModel(models.Model):
  # default to 1 day from now
  my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))

This last line is not defining a function; it is invoking a function to create a field in the class.

PRE Django 1.7

Django lets you pass a callable as the default, and it will invoke it each time, just as you want:

from datetime import datetime, timedelta
class MyModel(models.Model):
  # default to 1 day from now
  my_date = models.DateTimeField(default=lambda: datetime.now() + timedelta(days=1))

Django 1.7+

Please note that since Django 1.7, usage of lambda as default value is not recommended (c.f. @stvnw comment). The proper way to do this is to declare a function before the field and use it as a callable in default_value named arg:

from datetime import datetime, timedelta

# default to 1 day from now
def get_default_my_date():
  return datetime.now() + timedelta(days=1)

class MyModel(models.Model):
  my_date = models.DateTimeField(default=get_default_my_date)

More information in the @simanas answer below


Doing this default=datetime.now()+timedelta(days=1) is absolutely wrong!

It gets evaluated when you start your instance of django. If you are under apache it will probably work, because on some configurations apache revokes your django application on every request, but still you can find you self some day looking through out your code and trying to figure out why this get calculated not as you expect.

The right way of doing this is to pass a callable object to default argument. It can be a datetime.today function or your custom function. Then it gets evaluated every time you request a new default value.

def get_deadline():
    return datetime.today() + timedelta(days=20)

class Bill(models.Model):
    name = models.CharField(max_length=50)
    customer = models.ForeignKey(User, related_name='bills')
    date = models.DateField(default=datetime.today)
    deadline = models.DateField(default=get_deadline)

There's an important distinction between the following two DateTimeField constructors:

my_date = models.DateTimeField(auto_now=True)
my_date = models.DateTimeField(auto_now_add=True)

If you use auto_now_add=True in the constructor, the datetime referenced by my_date is "immutable" (only set once when the row is inserted to the table).

With auto_now=True, however, the datetime value will be updated every time the object is saved.

This was definitely a gotcha for me at one point. For reference, the docs are here:

https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield