在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.id
和force_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.instance
和self.instance.fieldname
与新值进行比较