Я хочу вызвать специальное действие в методе save () объекта модели Django, когда я сохраняю новую запись (не обновляя существующую запись).
Является ли проверка (self.id! = None) необходимой и достаточной, чтобы гарантировать, что собственная запись является новой и не обновляется? Какие-нибудь особые случаи это может упускать из виду?
django
django-models
MikeN
источник
источник
UUIDField pk
Ответы:
Обновлено: с пояснением,
self._state
которое не является частной переменной экземпляра, но названо таким образом, чтобы избежать конфликтов, проверкаself._state.adding
теперь является предпочтительным способом проверки.возвращает True в новом объекте Model, если только объект не имеет
UUIDField
егоprimary_key
.Угловой случай, о котором вам, возможно, придется беспокоиться, это наличие ограничений уникальности для полей, отличных от идентификатора (например, вторичных уникальных индексов для других полей). В этом случае у вас все еще может быть новая запись, но вы не сможете ее сохранить.
источник
is not
а не!=
при проверке идентичности сNone
объектомmodels.OneToOneField(OtherModel, primary_key=True)
. Я думаю, что вам нужно использоватьself.pk
UUIDField
в качестве первичного ключа,self.pk
никогдаNone
.Альтернативный способ проверки
self.pk
мы можем проверитьself._state
модельself._state.adding is True
созданиеself._state.adding is False
обновлениеЯ получил это с этой страницы
источник
self._state.adding
работает, но справедливое предупреждение, что оно кажется всегда равным,False
если вы проверяете его после вызоваsuper(TheModel, self).save(*args, **kwargs)
: github.com/django/django/blob/stable/1.10.x/django/db/models/ …_state
не частный; например_meta
, с префиксом подчеркивания, чтобы избежать путаницы с именами полей. (Обратите внимание на то, как это используется в связанной документации.)is_new = self._state.adding
тогдаsuper(MyModel, self).save(*args, **kwargs)
и потомif is_new: my_custom_logic()
Проверка
self.id
предполагает, чтоid
это первичный ключ для модели. Более общий способ - использовать ярлык pk .is_new = self.pk is None
источник
super(...).save()
.Проверка на
self.pk == None
это не достаточно , чтобы определить , если объект будет вставлен или обновлены в базе данных.Django O / RM имеет особенно неприятный хак, который в основном должен проверить, есть ли что-то в позиции PK и, если это так, сделать UPDATE, в противном случае сделать INSERT (это оптимизируется до INSERT, если PK - None).
Причина, по которой он должен это делать, заключается в том, что вам разрешено устанавливать PK при создании объекта. Хотя это редко встречается, когда у вас есть столбец последовательности для первичного ключа, это не относится к другим типам полей первичного ключа.
Если вы действительно хотите знать, вы должны делать то, что делает O / RM, и искать в базе данных.
Конечно, в вашем коде есть конкретный случай, и вполне вероятно, что он
self.pk == None
говорит вам все, что вам нужно знать, но это не общее решение.источник
UUIDField
в качестве первичного ключа: ключ не заполняется на уровне БД, поэтомуself.pk
всегдаTrue
.Вы можете просто подключиться к сигналу post_save, который посылает «созданные» kwargs, если true, ваш объект был вставлен.
http://docs.djangoproject.com/en/stable/ref/signals/#post-save
источник
ATOMIC_REQUESTS
, так что я не совсем уверен по умолчанию.Проверьте
self.id
иforce_insert
флаг.Это удобно, потому что ваш вновь созданный объект (self) имеет
pk
значениеисточник
Я очень опаздываю на этот разговор, но столкнулся с проблемой заполнения self.pk, когда с ним связано значение по умолчанию.
Как я обошёл это, добавив поле date_created к модели
date_created = models.DateTimeField(auto_now_add=True)
Отсюда вы можете пойти
created = self.date_created is None
источник
Для решения, которое также работает, даже если у вас есть
UUIDField
первичный ключ (что, как отметили другие,None
если вы просто переопределитеsave
), вы можете подключиться к сигналу Django post_save . Добавьте это к своим models.py :Этот обратный вызов заблокирует
save
метод, так что вы можете делать такие вещи, как триггерные уведомления или обновлять модель, прежде чем ваш ответ будет отправлен обратно по проводной связи, используете ли вы формы или инфраструктуру Django REST для вызовов AJAX. Конечно, используйте ответственно и переносите тяжелые задачи в очередь на работу вместо того, чтобы заставлять пользователей ждать :)источник
лучше использовать pk вместо id :
источник
Это обычный способ сделать это.
Идентификатор будет дан при первом сохранении в БД
источник
Будет ли это работать для всех вышеупомянутых сценариев?
источник
источник
Чтобы узнать, обновляете ли вы или вставляете объект (данные), используйте
self.instance.fieldname
в своей форме. Определите чистую функцию в своей форме и проверьте, совпадает ли текущая запись значения с предыдущей, если нет, то вы обновляете ее.self.instance
иself.instance.fieldname
сравнить с новым значениемисточник