2010-08-31 1 views
15

Я использую сигнал pre_save от Django для реализации auto_now_add. В Интернете много дискуссий о том, почему вы должны или не должны его реализовывать самостоятельно. Я не комментирую это. Ни о том, следует ли мне переписывать функцию сохранения (у меня есть много моделей, которые используют auto_now_add, поэтому использование сигналов имеет смысл).Django pre_save signal: проверить, не создан ли экземпляр экземпляра, существует ли kwargs ['created'] (все еще)?

Мой вопрос:
Я хотел бы проверить, создан или обновлен экземпляр. Согласно некоторым источникам в Интернете, это может быть сделано путем тестирования, если kwargs['created'] имеет значение True. Однако 'created' не отображается в моем kwargs, даже если экземпляр создан. Мне просто интересно, было ли это когда-либо или что оно исчезло волшебным образом. Я знаю, что я мог бы также проверить, установлен ли kwargs['instance'].id (это действительно работает для меня), но я хотел бы знать, существует ли kwargs ['created'].

+1

Следует иметь в виду, что если экземпляр id/pk установлен, что не обязательно означает, что объект существует в базе данных. Обычный пример: если эти экземпляры загружаются из __fixtures__. –

+0

@Botondus: Есть ли лучший способ (чтобы избежать проблемы, о которой вы упоминаете), чтобы проверить, был ли экземпляр вновь создан или он обновляется во время pre_save? – Heyl1

+0

Да, если PK установлен, вам действительно нужно запросить базу данных, чтобы точно определить, создан ли экземпляр или нет. Что-то вроде: MyModel.objects.filter (pk = pk_val) .exists() Фактически он реализован аналогично в внутренних функциях Django: http://code.djangoproject.com/browser/django/trunk/django/db/ model/base.py # L493 –

ответ

16

В соответствии с последним Django documentation, pre_save НЕ отправляет аргумент created. Post_save однако does. Я не мог найти ссылку на отправку сигнала created с version 1.0.

+1

Большое спасибо за ваш ответ. Я, должно быть, неправильно понял источники и предположил, что «созданный» также появился в сигнале pre_save. Это действительно имеет смысл, когда вы думаете об этом. Спасибо, что прояснил это для меня! – Heyl1

26

Атрибут основного ключа, обычно назначаемый базой данных при первом сохранении экземпляра. Таким образом, вы можете использовать что-то вроде if instance.pk is None

+0

Не работает, если вы используете натуральный ключ! – Chris

+0

@phasetwenty Вы можете заблокировать таблицу и дополнительно проверить, существует ли запись с таким естественным ключом. Или использовать суррогатный ключ как первичный и естественный как вторичный. –

7

Я не уверен, что это рекомендуемый способ, но метод @ Radagast не работал для меня (не уверен, что его, потому что я использую пользовательские Pk).

Я попробовал следующее (не уверен, что это лучший способ):

@receiver(pre_save, sender=YourModelName, weak=False,) 
def presave_payment_model_check(sender, instance=None, created=False, **kwargs): 
    #Reference: https://stackoverflow.com/questions/11561722/django-what-is-the-role-of-modelstate 
    if instance._state.adding is True: 
     # we would need to create the object 
     print "Creating an object" 
    else: 
     #we are updating the object 
     print "Updating an object" 

Ссылка: Django : What is the role of ModelState?

+5

... правда, правда? –

1

Использование instance._state.adding является наиболее логичным подходом, как вы сможете сказать, что состояние модели существует или является новым, независимо от того, назначен ли первичный ключ или нет.

Смежные вопросы