Loading django/db/models/fields/related.py +1 −1 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ class RelatedField(Field): # Check clashes between accessor or reverse query name of `field` # and any other field name -- i. e. accessor for Model.foreign is # model_set and it clashes with Target.model_set. potential_clashes = rel_opts.fields + rel_opts.local_many_to_many potential_clashes = rel_opts.fields + rel_opts.many_to_many for clash_field in potential_clashes: clash_name = "%s.%s" % (rel_opts.object_name, clash_field.name) # i. e. "Target.model_set" Loading tests/invalid_models_tests/test_relative_fields.py +29 −0 Original line number Diff line number Diff line Loading @@ -583,6 +583,35 @@ class AccessorClashTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_m2m_to_m2m_with_inheritance(self): """ Ref #22047. """ class Target(models.Model): pass class Model(models.Model): children = models.ManyToManyField('Child', related_name="m2m_clash", related_query_name="no_clash") class Parent(models.Model): m2m_clash = models.ManyToManyField('Target') class Child(Parent): pass errors = Model.check() expected = [ Error( 'Accessor for field Model.children clashes with field Child.m2m_clash.', hint=('Rename field Child.m2m_clash or add/change ' 'a related_name argument to the definition ' 'for field Model.children.'), obj=Model._meta.get_field('children'), id='E014', ) ] self.assertEqual(errors, expected) class ReverseQueryNameClashTests(IsolatedModelsTestCase): Loading Loading
django/db/models/fields/related.py +1 −1 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ class RelatedField(Field): # Check clashes between accessor or reverse query name of `field` # and any other field name -- i. e. accessor for Model.foreign is # model_set and it clashes with Target.model_set. potential_clashes = rel_opts.fields + rel_opts.local_many_to_many potential_clashes = rel_opts.fields + rel_opts.many_to_many for clash_field in potential_clashes: clash_name = "%s.%s" % (rel_opts.object_name, clash_field.name) # i. e. "Target.model_set" Loading
tests/invalid_models_tests/test_relative_fields.py +29 −0 Original line number Diff line number Diff line Loading @@ -583,6 +583,35 @@ class AccessorClashTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_m2m_to_m2m_with_inheritance(self): """ Ref #22047. """ class Target(models.Model): pass class Model(models.Model): children = models.ManyToManyField('Child', related_name="m2m_clash", related_query_name="no_clash") class Parent(models.Model): m2m_clash = models.ManyToManyField('Target') class Child(Parent): pass errors = Model.check() expected = [ Error( 'Accessor for field Model.children clashes with field Child.m2m_clash.', hint=('Rename field Child.m2m_clash or add/change ' 'a related_name argument to the definition ' 'for field Model.children.'), obj=Model._meta.get_field('children'), id='E014', ) ] self.assertEqual(errors, expected) class ReverseQueryNameClashTests(IsolatedModelsTestCase): Loading