Django поле modified_at с автоматическим обновлением на уровне базы данных
Мне нужно иметь поля modifed_at в моем Django проекте. Поле, которое обновляется каждый раз, когда строка обновляется в базе данных, независимо от того, откуда приходит обновление: через вызов .save()
или через queryset.update()
или даже когда обновления происходят в базе данных напрямую, а не из приложения Django.
существует свойство auto_now, которое не решает мою проблему согласно этому вопросу SO (основанному на документе Django).
Другие вопросы SO (такие как this и this) спрашивают то же самое, обновлять экземпляр при каждом изменении не только .save()
Эту проблему можно решить с помощью триггеров, как сказано здесь, но таким образом нам нужно написать один и тот же триггер для каждого поля modifed_at в модели.
как обсуждалось в этом Django ticket эта проблема не будет рассмотрена и решена в Django. даже предложенный патч только обновляет экземпляр, если он меняется через Django.
единственный способ, который приходит мне в голову, это сделать что-то вроде этого в mixin. mixin, который при наследовании создает триггер для полей с auto_now=True. возможно, изменить SQL, когда Django создает SQL для создания модели. но я не знаю, как это реализовать.
Итак, у меня два вопроса:
- как лучше всего добиться обновления на уровне базы данных для полей modified_at ?
- Если предложенный мной способ является лучшим вариантом, как его реализовать?
Я хотел бы иметь решение, не зависящее от базы данных, но, к вашему сведению, в настоящее время я использую PostgreSQL.
Поэтому вы можете использовать для этого поле Django auto_now
.
Если вы хотите автоматически заполнять поле DateTimeField при создании нового объекта, вы можете сделать следующее: created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("created_at"))
Если вы хотите обновлять поле при каждом обновлении объекта, вы можете сделать следующее: updated_at = models.DateTimeField(auto_now=True, verbose_name=_("updated at"))
Для получения дополнительной информации вы можете обратиться здесь
Как вы сказали, если вы используете триггеры, вам придется создавать триггеры для каждой таблицы.
Однако, чтобы упростить эту задачу, можно создать файл миграции для создания/уничтожения триггера. Вот пример.
Тогда это будет просто копирование файла миграции каждый раз, когда вы создаете новую модель.
Редактировать:
Вы даже можете переопределить команду makemigrations
, чтобы автоматически добавить создание триггерного шага к операциям начального файла миграций. Вот ответ, который показывает как переопределить команды управления .