回答:
更新:self._state
プライベートインスタンス変数ではないが、競合を回避するためにそのように名前が付けられた明確化により、チェックself._state.adding
はチェックするための望ましい方法です。
self.pk is None:
オブジェクトが持っていない限り、新しいモデルオブジェクト内にTrueを返しUUIDField
、そのようprimary_key
。
あなたが心配しなければならないかもしれない主なケースは、ID以外のフィールドに一意性の制約があるかどうかです(たとえば、他のフィールドのセカンダリ一意インデックス)。その場合、まだ新しいレコードを持っている可能性がありますが、それを保存することはできません。
is not
ではなく、使用する必要!=
がありNone
ます
models.OneToOneField(OtherModel, primary_key=True)
。つまり、を介して別のモデルが拡張されています。使用する必要があると思いますself.pk
UUIDField
aを主キーとして使用する場合、self.pk
決してではありませんNone
。
モデルをself.pk
チェックできるチェックself._state
の代替方法
self._state.adding is True
作成
self._state.adding is False
更新
このページから入手した
self._state.adding
動作の詳細についてはよくわかりませんが、呼び出し後にFalse
確認すると常に等しいように見えるという警告があります:github.com/django/django/blob/stable/1.10.x/django/db/models/ …super(TheModel, self).save(*args, **kwargs)
_state
非公開ではありません。のように_meta
、フィールド名との混同を避けるために、アンダースコアが前に付けられます。(リンクされたドキュメントでの使用方法に注意してください。)
is_new = self._state.adding
はそれsuper(MyModel, self).save(*args, **kwargs)
から、そしてそれからif is_new: my_custom_logic()
super(...).save()
。
のチェックでself.pk == None
は、オブジェクトがデータベースに挿入または更新されるかどうかを判断するには不十分です。
Django O / RMは特に厄介なハックを特徴としており、基本的にはPKの位置に何かがあるかどうかを確認し、ある場合はUPDATEを実行します。
これを行う必要があるのは、オブジェクトの作成時にPKを設定できるためです。主キーのシーケンス列がある場合は一般的ではありませんが、これは他のタイプの主キーフィールドには適用されません。
本当に知りたい場合は、O / RMが行うことを実行して、データベースを調べる必要があります。
もちろん、コードに特定のケースがあり、そのためself.pk == None
に知っておく必要があるすべてのことを示している可能性が高いですが、それは一般的な解決策ではありません。
UUIDField
、aを主キーとして使用する場合に特に当てはまります。キーはDBレベルで入力されないためself.pk
、常にTrue
です。
「作成された」クワーグを送信するpost_save信号に接続するだけで、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
新しく作成したオブジェクト(self)に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
メソッドをブロックするため、フォームを使用している場合でも、AJAX呼び出しにDjango RESTフレームワークを使用している場合でも、応答を送信する前に、トリガー通知やモデルの更新などを行うことができます。もちろん、ユーザーを待たせるのではなく、責任を持って使用し、重いタスクをジョブキューにオフロードしてください:)
むしろ使用PKの代わりにID:
if not self.pk:
do_something()
これは上記のすべてのシナリオで機能しますか?
if self.pk is not None and <ModelName>.objects.filter(pk=self.pk).exists():
...
> 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