Answers:
更新:澄清了self._state
不是私有实例变量,而是以避免冲突的方式命名,self._state.adding
现在检查是更可取的检查方法。
self.pk is None:
在新的Model对象中返回True,除非该对象的UUIDField
为其primary_key
。
您可能要担心的极端情况是除id以外的其他字段是否存在唯一性约束(例如,其他字段上的辅助唯一索引)。在这种情况下,您仍然可以拥有新记录,但是无法保存它。
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.pk == None
是不足够的,以确定该物体将被插入或更新数据库。
Django O / RM具有一个特别讨厌的技巧,该技巧基本上是检查PK位置是否有东西,如果有,则执行UPDATE,否则检查INSERT(如果PK为None,则将其优化为INSERT)。
它必须执行此操作的原因是,允许在创建对象时设置PK。尽管在具有主键的序列列的地方并不常见,但这不适用于其他类型的主键字段。
如果您真的想知道,您必须执行O / RM的操作并查看数据库。
当然,您的代码中有一个特定的案例,很可能会self.pk == None
告诉您所有您需要知道的情况,但这不是一般的解决方案。
UUIDField
用作主键的情况下尤其如此:该键不在数据库级别填充,因此self.pk
始终填充True
。
您可以只连接到post_save信号,该信号发送一个“已创建”的kwarg,如果为true,则表示已插入您的对象。
http://docs.djangoproject.com/en/stable/ref/signals/#post-save
ATOMIC_REQUESTS
,所以我不确定默认值。
检查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
这很方便,因为您新创建的对象(自己)具有它的pk
价值
对于即使您具有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调用,您都可以执行触发通知之类的操作或进一步更新模型,然后再通过网络发送回响应。当然,负责任地使用并将繁重的任务卸载到作业队列中,而不是让用户等待:)
> 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)
UUIDField pk