リレーション先オブジェクトのリファレンス¶
- 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
と等価であり、blog
ForeignKey
には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()
メソッドがプリフェッチキャッシュをクリアします。