オブジェクトが保存されている場合は、通常、_if obj.pk
_をチェックしてknwoをチェックします。ただし、一部のフィールドに_primary_key = True
_を設定している場合、これは機能しません。たとえば、UserProfile
にuser = models.OneToOneField(User, primary_key=True)
を設定します。
Djangoモデルがデータベースに保存されているかどうかを確認するための正規の方法は何ですか?
重要な注意事項(19年5月6日現在):モデルでUUIDフィールド(またはその他の内部ID生成方法)を使用している場合は、コメントに記載されているように_self._state.adding
_を使用してください。
実際には、_obj.pk
_が最も標準的な方法です。 Djangoオブジェクト自体が保存されているかどうかは、多くの場合それ自体が「認識」していません。 the Djangoモデルインスタンス参照 によると、主キーセットが既にある場合は、挿入する前にデータベース内のIDを選択して、onsave()
呼び出しをチェックします。
user = models.OneToOneField(..., primary_key=True)
を設定しても、_.pk
_属性は正しい主キー(おそらく_user_id
_)をポイントし、同じプロパティであるかのように使用して設定できます。
オブジェクトが保存された後に知りたい場合は、 post_saveシグナル をキャッチできます。この信号はモデルの保存時に発生し、必要に応じて、_obj.was_saved = True
_などの独自のアプリケーション固有の属性をモデルに追加できます。 Djangoはインスタンスをクリーンに保つためにこれを回避しますが、これを自分で実行できなかった理由はありません。以下に最小限の例を示します。
_from Django.db.models.signals import post_save
from myapp.models import MyModel
def save_handler(sender, instance, **kwargs):
instance.was_saved = True
post_save.connect(save_handler, sender=MyModel)
_
あるいは、_sender=
_引数を指定せずに信号を接続するだけで、アプリ内のallモデルに対してこの関数を機能させることができます。ただし、インポートする他の誰かのモデルインスタンスのプロパティをオーバーライドすると、未定義の動作を作成する可能性があります。
現在、次のことを確認できます。
_self._state.adding
_
この値は、データベースにまだ追加されていないオブジェクトのQuerySet.iterator()
によって設定されます。この値は、オブジェクトの構築後に設定されるため、__init__()
メソッドではまだ使用できません。
obj
がMyModel
のインスタンスであるとしましょう。次に、次のコードブロックを使用して、データベースにその主キーを持つインスタンスが既に存在するかどうかを確認します。
if obj.pk is None:
# Definitely doesn't exist, since there's no `pk`.
exists = False
else:
# The `pk` is set, but it doesn't guarantee exists in db.
try:
obj_from_db = MyModel.objects.get(pk=obj.pk)
exists = True
except MyModel.DoesNotExist:
exists = False
これはobj.pk is None
、あなたができるから
obj = MyModel()
obj.pk = 123
その後
obj.pk is None # False
これは、自動インクリメントid
フィールドを主キーとして使用せず、代わりに自然キーを使用する場合でも、非常に可能性が高くなります。
または、マシューがコメントで指摘したように、
obj.delete()
その後、あなたはまだ持っています
obj.pk is None # False
@キャストの答えは良かったが、私は不完全だと思う。単体テストでオブジェクトがデータベースにあるかどうかを判断するために使用するコードは、次のとおりです。その下で、_obj.pk is None
_のチェックよりも優れていると思う理由を説明します。
_from Django.test import TestCase
class TestCase(TestCase):
def assertInDB(self, obj, msg=None):
"""Test for obj's presence in the database."""
fullmsg = "Object %r unexpectedly not found in the database" % obj
fullmsg += ": " + msg if msg else ""
try:
type(obj).objects.get(pk=obj.pk)
except obj.DoesNotExist:
self.fail(fullmsg)
def assertNotInDB(self, obj, msg=None):
"""Test for obj's absence from the database."""
fullmsg = "Object %r unexpectedly found in the database" % obj
fullmsg += ": " + msg if msg else ""
try:
type(obj).objects.get(pk=obj.pk)
except obj.DoesNotExist:
return
else:
self.fail(fullmsg)
_
注:モデル名にobjects
以外のカスタムマネージャーを使用する場合は、上記のコードを慎重に使用してください。 (Djangoを取得して、デフォルトのマネージャーが何であるかを知る方法があると確信しています。)さらに、/assert(Not)?InDB/
はPEP 8メソッド名ではないことを知っています。しかし、私はunittest
パッケージの残りが使用するスタイルを使用しました。
assertInDB(obj)
がassertIsNotNone(obj.pk)
よりも優れていると思う理由は、次のような場合です。次のモデルがあるとします。
_from Django.db import models
class Node(models.Model):
next = models.OneToOneField('self', null=True, related_name='prev')
_
Node
は二重リンクリストをモデル化します。外部キーを使用して各ノードに任意のデータをアタッチでき、末尾はNode
objであり、_obj.next is None
_となります。デフォルトでは、DjangoはSQL制約_ON DELETE CASCADE
_をNode
の主キーに追加します。ここで、list
ノード長さn _nodes[i].next == nodes[i + 1]
_ for i in [0、n-1)。 nodes[0].delete()
を呼び出すとします。 Django 1.5.1のPython 3.3でのテストでは、_nodes[i].pk is not None
_ for i for [1 、n)および_nodes[0].pk is None
_のみ。ただし、上記の/assert(Not)?InDB/
メソッドは、[1のiの_nodes[i]
_を正しく検出しました、n)は実際に削除されました。