diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index a9445d5d10..451d0b4e1f 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -999,7 +999,8 @@ def create_forward_many_to_many_manager(superclass, rel, reverse): for obj in objs: fk_val = ( self.target_field.get_foreign_related_value(obj)[0] - if isinstance(obj, self.model) else obj + if isinstance(obj, self.model) + else self.target_field.get_prep_value(obj) ) if fk_val in old_ids: old_ids.remove(fk_val) diff --git a/tests/many_to_many/tests.py b/tests/many_to_many/tests.py index 79d0fa420c..b4314580ec 100644 --- a/tests/many_to_many/tests.py +++ b/tests/many_to_many/tests.py @@ -469,6 +469,19 @@ class ManyToManyTests(TestCase): self.a4.publications.set([], clear=True) self.assertQuerysetEqual(self.a4.publications.all(), []) + def test_set_existing_different_type(self): + # Existing many-to-many relations remain the same for values provided + # with a different type. + ids = set(Publication.article_set.through.objects.filter( + article__in=[self.a4, self.a3], + publication=self.p2, + ).values_list('id', flat=True)) + self.p2.article_set.set([str(self.a4.pk), str(self.a3.pk)]) + new_ids = set(Publication.article_set.through.objects.filter( + publication=self.p2, + ).values_list('id', flat=True)) + self.assertEqual(ids, new_ids) + def test_assign_forward(self): msg = ( "Direct assignment to the reverse side of a many-to-many set is "