Django: timezone.now vs timezone.now()

Question:

I am in the process of upgrading my project from Django 1.8.2 to 1.9.7 and I’m getting this warning:

WARNINGS:
my_app.my_model.date_available: (fields.W161) Fixed default value provided.
HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. 
If you want to have the current date as default, use `django.utils.timezone.now

Here’s the line from my_app/models.py:

from django.utils import timezone
...
class my_model(models.Model):
    ...
    datetime_released = models.DateTimeField(default=timezone.now() )

If I remove the parentheses and instead use:

datetime_released = models.DateTimeField(default=timezone.now )

The Django warning goes away. What’s the difference between the two?


In another area of my project I am using timezone.now() in a queryset filter:

def date_available(self):
        return self.filter(date_available__lte = timezone.now())

Here, if I remove the parentheses, an error is thrown:

TypeError: expected string or buffer


I can get both of these two work by adding/removing the parenthesis as required, but what is the difference between timezone.now() and timezone.now and why do they cause warnings/errors in these cases?

Asked By: 43Tesseracts

||

Answers:

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.

Answered By: solarissmoke

now() gets executed when the model is loaded and returns a datetime object / time string at loading. (hence the Django warning!)
(The model file if fully executed when the server starts)

now will pass on the now method, and will get executed only when the class/model gets instantiated, creating the time stamp at the right time (the correct way, and what most people are trying to achieve).

In the filter example, it only gets called when the filter function is called.
if you don’t executed (now()) and will feed the method, and will never generate the required datetime object. (error, expected a string, got, something else)

Answered By: gtalarico

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.

Answered By: Arun Ghosh

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.

Answered By: Antoine Pinsard

timezone.now() returns the current timestamp when when model is loaded. On the other hand, timezone.now is passed as an argument to the function and it is called whenever the object is created (on class instantiation)

in the following code

def date_available(self):
    return self.filter(date_available__lte = timezone.now())

the function date_availabe needs a function string to parse as a function when it returns self.filter.

Answered By: akhilesh upadhyaya
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.