Search code examples
djangodjango-modelsparameterslambdadefault

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)


EDITED:

How can I set a Django field's default to a function that gets evaluated each time a new model object gets created?

I want to do something like the following, except that in this code, the code gets evaluated once and sets the default to the same date for each model object created, rather than evaluating the code each time a model object gets created:

from datetime import datetime, timedelta

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

ORIGINAL:

I want to create a default value for a function parameter such that it is dynamic and gets called and set each time the function is called. How can I do that? e.g.,

from datetime import datetime

def mydatetime(date=datetime.now()):
    print date

mydatetime() 
mydatetime() # prints the same thing as the previous call; but I want it to be a newer value

Specifically, I want to do it in Django, e.g.,

from datetime import datetime, timedelta

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

Solution

  • 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)