Django: timezone.now vs timezone.now()
In python everything is an object, including functions. This means you can affect a function to a variable:
>>> from django.utils import timezone
>>> foo = timezone.now
>>> foo
<function django.utils.timezone.now>
>>> foo()
datetime.datetime(2016, 7, 7, 9, 11, 6, 489063)
A function is a callable object:
>>> callable(foo)
True
>>> callable(foo())
False
When default
receives a callable, the callable is called each time a default value is requested.
On the other hand, when you call timezone.now()
prior to setting default
, the value is given and fixed. As a reminder, the following line is executed only once at server start up, since it is a class attribute:
datetime_released = models.DateTimeField(default=timezone.now())
and thus timezone.now()
is executed only once. Passing a callable timezone.now
makes it possible to recalculate the value whenever it needs to be.
The difference is that timezone.now
is a callable that gets executed at runtime, while timezone.now()
returns the output of that function.
For the models.DateTimeField
, you need to use the callable. Better still, just set auto_now_add
which does this for you:
datetime_released = models.DateTimeField(auto_now_add=True)
The filter on the other hand does not accept a callable - it requires a value. Hence you must evaluate timezone.now()
when passing this as an argument to the filter.
In self.filter(date_available__lte = timezone.now())
you want to make a query to the DB based on the current time. So you need it in string format.
In datetime_released = models.DateTimeField(default=timezone.now)
you want default to be current time. So you cannot have a string there. Instead you provide a function which can return current time.