Django datetime проблемы (по умолчанию = datetime.now ()) - PullRequest
242 голосов
/ 05 мая 2010

У меня есть модель дб ниже:

from datetime import datetime    

class TermPayment(models.Model):
    # I have excluded fields that are irrelevant to the question
    date = models.DateTimeField(default=datetime.now(), blank=True)

Я добавляю новый экземпляр, используя ниже:

tp = TermPayment.objects.create(**kwargs)

Моя проблема: все записи в базе данных имеют одинаковое значение в поле даты, которое является датой первого платежа. После перезапуска сервера одна запись имеет новую дату, а другие записи совпадают с первой. Похоже, что некоторые данные кэшируются, но я не могу найти где.

база данных: mysql 5.1.25

django v1.1.1

Ответы [ 8 ]

524 голосов
/ 05 мая 2010

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

У Django есть функция, позволяющая выполнить то, что вы уже пытаетесь сделать:

date = models.DateTimeField(auto_now_add=True, blank=True)

или

date = models.DateTimeField(default=datetime.now, blank=True)

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

Дополнительную информацию можно получить в справочнике модели Django

85 голосов
/ 20 августа 2015

Вместо использования datetime.now вы должны действительно использовать from django.utils.timezone import now

Справка:

так что сделайте что-то вроде этого:

from django.utils.timezone import now


created_date = models.DateTimeField(default=now, editable=False)
26 голосов
/ 05 мая 2010

Из документации в поле по умолчанию для модели django:

Значение по умолчанию для поля. Это может быть значение или вызываемый объект. Если он вызывается, он будет вызываться каждый раз, когда создается новый объект.

Поэтому должно работать следующее:

date = models.DateTimeField(default=datetime.now,blank=True)
16 голосов
/ 31 марта 2015

У Давида был правильный ответ. Скобка () делает так, что callable timezone.now () вызывается каждый раз, когда оценивается модель. Если вы удалите () из timezone.now () (или datetime.now (), если используете наивный объект datetime), сделайте так:

default=timezone.now

Тогда все будет работать так, как вы ожидаете:
Новые объекты получат текущую дату при их создании, но эта дата не будет переопределяться каждый раз, когда вы выполняете manage.py makemigrations / migrate.

Я только что столкнулся с этим. Большое спасибо Дэвиду.

9 голосов
/ 05 мая 2010

datetime.now() оценивается при создании класса, а не при добавлении новой записи в базу данных.

Чтобы достичь желаемого, определите это поле как:

date = models.DateTimeField(auto_now_add=True)

Таким образом, в поле date будет установлена ​​текущая дата для каждой новой записи.

6 голосов
/ 20 августа 2013

Ответ на этот вопрос на самом деле неправильный.

Автоматическое заполнение значения (auto_now / auto_now_add отличается от значения по умолчанию). Значение по умолчанию будет фактически тем, что видит пользователь, если это совершенно новый объект. Что я обычно делаю, это:

date = models.DateTimeField(default=datetime.now, editable=False,)

Убедитесь, что если вы пытаетесь представить это на странице администратора, вы перечислили это как 'read_only' и указали имя поля

read_only = 'date'

Опять же, я делаю это, поскольку мое значение по умолчанию обычно не редактируется, а страницы администратора игнорируют нередактируемые, если не указано иное. Однако существует определенная разница между установкой значения по умолчанию и реализацией auto_add, который здесь является ключевым. Проверьте это!

6 голосов
/ 06 декабря 2011

datetime.now() оценивается один раз, когда создается экземпляр вашего класса. Попробуйте убрать круглые скобки, чтобы функция datetime.now была возвращена и затем оценена. У меня была такая же проблема с настройкой значений по умолчанию для моих DateTimeField s, и я написал свое решение здесь .

5 голосов
/ 05 мая 2010

Из справочника по языку Python, под Определения функций :

Значения параметров по умолчанию оцениваются при выполнении определения функции. Это означает, что выражение вычисляется один раз, когда функция определена, и что одно и то же «предварительно вычисленное» значение используется для каждого вызова.

К счастью, у Django есть способ сделать то, что вы хотите, если вы используете аргумент auto_now для DateTimeField:

date = models.DateTimeField(auto_now=True)

См. Документы Django для DateTimeField .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...