From 83b950e9ffd4904500bb9dcc9c7526f4d7899853 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Sat, 30 Jul 2016 20:50:09 -0400 Subject: [PATCH] [1.10.x] Refs #25550 -- Corrected deprecation message for assigning M2M relations. Backport of 5fa4370543658aedd79dc554d8c52684d6c7cbca from master --- django/db/models/fields/related_descriptors.py | 18 +++++++++++++++--- tests/many_to_many/tests.py | 13 +++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index ea80a1cdd7b..07c7efe48a6 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -475,6 +475,12 @@ class ReverseManyToOneDescriptor(object): return self.related_manager_cls(instance) + def _get_set_deprecation_msg_params(self): + return ( # RemovedInDjango20Warning + 'reverse side of a related set', + self.rel.get_accessor_name(), + ) + def __set__(self, instance, value): """ Set the related objects through the reverse relation. @@ -486,9 +492,9 @@ class ReverseManyToOneDescriptor(object): - ``value`` is the ``children`` sequence on the right of the equal sign """ warnings.warn( - 'Direct assignment to the reverse side of a related set is ' - 'deprecated due to the implicit save() that happens. Use %s.set() ' - 'instead.' % self.rel.get_accessor_name(), RemovedInDjango20Warning, stacklevel=2, + 'Direct assignment to the %s is deprecated due to the implicit ' + 'save() that happens. Use %s.set() instead.' % self._get_set_deprecation_msg_params(), + RemovedInDjango20Warning, stacklevel=2, ) manager = self.__get__(instance) manager.set(value) @@ -723,6 +729,12 @@ class ManyToManyDescriptor(ReverseManyToOneDescriptor): reverse=self.reverse, ) + def _get_set_deprecation_msg_params(self): + return ( # RemovedInDjango20Warning + '%s side of a many-to-many set' % ('reverse' if self.reverse else 'forward'), + self.rel.get_accessor_name() if self.reverse else self.field.name, + ) + def create_forward_many_to_many_manager(superclass, rel, reverse): """ diff --git a/tests/many_to_many/tests.py b/tests/many_to_many/tests.py index 67b3c9601eb..86ffe816eb2 100644 --- a/tests/many_to_many/tests.py +++ b/tests/many_to_many/tests.py @@ -400,15 +400,24 @@ class ManyToManyTests(TestCase): self.a4.publications.set([], clear=True) self.assertQuerysetEqual(self.a4.publications.all(), []) - def test_assign_deprecation(self): + def test_assign_forward_deprecation(self): msg = ( - "Direct assignment to the reverse side of a related set is " + "Direct assignment to the reverse side of a many-to-many set is " "deprecated due to the implicit save() that happens. Use " "article_set.set() instead." ) with self.assertRaisesMessage(RemovedInDjango20Warning, msg): self.p2.article_set = [self.a4, self.a3] + def test_assign_reverse_deprecation(self): + msg = ( + "Direct assignment to the forward side of a many-to-many " + "set is deprecated due to the implicit save() that happens. Use " + "publications.set() instead." + ) + with self.assertRaisesMessage(RemovedInDjango20Warning, msg): + self.a1.publications = [self.p1, self.p2] + @ignore_warnings(category=RemovedInDjango20Warning) def test_assign_deprecated(self): self.p2.article_set = [self.a4, self.a3]