summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Foster <david@dafoster.net>2019-10-20 11:47:38 -0700
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-11-12 13:13:49 +0100
commitafde973061a3e6477f3c454f4471842d37e73494 (patch)
tree929e391791d8183a69a2bc3cd9235c8b67378520
parent612c2d166c9048c59ee241ce4ba89858aa65665d (diff)
[2.2.x] Fixed #30828 -- Added how to remove/insert many-to-many relations in bulk to the database optimization docs.
Backport of 6a04e69e686cf417b469d7676f93c2e3a9c8d6a3 from master
-rw-r--r--AUTHORS1
-rw-r--r--docs/topics/db/optimization.txt62
2 files changed, 63 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
index 7eb38f72f7..9b889cbd10 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -225,6 +225,7 @@ answer newbie questions, and generally made Django that much better:
David Cramer <dcramer@gmail.com>
David Danier <david.danier@team23.de>
David Eklund
+ David Foster <david@dafoster.net>
David Gouldin <dgouldin@gmail.com>
david@kazserve.org
David Krauth
diff --git a/docs/topics/db/optimization.txt b/docs/topics/db/optimization.txt
index 6e5ccd0290..ca2ab35a3e 100644
--- a/docs/topics/db/optimization.txt
+++ b/docs/topics/db/optimization.txt
@@ -412,3 +412,65 @@ objects to reduce the number of SQL queries. For example::
my_band.members.add(my_friend)
...where ``Bands`` and ``Artists`` have a many-to-many relationship.
+
+When inserting different pairs of objects into
+:class:`~django.db.models.ManyToManyField` or when the custom
+:attr:`~django.db.models.ManyToManyField.through` table is defined, use
+:meth:`~django.db.models.query.QuerySet.bulk_create()` method to reduce the
+number of SQL queries. For example::
+
+ PizzaToppingRelationship = Pizza.toppings.through
+ PizzaToppingRelationship.objects.bulk_create([
+ PizzaToppingRelationship(pizza=my_pizza, topping=pepperoni),
+ PizzaToppingRelationship(pizza=your_pizza, topping=pepperoni),
+ PizzaToppingRelationship(pizza=your_pizza, topping=mushroom),
+ ], ignore_conflicts=True)
+
+...is preferable to::
+
+ my_pizza.toppings.add(pepperoni)
+ your_pizza.toppings.add(pepperoni, mushroom)
+
+...where ``Pizza`` and ``Topping`` have a many-to-many relationship. Note that
+there are a number of :meth:`caveats to this method
+<django.db.models.query.QuerySet.bulk_create>`, so make sure it's appropriate
+for your use case.
+
+Remove in bulk
+--------------
+
+When removing objects from :class:`ManyToManyFields
+<django.db.models.ManyToManyField>`, use
+:meth:`~django.db.models.fields.related.RelatedManager.remove` with multiple
+objects to reduce the number of SQL queries. For example::
+
+ my_band.members.remove(me, my_friend)
+
+...is preferable to::
+
+ my_band.members.remove(me)
+ my_band.members.remove(my_friend)
+
+...where ``Bands`` and ``Artists`` have a many-to-many relationship.
+
+When removing different pairs of objects from :class:`ManyToManyFields
+<django.db.models.ManyToManyField>`, use
+:meth:`~django.db.models.query.QuerySet.delete` on a
+:class:`~django.db.models.Q` expression with multiple
+:attr:`~django.db.models.ManyToManyField.through` model instances to reduce
+the number of SQL queries. For example::
+
+ from django.db.models import Q
+ PizzaToppingRelationship = Pizza.toppings.through
+ PizzaToppingRelationship.objects.filter(
+ Q(pizza=my_pizza, topping=pepperoni) |
+ Q(pizza=your_pizza, topping=pepperoni) |
+ Q(pizza=your_pizza, topping=mushroom)
+ ).delete()
+
+...is preferable to::
+
+ my_pizza.toppings.remove(pepperoni)
+ your_pizza.toppings.remove(pepperoni, mushroom)
+
+...where ``Pizza`` and ``Topping`` have a many-to-many relationship.