У меня такая модель:
class FooBar(models.Model):
createtime = models.DateTimeField(auto_now_add=True)
lastupdatetime = models.DateTimeField(auto_now=True)
Я хочу перезаписать два поля даты для некоторых экземпляров модели (используемых при переносе данных). Текущее решение выглядит так:
for field in new_entry._meta.local_fields:
if field.name == "lastupdatetime":
field.auto_now = False
elif field.name == "createtime":
field.auto_now_add = False
new_entry.createtime = date
new_entry.lastupdatetime = date
new_entry.save()
for field in new_entry._meta.local_fields:
if field.name == "lastupdatetime":
field.auto_now = True
elif field.name == "createtime":
field.auto_now_add = True
Есть ли лучшее решение?
auto_now(_add)
Ответы:
Недавно я столкнулся с такой ситуацией при тестировании своего приложения. Мне нужно было «принудительно» установить истекшую временную метку. В моем случае я сделал трюк, используя обновление набора запросов. Как это:
источник
update()
поведение как раз то, что нам нужно.Вы не можете отключить auto_now / auto_now_add другим способом, чем вы уже это сделали. Если вам нужна гибкость для изменения этих значений,
auto_now
/auto_now_add
- не лучший выбор. Часто бывает более гибким использованиеdefault
и / или переопределениеsave()
метода для выполнения манипуляций непосредственно перед сохранением объекта.Используя
default
замещенныйsave()
метод, одним из способов решения вашей проблемы было бы определение вашей модели следующим образом:В вашем коде, где вы хотите пропустить автоматическое изменение времени последнего обновления, просто используйте
Если ваш объект сохранен в интерфейсе администратора или в другом месте, save () будет вызываться без аргумента skip_lastupdatetime, и он будет вести себя так же, как и раньше, с
auto_now
.источник
auto_now_add
используйтеdefault
вместо этого.datetime.datetime.now
возвращает наивное datetime. Чтобы использовать датуfrom django.utils import timezone
и время с учетом часового пояса, используйте иmodels.DateTimeField(default=timezone.now)
см. Docs.djangoproject.com/en/1.9/topics/i18n/timezones/…createtime
поле, вам не нужно переопределятьsave()
. Достаточно заменитьauto_now_add=True
на аналогdefault=timezone.now, editable=False, blank=True
(согласно документации ). Последние два параметра обеспечивают аналогичное поведение в админке.Я использовал предложение, сделанное спрашивающим, и создал несколько функций. Вот пример использования:
Вот реализация:
Можно создать аналогичные функции, чтобы снова включить их.
источник
Clazz._meta.get_field_by_name(field_name)[0]
.Вы также можете использовать
update_fields
параметрsave()
и передавать своиauto_now
поля. Вот пример:Вот объяснение из документации Django: https://docs.djangoproject.com/en/stable/ref/models/instances/#specifying-which-fields-to-save
источник
auto_now
иauto_now_add
).Я пошел путем диспетчера контекста для повторного использования.
Используйте так:
Бум.
источник
Для тех, кто смотрит на это при написании тестов, есть библиотека Python под названием freezegun, которая позволяет имитировать время, поэтому, когда
auto_now_add
код запускается, он получает время, которое вы действительно хотите. Так:Его также можно использовать в качестве декоратора - см. Ссылку выше для получения базовой документации.
источник
Вы можете переопределить
auto_now_add
без специального кода.Я столкнулся с этим вопросом, когда пытался создать объект с определенной датой:
где
publication_date = models.DateField(auto_now_add=True)
.Вот что я сделал:
Это успешно отменено
auto_now_add
.В качестве более долгосрочного решения можно использовать
save
метод переопределения : https://code.djangoproject.com/ticket/16583источник
Мне нужно было отключить auto_now для поля DateTime во время миграции, и я смог это сделать.
источник
Я опаздываю на вечеринку, но, как и некоторые другие ответы, это решение, которое я использовал во время миграции базы данных. Отличие от других ответов заключается в том, что это отключает все поля auto_now для модели при условии, что на самом деле нет причин иметь более одного такого поля.
Затем, чтобы использовать его, вы можете просто сделать:
И он будет идти до конца и ядерного оружия всех ваших
auto_now
иauto_now_add
полей для всех классов моделей , которые Вы передаете в.источник
Немного более чистая версия диспетчера контекста из https://stackoverflow.com/a/35943149/1731460
Вы можете использовать его даже с фабриками (заводчик)
источник
копия Django - Models.DateTimeField - Динамическое изменение значения auto_now_add
Итак, сегодня днем я выяснил, и первая проблема - это как получить объект модели и где в коде. Я нахожусь в restframework в serializer.py, например, в
__init__
сериализаторе еще не может быть Модель. Теперь в to_internal_value вы можете получить класс модели после получения поля и после изменения свойств поля, как в этом примере:источник
Мне нужно было решение, которое будет работать с
update_or_create
, я пришел к этому решению на основе кода @andreaspelme.Единственное изменение состоит в том, что вы можете установить пропуск, установив для измененного поля
skip
не только фактическую передачу kwargskip_modified_update
save ().Просто
yourmodelobject.modified='skip'
и обновление будет пропущено!источник