Проблемы с datetime в Django (по умолчанию = datetime.now())

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

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

Джанго v1.1.1

Ответ 1

похоже, что 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 ссылка на поле модели

Ответ 2

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

Ссылка:

так что перейдите на что-то вроде этого:

from django.utils.timezone import now


created_date = models.DateTimeField(default=now, editable=False)

Ответ 3

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

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

Следовательно, следующее должно работать:

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

Ответ 4

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

default=timezone.now

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

Я просто столкнулся с этим. Огромное спасибо Дэвиду.

Ответ 5

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

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

date = models.DateTimeField(auto_now_add=True)

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

Ответ 6

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

Ответ 7

Ответ на этот вопрос на самом деле неверен.

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

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

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

read_only = 'date'

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

Ответ 8

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

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

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

date = models.DateTimeField(auto_now=True)

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