"関係マネージャ(related manager)"とは、1対多または多対多の関係するコンテキストで使用されるマネージャのことです。これは2つのケースで起こります:
ForeignKey
リレーションの "反対側"。つまり:
from django.db import models
class Blog(models.Model):
# ...
pass
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)
上記の例では、以下のメソッドがマネージャ blog.entry_set
で利用可能です。
ManyToManyField
リレーションの両側:
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
この例では、以下のメソッドは topping.pizza_set
と pizza.toppings
の両方で利用できます。
非同期バージョン: aadd()
リレーション先オブジェクトのセットに、指定したモデルオブジェクトを追加します。
例:
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.
上の例では、 ForeignKey
リレーションの場合、 QuerySet.update()
を使って更新を行います。これにはオブジェクトが既に保存されている必要があります。
引数 bulk=False
を使用することで、関係マネージャが e.save()
を呼び出して更新を行うことができます。
しかし、多対多のリレーションシップで add()
を使用すると、 save()
メソッドは呼び出しません (bulk
引数は存在しません)。 QuerySet.bulk_create()
を使用してリレーションシップを作成します。リレーションシップの作成時にカスタムロジックを実行する必要がある場合は、 m2m_changed
シグナルを待ち受けます。
すでに存在するリレーションに add()
を使っても、リレーションは複製されませんが、シグナルは発生します。
多対多のリレーションシップの場合、 add()
は *objs
引数としてモデルインスタンスかフィールドの値(通常は主キー)を受け付けます。
必要であれば、引数 through_defaults
を使用して、新しい 中間モデル インスタンスの値を指定します。呼び出し可能オブジェクトを through_defaults
辞書の値として使用することができ、中間インスタンスを作成する前に一度だけ評価されます。
非同期バージョン: acreate()
新しいオブジェクトを作成して保存し、リレーション先オブジェクトのセットに入れます。新しく作成されたオブジェクトを返します:
>>> b = Blog.objects.get(id=1)
>>> e = b.entry_set.create(
... headline="Hello", body_text="Hi", pub_date=datetime.date(2005, 1, 1)
... )
# No need to call e.save() at this point -- it's already been saved.
これは下記のコードと等価です(しかし、よりシンプルです):
>>> b = Blog.objects.get(id=1)
>>> e = Entry(blog=b, headline="Hello", body_text="Hi", pub_date=datetime.date(2005, 1, 1))
>>> e.save(force_insert=True)
リレーションシップを定義するモデルのキーワード引数を指定する必要はないことに注意してください。上の例では、 create()
にパラメータ blog
を渡していません。Django は新しい Entry
オブジェクトの blog
フィールドを b
に設定すべきであると判断します。
必要であれば、 through_defaults
引数を使用して、新しい 中間モデル インスタンスの値を指定します。呼び出し可能オブジェクトを through_defaults
辞書の値として使用できます。
非同期バージョン: aremove()
リレーション先オブジェクトのセットから指定されたモデルオブジェクトを削除します:
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
上記の例では add()
と同様に e.save()
が呼び出されて更新が行われます。しかし、多対多のリレーションシップで remove()
を使用すると、 QuerySet.delete()
を使用してリレーションシップを削除するので、モデルの save()
メソッドは呼び出されません。リレーションシップが削除されたときにカスタムコードを実行したい場合は、 m2m_changed
シグナルを待ち受けます。
多対多のリレーションシップの場合、 remove()
は *objs
引数としてモデルインスタンスかフィールドの値(通常は主キー)を受け付けます。
ForeignKey
オブジェクトでは、このメソッドは null=True
の場合のみ存在します。リレーション先フィールドを None
(NULL
) に設定できない場合、リレーション先オブジェクトを別のオブジェクトに追加せずに削除することはできません。上の例では、 b.entry_set()
から e
を削除することは e.blog = None
と等価であり、 blog
ForeignKey
には null=True
がないので、これは無効です。
ForeignKey
オブジェクトの場合、このメソッドは bulk
引数を受け取り、操作の実行方法を制御します。もし True
(デフォルト) なら、 QuerySet.update()
が使用されます。もし bulk=False
なら、代わりに個々のモデルインスタンスの save()
メソッドが呼び出されます。これはパフォーマンスを犠牲にし、 pre_save
シグナルと post_save
シグナルをトリガーします。
多対多のリレーションシップの場合、キーワード引数 bulk
は存在しません。
非同期バージョン: aclear()
リレーション先オブジェクトのセットからすべてのオブジェクトを削除します:
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()
これはリレーション先のオブジェクトを削除するのではなく、単に関連付けを解除するだけであることに注意してください。
remove()
と同様に、 clear()
は ForeignKey
で null=True
の場合にのみ使用可能で、 bulk
キーワード引数も受け付けます。
多対多のリレーションシップの場合、キーワード引数 bulk
は存在しません。
非同期バージョン: aset()
リレーション先のオブジェクトのセットを置き換えます:
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)
このメソッドには clear
引数を渡すことができます。もし False
(デフォルト) なら、 remove()
を使って新しいセットから欠けている要素を削除し、新しい要素だけを追加します。もし clear=True
なら、代わりに clear()
メソッドが呼び出され、セット全体が一度に追加されます。
ForeignKey
オブジェクトの場合、 bulk
引数は add()
と remove()
に渡されます。
多対多のリレーションシップの場合、キーワード引数 bulk
は存在しません。
set()
は複合操作であるため、競合状態になりやすいことに注意してください。例えば、 clear()
を呼び出してから add()
を呼び出すまでの間に、新しいオブジェクトがデータベースに追加される可能性があります。
多対多のリレーションシップの場合、 set()
は objs
引数としてモデルインスタンスかフィールド値(通常は主キー)のリストを受け付けます。
必要であれば、引数 through_defaults
を使用して、新しい 中間モデル インスタンスの値を指定します。呼び出し可能オブジェクトを through_defaults
辞書の値として使用することができ、中間インスタンスを作成する前に一度だけ評価されます。
注釈
add()
, aadd()
, create()
, acreate()
, remove()
, aremove()
, clear()
, aclear()
, set()
, そして aset()
はすべて、すべてのタイプのリレーション先のフィールドに対してデータベースの変更を即座に適用することに注意してください。つまり、リレーションシップのどちらの側でも save()
/asave()
を呼び出す必要はありません。
prefetch_related()
を使用すると、 add()
, aadd()
, remove()
, aremove()
, clear()
, aclear()
, set()
, aset()
メソッドがプリフェッチキャッシュをクリアします。
_meta
API
オフライン (Django 5.1):
HTML |
PDF |
ePub
Read the Docs により提供されています。
© 2005-2024 Django Software Foundation and individual contributors. Django is a registered trademark of the Django Software Foundation.