Django: timezone.now vs timezone.now()

Я занимаюсь обновлением своего проекта с Django 1.8.2 до 1.9.7, и я получаю это предупреждение:

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

Здесь строка из my_app/models.py:

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

Если я удалю круглые скобки и вместо этого использую:

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

Предупреждение Django исчезает. Какая разница между ними?


В другой области моего проекта я использую timezone.now() в фильтрах запросов:

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

Здесь, если я удаляю круглые скобки, возникает ошибка:

TypeError: expected string or buffer


Я могу получить обе эти две работы, добавив/удалив скобки по мере необходимости, но в чем разница между timezone.now() и timezone.now и почему они вызывают предупреждения или ошибки в этих случаях?

Ответы

Ответ 1

В python все это объект, включая функции. Это означает, что вы можете воздействовать на функцию на переменную:

>>> from django.utils import timezone
>>> foo = timezone.now
>>> foo
<function django.utils.timezone.now>
>>> foo()
datetime.datetime(2016, 7, 7, 9, 11, 6, 489063)

Функция - вызываемый объект:

>>> callable(foo)
True
>>> callable(foo())
False

Когда по default принимает вызываемый, вызываемый вызывается каждый раз, когда запрашивается значение по умолчанию.

С другой стороны, когда вы вызываете timezone.now() перед установкой по default, значение задается и фиксируется. Напоминаем, что следующая строка выполняется только один раз при запуске сервера, так как это атрибут класса:

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

и поэтому timezone.now() выполняется только один раз. Передача вызываемого timezone.now теперь позволяет пересчитывать значение всякий раз, когда это необходимо.

Ответ 2

Разница в том, что timezone.now является вызываемым, который запускается во время выполнения, а timezone.now() возвращает результат этой функции.

Для models.DateTimeField вам нужно использовать вызываемый. Еще лучше, просто установите auto_now_add который сделает это за вас:

datetime_released = models.DateTimeField(auto_now_add=True)

Фильтр, с другой стороны, не принимает вызываемый - для этого требуется значение. Следовательно, вы должны оценить timezone.now() передавая это как аргумент фильтру.

Ответ 3

now() запускается при загрузке модели и возвращает при загрузке строку объекта/времени datetime. (отсюда предупреждение Django!) (Файл модели, если он полностью выполняется при запуске сервера)

теперь передаст метод now и будет выполнен только тогда, когда экземпляр класса/модели будет создан, создавая отметку времени в нужное время (правильный путь и то, что большинство людей пытается достичь).

В примере фильтра он вызывается только при вызове функции фильтра. если вы не выполнили (now()) и будете кормить метод, и никогда не создадите требуемый объект datetime. (ошибка, ожидаемая строка, полученная, что-то еще)

Ответ 4

В self.filter(date_available__lte = timezone.now()) вы хотите сделать запрос к БД на основе текущего времени. Поэтому вам это нужно в строчном формате.

В datetime_released = models.DateTimeField(default=timezone.now) вы хотите, чтобы по умолчанию было текущее время. Таким образом, у вас не может быть строки. Вместо этого вы предоставляете функцию, которая может возвращать текущее время.

Ответ 5

timezone.now() возвращает текущую временную метку, когда загружается модель. С другой стороны, timezone.now передается в качестве аргумента функции и вызывается всякий раз, когда создается объект (при создании экземпляра класса)

в следующем коде

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

функция date_availabe нуждается в строке функции для анализа как функции, когда она возвращает self.filter.