mirror of
https://github.com/django/django.git
synced 2025-06-05 03:29:12 +00:00
Fixed #22977 -- Added system check for clashing managers and reverse related fields.
With thanks to Konrad Świat, Loïc Bistuer, Russell Keith-Magee, and Mariusz Felisiak. Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
9d5d0e8135
commit
6888375c53
@ -580,6 +580,7 @@ class ForeignObject(RelatedField):
|
|||||||
*self._check_to_fields_exist(),
|
*self._check_to_fields_exist(),
|
||||||
*self._check_to_fields_composite_pk(),
|
*self._check_to_fields_composite_pk(),
|
||||||
*self._check_unique_target(),
|
*self._check_unique_target(),
|
||||||
|
*self._check_conflict_with_managers(),
|
||||||
]
|
]
|
||||||
|
|
||||||
def _check_to_fields_exist(self):
|
def _check_to_fields_exist(self):
|
||||||
@ -708,6 +709,27 @@ class ForeignObject(RelatedField):
|
|||||||
]
|
]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def _check_conflict_with_managers(self):
|
||||||
|
errors = []
|
||||||
|
manager_names = {manager.name for manager in self.opts.managers}
|
||||||
|
for rel_objs in self.model._meta.related_objects:
|
||||||
|
related_object_name = rel_objs.name
|
||||||
|
if related_object_name in manager_names:
|
||||||
|
field_name = f"{self.model._meta.object_name}.{self.name}"
|
||||||
|
errors.append(
|
||||||
|
checks.Error(
|
||||||
|
f"Related name '{related_object_name}' for '{field_name}' "
|
||||||
|
"clashes with the name of a model manager.",
|
||||||
|
hint=(
|
||||||
|
"Rename the model manager or change the related_name "
|
||||||
|
f"argument in the definition for field '{field_name}'."
|
||||||
|
),
|
||||||
|
obj=self,
|
||||||
|
id="fields.E348",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return errors
|
||||||
|
|
||||||
def deconstruct(self):
|
def deconstruct(self):
|
||||||
name, path, args, kwargs = super().deconstruct()
|
name, path, args, kwargs = super().deconstruct()
|
||||||
kwargs["on_delete"] = self.remote_field.on_delete
|
kwargs["on_delete"] = self.remote_field.on_delete
|
||||||
|
@ -340,6 +340,8 @@ Related fields
|
|||||||
* **fields.W346**: ``db_comment`` has no effect on ``ManyToManyField``.
|
* **fields.W346**: ``db_comment`` has no effect on ``ManyToManyField``.
|
||||||
* **fields.E347**: Field defines a relation to the ``CompositePrimaryKey`` of
|
* **fields.E347**: Field defines a relation to the ``CompositePrimaryKey`` of
|
||||||
model ``<model>`` which is not supported.
|
model ``<model>`` which is not supported.
|
||||||
|
* **fields.E348**: Related name ``<related_name>`` for ``<model>.<field name>``
|
||||||
|
clashes with the name of a model manager.
|
||||||
|
|
||||||
Models
|
Models
|
||||||
------
|
------
|
||||||
|
@ -1536,6 +1536,32 @@ class ExplicitRelatedQueryNameClashTests(SimpleTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@isolate_apps("invalid_models_tests")
|
||||||
|
class RelatedQueryNameClashWithManagerTests(SimpleTestCase):
|
||||||
|
def test_clash_between_related_query_name_and_manager(self):
|
||||||
|
class Author(models.Model):
|
||||||
|
authors = models.Manager()
|
||||||
|
mentor = models.ForeignKey(
|
||||||
|
"self", related_name="authors", on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
Author.check(),
|
||||||
|
[
|
||||||
|
Error(
|
||||||
|
"Related name 'authors' for 'Author.mentor' clashes with the name "
|
||||||
|
"of a model manager.",
|
||||||
|
hint=(
|
||||||
|
"Rename the model manager or change the related_name argument "
|
||||||
|
"in the definition for field 'Author.mentor'."
|
||||||
|
),
|
||||||
|
obj=Author._meta.get_field("mentor"),
|
||||||
|
id="fields.E348",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@isolate_apps("invalid_models_tests")
|
@isolate_apps("invalid_models_tests")
|
||||||
class SelfReferentialM2MClashTests(SimpleTestCase):
|
class SelfReferentialM2MClashTests(SimpleTestCase):
|
||||||
def test_clash_between_accessors(self):
|
def test_clash_between_accessors(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user