Related objects reference
- class
RelatedManager
A “related manager” is a manager used in a one-to-many or many-to-manyrelated context. This happens in two cases:
- The “other side” of a
ForeignKey
relation.That is:
- The “other side” of a
- 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 onthe 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 ontopping.pizza_set
and on pizza.toppings
.
add
(*objs, bulk=True, through_defaults=None)- Adds the specified model objects to the related object set.
Example:
- >>> 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 aForeignKey
relationship,QuerySet.update()
is used to perform the update. This requires the objects to already besaved.
You can use the bulk=False
argument to instead have the relatedmanager perform the update by calling e.save()
.
Using add()
with a many-to-many relationship, however, will notcall any save()
methods (the bulk
argument doesn’t exist), butrather create the relationships using QuerySet.bulk_create()
. If you need to executesome custom logic when a relationship is created, listen to them2m_changed
signal, which willtrigger pre_add
and post_add
actions.
Using add()
on a relation that already exists won’t duplicate therelation, but it will still trigger signals.
add()
also accepts the field the relation points to as an argument.The above example can be rewritten as b.entry_set.add(234)
.
Use the through_defaults
argument to specify values for the newintermediate model instance(s), ifneeded.
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 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 modelthat defines the relationship. In the above example, we don’t pass theparameter blog
to create()
. Django figures out that the newEntry
object’s blog
field should be set to b
.
Use the through_defaults
argument to specify values for the newintermediate model instance, ifneeded.
Changed in Django 2.2:The through_defaults
argument was added.
- >>> 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 aboveto perform the update. Using remove()
with a many-to-manyrelationship, however, will delete the relationships usingQuerySet.delete()
whichmeans no model save()
methods are called; listen to them2m_changed
signal if you wish toexecute custom code when a relationship is deleted.
Similarly to add()
, remove()
also accepts the field therelation points to as an argument. The above example can be rewrittenas b.entry_set.remove(234)
.
For ForeignKey
objects, this method onlyexists if null=True
. If the related field can’t be set to None
(NULL
), then an object can’t be removed from a relation withoutbeing added to another. In the above example, removing e
fromb.entry_set()
is equivalent to doing e.blog = None
, and becausethe blog
ForeignKey
doesn’t havenull=True
, this is invalid.
For ForeignKey
objects, this method acceptsa bulk
argument to control how to perform the operation.If True
(the default), QuerySet.update()
is used.If bulk=False
, the save()
method of each individual modelinstance is called instead. This triggers thepre_save
andpost_save
signals and comes at theexpense of performance.
For many-to-many relationships, the bulk
keyword argument doesn’texist.
- >>> b = Blog.objects.get(id=1)
- >>> b.entry_set.clear()
Note this doesn’t delete the related objects – it just disassociatesthem.
Just like remove()
, clear()
is only available onForeignKey
s where null=True
and it alsoaccepts the bulk
keyword argument.
For many-to-many relationships, the bulk
keyword argument doesn’texist.
- >>> new_list = [obj1, obj2, obj3]
- >>> e.related_set.set(new_list)
This method accepts a clear
argument to control how to perform theoperation. If False
(the default), the elements missing from thenew set are removed using remove()
and only the new ones are added.If clear=True
, the clear()
method is called instead and thewhole set is added at once.
For ForeignKey
objects, the bulk
argument is passed on to add()
and remove()
.
For many-to-many relationships, the bulk
keyword argument doesn’texist.
Note that since set()
is a compound operation, it is subject torace conditions. For instance, new objects may be added to the databasein between the call to clear()
and the call to add()
.
Similarly to add()
, set()
also accepts the field therelation points to as an argument. The above example can be rewrittenas e.related_set.set([obj1.pk, obj2.pk, obj3.pk])
.
Use the through_defaults
argument to specify values for the newintermediate model instance(s), ifneeded.
Changed in Django 2.2:The through_defaults
argument was added.
Note
Note that add()
, create()
, remove()
, clear()
, andset()
all apply database changes immediately for all types ofrelated fields. In other words, there is no need to call save()
on either end of the relationship.
If you use prefetch_related()
,the add()
, remove()
, clear()
, and set()
methods clearthe prefetched cache.