リレーション先オブジェクトのリファレンス¶
- class RelatedManager¶
"関係マネージャ(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の両方で利用できます。
- add(*objs, bulk=True, through_defaults=None)¶
- aadd(*objs, bulk=True, through_defaults=None)¶
非同期バージョン:
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辞書の値として使用することができ、中間インスタンスを作成する前に一度だけ評価されます。
- create(through_defaults=None, **kwargs)¶
- acreate(through_defaults=None, **kwargs)¶
非同期バージョン:
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辞書の値として使用できます。
- remove(*objs, bulk=True)¶
- aremove(*objs, bulk=True)¶
非同期バージョン:
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と等価であり、blogForeignKeyにはnull=Trueがないので、これは無効です。ForeignKeyオブジェクトの場合、このメソッドはbulk引数を受け取り、操作の実行方法を制御します。もしTrue(デフォルト) なら、QuerySet.update()が使用されます。もしbulk=Falseなら、代わりに個々のモデルインスタンスのsave()メソッドが呼び出されます。これはパフォーマンスを犠牲にし、pre_saveシグナルとpost_saveシグナルをトリガーします。多対多のリレーションシップの場合、キーワード引数
bulkは存在しません。
- clear(bulk=True)¶
- aclear(bulk=True)¶
非同期バージョン:
aclear()リレーション先オブジェクトのセットからすべてのオブジェクトを削除します:
>>> b = Blog.objects.get(id=1) >>> b.entry_set.clear()
これはリレーション先のオブジェクトを削除するのではなく、単に関連付けを解除するだけであることに注意してください。
remove()と同様に、clear()はForeignKeyでnull=Trueの場合にのみ使用可能で、bulkキーワード引数も受け付けます。多対多のリレーションシップの場合、キーワード引数
bulkは存在しません。
- set(objs, bulk=True, clear=False, through_defaults=None)¶
- aset(objs, bulk=True, clear=False, through_defaults=None)¶
非同期バージョン:
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()メソッドがプリフェッチキャッシュをクリアします。