diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index 451d0b4e1f..20f247c603 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -697,6 +697,10 @@ def create_reverse_many_to_one_manager(superclass, rel): val = self.field.get_foreign_related_value(self.instance) old_ids = set() for obj in objs: + if not isinstance(obj, self.model): + raise TypeError("'%s' instance expected, got %r" % ( + self.model._meta.object_name, obj, + )) # Is obj actually part of this descriptor set? if self.field.get_local_related_value(obj) == val: old_ids.add(obj.pk) diff --git a/tests/many_to_one/tests.py b/tests/many_to_one/tests.py index d769b206b9..76ef4921dd 100644 --- a/tests/many_to_one/tests.py +++ b/tests/many_to_one/tests.py @@ -733,3 +733,14 @@ class ManyToOneTests(TestCase): child = parent.to_field_children.get() with self.assertNumQueries(0): self.assertIs(child.parent, parent) + + def test_add_remove_set_by_pk_raises(self): + usa = Country.objects.create(name='United States') + chicago = City.objects.create(name='Chicago') + msg = "'City' instance expected, got %s" % chicago.pk + with self.assertRaisesMessage(TypeError, msg): + usa.cities.add(chicago.pk) + with self.assertRaisesMessage(TypeError, msg): + usa.cities.remove(chicago.pk) + with self.assertRaisesMessage(TypeError, msg): + usa.cities.set([chicago.pk])