Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: timezone.now vs timezone.now()

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?

like image 200
43Tesseracts Avatar asked Jul 07 '16 04:07

43Tesseracts


People also ask

What does timezone NOW () return?

timezone. now() useful. This function returns the current date and time as a naive datetime when USE_TZ = False and as an aware datetime when USE_TZ = True .

What timezone does datetime NOW ()?

In the documentation, it can also be seen that, since Python 3.6, datetime. now() can be called without any arguments and return the correct local result (naive datetime s are presumed to be in the local time zone).

What is the default timezone setting in Django America?

Django's timezone is set to UTC by default. If your timezone is not UTC, you can change it using the procedure below: Open the setting.py file in the directory of our project.


2 Answers

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.

like image 63
Antoine Pinsard Avatar answered Sep 19 '22 07:09

Antoine Pinsard


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.

like image 44
solarissmoke Avatar answered Sep 18 '22 07:09

solarissmoke