rajagopalx
rajagopalx

Reputation: 3104

How to use timedelta with timezone.now as default?

In Django models, How to increment the date field using timezone.now?

working:

end_date = models.DateTimeField(default=timezone.now() + timezone.timedelta(days=365))

Not Working

end_date = models.DateTimeField(default=timezone.now + timezone.timedelta(days=365))

I think timezone.now is a function which runs every time when the object is created. so that error occurs.

Upvotes: 5

Views: 12477

Answers (2)

Moses Koledoye
Moses Koledoye

Reputation: 78536

You could use a function:

def f():
   return timezone.now() + timezone.timedelta(days=365)
...
end_date = models.DateTimeField(default=f)

The current time in that timezone is the added with the timedelta anytime a new end_date is created by default:

>>> from django.utils import timezone
>>> from datetime import timedelta
>>> def f():
...    return timezone.now() + timezone.timedelta(days=365)
... 
>>> f()
datetime.datetime(2018, 6, 25, 19, 42, 49, 761389, tzinfo=<UTC>)
>>> f()
datetime.datetime(2018, 6, 25, 19, 43, 2, 953158, tzinfo=<UTC>)

Sample run with Django:

In [1]: from testapp import models

In [2]: models.Test.objects.create().date_added
Out[2]: datetime.datetime(2018, 6, 25, 20, 5, 28, 316214, tzinfo=<UTC>)

In [3]: models.Test.objects.create().date_added
Out[3]: datetime.datetime(2018, 6, 25, 20, 5, 33, 114624, tzinfo=<UTC>)

Upvotes: 11

Kostas Livieratos
Kostas Livieratos

Reputation: 1067

A good approach would be to use the post_save signal. Import it with from django.db.models.signals import post_save and then create a handler function like this:

def handler_function(sender, instance, created, **kwargs):
    if sender == YourModel and created:
        instance.end_date = timezone.now() + timezone.timedelta(days=365)
        instance.save()

post_save.connect(handler_function, sender=YourModel)

This will work for sure, I hope this also applies to your case. Let me know if you need further help!

Upvotes: 0

Related Questions