在Django模型自定义save()方法中,你应该如何识别一个新的对象?

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

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

self.pk is None: 

在新的Model对象中返回True,除非对象具有UUIDField作为其primary_key

您可能不得不担心的是,除了id以外的字段是否存在唯一性约束(例如,其他字段上的次要唯一索引)。 在这种情况下,您仍然可以获得新的logging,但无法保存。

检查self.id假定id是模型的主键。 更通用的方法是使用PK快捷键 。

is_new = self.pk is None

另一种检查self.pk方法是检查模型的self._state

self._state.adding == True创造

self._state.adding == False更新

我从这个页面得到它

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

Django的O / RMfunction特别讨厌的黑客基本上是检查是否有什么东西在PK的位置,如果是这样做一个更新,否则做一个插入(这优化到一个插入,如果PK是无)。

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

如果你真的想知道你必须做什么的O / RM做,并在数据库中查找。

当然你的代码中有一个具体的例子,因此很有可能self.pk == None告诉你所有你需要知道的东西,但这不是一个通用的解决scheme。

检查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 

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

你可以连接到post_save信号发送一个“创build”kwargs,如果真的,你的对象已被插入。

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

这个谈话我迟到了,但是我遇到了一个self.pk的问题,当它有一个默认值时,它就会被填充。

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

date_created = models.DateTimeField(auto_now_add=True)

从这里你可以去

created = self.date_created is None

宁愿用pk代替id

 if not self.pk: do_something() 

这是通常的做法。

id会在第一次保存到db的时候给出

对于即使当你有一个UUIDField作为主键时也是有效的解决scheme(正如其他人注意到的不是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, eg # instance.generate_avatar() # instance.send_email_notification() pass 

这个callback会阻止save方法,所以你可以做一些事情,比如触发通知,或者在你的响应通过线路发回之前进一步更新模型,无论你是使用表单还是使用Django REST框架进行AJAX调用。 当然,负责任地使用,并卸下繁重的任务到一个工作队列,而不是让你的用户等待:)

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

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