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.