在django模型自定义save()方法中,您应该如何识别新对象?

时间:2009-05-25 18:45:28

标签: django django-models

当我保存新记录(不更新现有记录)时,我想在Django模型对象的save()方法中触发一个特殊操作。

检查(self.id!= None)是否必要且足以保证自我记录是新的而不是更新?这可能会忽略任何特殊情况吗?

13 个答案:

答案 0 :(得分:176)

self.pk is None:

在新的Model对象中返回True,除非该对象的UUIDFieldprimary_key

您可能需要担心的极端情况是,除id之外的字段是否存在唯一性约束(例如,其他字段上的辅助唯一索引)。在这种情况下,您仍然可以手头有新记录,但无法保存。

答案 1 :(得分:128)

检查self.pk的其他方式我们可以检查模型的self._state

self._state.adding is True创建

self._state.adding is False正在更新

我从page

获得了它

答案 2 :(得分:42)

检查self.id假设id是模型的主键。更通用的方法是使用pk shortcut

is_new = self.pk is None

答案 3 :(得分:38)

self.pk == None的检查足以确定是否要在数据库中插入或更新对象。

Django O / RM有一个特别讨厌的黑客,基本上是检查PK位置是否有东西,如果是这样做UPDATE,否则执行INSERT(如果PK为None,则优化为INSERT)

之所以这样做是因为您可以在创建对象时设置PK。虽然在主键的序列列中不常见,但这不适用于其他类型的主键字段。

如果您真的想知道您必须执行O / RM所做的事情并查看数据库。

当然,您的代码中有一个特定的案例,因此self.pk == None很可能会告诉您所有需要知道的内容,但它不是一般解决方案。< / p>

答案 4 :(得分:8)

您可以连接到发送“已创建”的kwargs的post_save信号,如果为true,则表示您的对象已插入。

http://docs.djangoproject.com/en/stable/ref/signals/#post-save

答案 5 :(得分:7)

检查self.idforce_insert标志。

if not self.pk or kwargs.get('force_insert', False):
    self.created = True

# call save method.
super(self.__class__, self).save(*args, **kwargs)

#Do all your post save actions in the if block.
if getattr(self, 'created', False):
    # So something
    # Do something else

这很方便,因为您新创建的对象(self)具有pk

答案 6 :(得分:5)

我对这个对话已经很晚了,但是我遇到了一个问题,当self.pk有一个与之关联的默认值时会填充它。

我解决这个问题的方法是在模型中添加date_created字段

date_created = models.DateTimeField(auto_now_add=True)

从这里你可以去

created = self.date_created is None

答案 7 :(得分:3)

而是使用 pk 而不是 id

if not self.pk:
  do_something()

答案 8 :(得分:3)

对于即使您将UUIDField作为主键(如果您只是覆盖None而其他人已注明不是save)也可以使用的解决方案插入Django的post_save信号。将其添加到 models.py

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=MyModel)
def mymodel_saved(sender, instance, created, **kwargs):
    if created:
        # do extra work on your instance, e.g.
        # instance.generate_avatar()
        # instance.send_email_notification()
        pass

此回调将阻止save方法,因此您可以执行诸如触发通知之类的操作,或者在通过网络发回响应之前更新模型,无论您是使用表单还是Django REST框架AJAX调用。当然,负责任地使用并将繁重的任务卸载到作业队列而不是让用户等待:)

答案 9 :(得分:1)

这是常用的方法。

在第一次保存到db

时会给出id

答案 10 :(得分:0)

在以上所有情况下都可以使用吗?

if self.pk is not None and <ModelName>.objects.filter(pk=self.pk).exists():
...

答案 11 :(得分:0)

> def save_model(self, request, obj, form, change):
>         if form.instance._state.adding:
>             form.instance.author = request.user
>             super().save_model(request, obj, form, change)
>         else:
>             obj.updated_by = request.user.username
> 
>             super().save_model(request, obj, form, change)

答案 12 :(得分:-3)

要知道您是要更新还是插入对象(数据),请在表单中使用self.instance.fieldname。在表单中定义一个干净的函数,并检查当前值条目是否与前一个相同,如果不是,则更新它。

self.instanceself.instance.fieldname与新值进行比较