Code

Ticket #18556: t18556-remove-efficiency.diff

File t18556-remove-efficiency.diff, 2.5 KB (added by Alex, 2 years ago)
Line 
1diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
2index 96d1438..9ddba43 100644
3--- a/django/db/models/fields/related.py
4+++ b/django/db/models/fields/related.py
5@@ -523,13 +523,14 @@ class ForeignRelatedObjectsDescriptor(object):
6             if rel_field.null:
7                 def remove(self, *objs):
8                     val = getattr(self.instance, attname)
9+                    ids = []
10                     for obj in objs:
11                         # Is obj actually part of this descriptor set?
12                         if getattr(obj, rel_field.attname) == val:
13-                            setattr(obj, rel_field.name, None)
14-                            obj.save()
15+                            ids.append(obj.pk)
16                         else:
17                             raise rel_field.rel.to.DoesNotExist("%r is not related to %r." % (obj, self.instance))
18+                    self.filter(pk__in=ids).update(**{rel_field.name: None})
19                 remove.alters_data = True
20 
21                 def clear(self):
22diff --git a/django/db/models/related.py b/django/db/models/related.py
23index 90995d7..08b825b 100644
24--- a/django/db/models/related.py
25+++ b/django/db/models/related.py
26@@ -36,7 +36,7 @@ class RelatedObject(object):
27                 {'%s__isnull' % self.parent_model._meta.module_name: False})
28         lst = [(x._get_pk_val(), smart_unicode(x)) for x in queryset]
29         return first_choice + lst
30-       
31+
32     def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
33         # Defer to the actual field definition for db prep
34         return self.field.get_db_prep_lookup(lookup_type, value,
35diff --git a/tests/modeltests/many_to_one_null/tests.py b/tests/modeltests/many_to_one_null/tests.py
36index 1a404bd..f367ea1 100644
37--- a/tests/modeltests/many_to_one_null/tests.py
38+++ b/tests/modeltests/many_to_one_null/tests.py
39@@ -92,4 +92,13 @@ class ManyToOneNullTests(TestCase):
40             r.article_set.create()
41         with self.assertNumQueries(1):
42             r.article_set.clear()
43-        self.assertEqual(r.article_set.count(), 0)
44\ No newline at end of file
45+        self.assertEqual(r.article_set.count(), 0)
46+
47+    def test_remove_efficiency(self):
48+        r = Reporter.objects.create()
49+        articles = []
50+        for _ in xrange(3):
51+            articles.append(r.article_set.create())
52+        with self.assertNumQueries(1):
53+            r.article_set.remove(*articles)
54+        self.assertEqual(r.article_set.count(), 0)