Related objects reference¶
-
class
RelatedManager
¶ A "related manager" is a manager used in a one-to-many or many-to-many related context. This happens in two cases:
The "other side" of a
ForeignKey
relation. That is:from django.db import models class Reporter(models.Model): # ... pass class Article(models.Model): reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
In the above example, the methods below will be available on the manager
reporter.article_set
.Both sides of a
ManyToManyField
relation:class Topping(models.Model): # ... pass class Pizza(models.Model): toppings = models.ManyToManyField(Topping)
In this example, the methods below will be available both on
topping.pizza_set
and onpizza.toppings
.
-
add
(*objs, bulk=True, through_defaults=None)¶ 関係オブジェクトのセットに、指定したモデルオブジェクトを追加します。
実装例:
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.add(e) # Associates Entry e with Blog b.
In the example above, in the case of a
ForeignKey
relationship,QuerySet.update()
is used to perform the update. This requires the objects to already be saved.You can use the
bulk=False
argument to instead have the related manager perform the update by callinge.save()
.Using
add()
with a many-to-many relationship, however, will not call anysave()
methods (thebulk
argument doesn't exist), but rather create the relationships usingQuerySet.bulk_create()
. If you need to execute some custom logic when a relationship is created, listen to them2m_changed
signal, which will triggerpre_add
andpost_add
actions.Using
add()
on a relation that already exists won't duplicate the relation, but it will still trigger signals.add()
also accepts the field the relation points to as an argument. The above example can be rewritten asb.entry_set.add(234)
.Use the
through_defaults
argument to specify values for the new intermediate model instance(s), if needed.Changed in Django 2.2:The
through_defaults
argument was added.
-
create
(through_defaults=None, **kwargs)¶ Creates a new object, saves it and puts it in the related object set. Returns the newly created object:
>>> 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.
This is equivalent to (but much simpler than):
>>> 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)
Note that there's no need to specify the keyword argument of the model that defines the relationship. In the above example, we don't pass the parameter
blog
tocreate()
. Django figures out that the newEntry
object'sblog
field should be set tob
.Use the
through_defaults
argument to specify values for the new intermediate model instance, if needed.Changed in Django 2.2:The
through_defaults
argument was added.
-
remove
(*objs, bulk=True)¶ Removes the specified model objects from the related object set:
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
Similar to
add()
,e.save()
is called in the example above to perform the update. Usingremove()
with a many-to-many relationship, however, will delete the relationships usingQuerySet.delete()
which means no modelsave()
methods are called; listen to them2m_changed
signal if you wish to execute custom code when a relationship is deleted.Similarly to
add()
,remove()
also accepts the field the relation points to as an argument. The above example can be rewritten asb.entry_set.remove(234)
.For
ForeignKey
objects, this method only exists ifnull=True
. If the related field can't be set toNone
(NULL
), then an object can't be removed from a relation without being added to another. In the above example, removinge
fromb.entry_set()
is equivalent to doinge.blog = None
, and because theblog
ForeignKey
doesn't havenull=True
, this is invalid.For
ForeignKey
objects, this method accepts abulk
argument to control how to perform the operation. IfTrue
(the default),QuerySet.update()
is used. Ifbulk=False
, thesave()
method of each individual model instance is called instead. This triggers thepre_save
andpost_save
signals and comes at the expense of performance.For many-to-many relationships, the
bulk
keyword argument doesn't exist.
-
clear
(bulk=True)¶ Removes all objects from the related object set:
>>> b = Blog.objects.get(id=1) >>> b.entry_set.clear()
Note this doesn't delete the related objects -- it just disassociates them.
Just like
remove()
,clear()
is only available onForeignKey
s wherenull=True
and it also accepts thebulk
keyword argument.For many-to-many relationships, the
bulk
keyword argument doesn't exist.
-
set
(objs, bulk=True, clear=False, through_defaults=None)¶ Replace the set of related objects:
>>> new_list = [obj1, obj2, obj3] >>> e.related_set.set(new_list)
This method accepts a
clear
argument to control how to perform the operation. IfFalse
(the default), the elements missing from the new set are removed usingremove()
and only the new ones are added. Ifclear=True
, theclear()
method is called instead and the whole set is added at once.For
ForeignKey
objects, thebulk
argument is passed on toadd()
andremove()
.For many-to-many relationships, the
bulk
keyword argument doesn't exist.Note that since
set()
is a compound operation, it is subject to race conditions. For instance, new objects may be added to the database in between the call toclear()
and the call toadd()
.Similarly to
add()
,set()
also accepts the field the relation points to as an argument. The above example can be rewritten ase.related_set.set([obj1.pk, obj2.pk, obj3.pk])
.Use the
through_defaults
argument to specify values for the new intermediate model instance(s), if needed.Changed in Django 2.2:The
through_defaults
argument was added.
注釈
Note that
add()
,create()
,remove()
,clear()
, andset()
all apply database changes immediately for all types of related fields. In other words, there is no need to callsave()
on either end of the relationship.If you use
prefetch_related()
, theadd()
,remove()
,clear()
, andset()
methods clear the prefetched cache.