mirror of
https://github.com/django/django.git
synced 2025-08-09 13:28:18 +00:00
Fixed #36530 -- Extended fields.E347 to check for ManyToManyField involving CompositePrimaryKey on either side.
Thanks to Jacob Walls for the report.
This commit is contained in:
parent
e664c5afa9
commit
2013092b69
4 changed files with 68 additions and 53 deletions
|
@ -626,9 +626,10 @@ class ForeignObject(RelatedField):
|
||||||
if isinstance(field, CompositePrimaryKey):
|
if isinstance(field, CompositePrimaryKey):
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
"Field defines a relation to the CompositePrimaryKey of "
|
"Field defines a relation involving model "
|
||||||
f"model {self.remote_field.model._meta.object_name!r} "
|
f"{self.remote_field.model._meta.object_name!r} which has "
|
||||||
"which is not supported.",
|
"a CompositePrimaryKey and such relations are not "
|
||||||
|
"supported.",
|
||||||
obj=self,
|
obj=self,
|
||||||
id="fields.E347",
|
id="fields.E347",
|
||||||
)
|
)
|
||||||
|
@ -1538,16 +1539,20 @@ class ManyToManyField(RelatedField):
|
||||||
to_model_name = to_model
|
to_model_name = to_model
|
||||||
else:
|
else:
|
||||||
to_model_name = to_model._meta.object_name
|
to_model_name = to_model._meta.object_name
|
||||||
if (
|
if self.remote_field.through_fields is None and not isinstance(
|
||||||
self.remote_field.through_fields is None
|
to_model, str
|
||||||
and not isinstance(to_model, str)
|
|
||||||
and isinstance(to_model._meta.pk, CompositePrimaryKey)
|
|
||||||
):
|
):
|
||||||
|
model_name = None
|
||||||
|
if isinstance(to_model._meta.pk, CompositePrimaryKey):
|
||||||
|
model_name = self.remote_field.model._meta.object_name
|
||||||
|
elif isinstance(from_model._meta.pk, CompositePrimaryKey):
|
||||||
|
model_name = from_model_name
|
||||||
|
if model_name:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
"Field defines a relation to the CompositePrimaryKey of model "
|
f"Field defines a relation involving model {model_name!r} "
|
||||||
f"{self.remote_field.model._meta.object_name!r} which is not "
|
"which has a CompositePrimaryKey and such relations are "
|
||||||
"supported.",
|
"not supported.",
|
||||||
obj=self,
|
obj=self,
|
||||||
id="fields.E347",
|
id="fields.E347",
|
||||||
)
|
)
|
||||||
|
|
|
@ -338,8 +338,8 @@ Related fields
|
||||||
* **fields.W345**: ``related_name`` has no effect on ``ManyToManyField`` with a
|
* **fields.W345**: ``related_name`` has no effect on ``ManyToManyField`` with a
|
||||||
symmetrical relationship, e.g. to "self".
|
symmetrical relationship, e.g. to "self".
|
||||||
* **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 involving model ``<model>`` which
|
||||||
model ``<model>`` which is not supported.
|
has a ``CompositePrimaryKey`` and such relations are not supported.
|
||||||
* **fields.E348**: Related name ``<related_name>`` for ``<model>.<field name>``
|
* **fields.E348**: Related name ``<related_name>`` for ``<model>.<field name>``
|
||||||
clashes with the name of a model manager.
|
clashes with the name of a model manager.
|
||||||
|
|
||||||
|
|
|
@ -21,3 +21,7 @@ Bugfixes
|
||||||
(:ticket:`36518`).
|
(:ticket:`36518`).
|
||||||
|
|
||||||
* Added compatibility for ``docutils`` 0.22 (:ticket:`36535`).
|
* Added compatibility for ``docutils`` 0.22 (:ticket:`36535`).
|
||||||
|
|
||||||
|
* Fixed a crash in Django 5.2 when using a ``ManyToManyField`` on a model with
|
||||||
|
a composite primary key, by extending the ``fields.E347`` system check
|
||||||
|
(:ticket:`36530`).
|
||||||
|
|
|
@ -454,29 +454,19 @@ class RelativeFieldTests(SimpleTestCase):
|
||||||
"Parent", on_delete=models.CASCADE, related_name="child_string_set"
|
"Parent", on_delete=models.CASCADE, related_name="child_string_set"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
error = (
|
||||||
|
"Field defines a relation involving model 'Parent' which has a "
|
||||||
|
"CompositePrimaryKey and such relations are not supported."
|
||||||
|
)
|
||||||
field = Child._meta.get_field("rel_string_parent")
|
field = Child._meta.get_field("rel_string_parent")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
field.check(),
|
field.check(),
|
||||||
[
|
[Error(error, obj=field, id="fields.E347")],
|
||||||
Error(
|
|
||||||
"Field defines a relation to the CompositePrimaryKey of model "
|
|
||||||
"'Parent' which is not supported.",
|
|
||||||
obj=field,
|
|
||||||
id="fields.E347",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
field = Child._meta.get_field("rel_class_parent")
|
field = Child._meta.get_field("rel_class_parent")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
field.check(),
|
field.check(),
|
||||||
[
|
[Error(error, obj=field, id="fields.E347")],
|
||||||
Error(
|
|
||||||
"Field defines a relation to the CompositePrimaryKey of model "
|
|
||||||
"'Parent' which is not supported.",
|
|
||||||
obj=field,
|
|
||||||
id="fields.E347",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_many_to_many_to_model_with_composite_primary_key(self):
|
def test_many_to_many_to_model_with_composite_primary_key(self):
|
||||||
|
@ -493,29 +483,45 @@ class RelativeFieldTests(SimpleTestCase):
|
||||||
"Parent", related_name="child_string_set"
|
"Parent", related_name="child_string_set"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
error = (
|
||||||
|
"Field defines a relation involving model 'Parent' which has a "
|
||||||
|
"CompositePrimaryKey and such relations are not supported."
|
||||||
|
)
|
||||||
field = Child._meta.get_field("rel_string_parent")
|
field = Child._meta.get_field("rel_string_parent")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
field.check(from_model=Child),
|
field.check(from_model=Child),
|
||||||
[
|
[Error(error, obj=field, id="fields.E347")],
|
||||||
Error(
|
|
||||||
"Field defines a relation to the CompositePrimaryKey of model "
|
|
||||||
"'Parent' which is not supported.",
|
|
||||||
obj=field,
|
|
||||||
id="fields.E347",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
field = Child._meta.get_field("rel_class_parent")
|
field = Child._meta.get_field("rel_class_parent")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
field.check(from_model=Child),
|
field.check(from_model=Child),
|
||||||
[
|
[Error(error, obj=field, id="fields.E347")],
|
||||||
Error(
|
)
|
||||||
"Field defines a relation to the CompositePrimaryKey of model "
|
|
||||||
"'Parent' which is not supported.",
|
def test_many_to_many_from_model_with_composite_primary_key(self):
|
||||||
obj=field,
|
class Parent(models.Model):
|
||||||
id="fields.E347",
|
name = models.CharField(max_length=20)
|
||||||
),
|
|
||||||
],
|
class Meta:
|
||||||
|
app_label = "invalid_models_tests"
|
||||||
|
|
||||||
|
class Child(models.Model):
|
||||||
|
pk = models.CompositePrimaryKey("version", "name")
|
||||||
|
version = models.IntegerField()
|
||||||
|
name = models.CharField(max_length=20)
|
||||||
|
parents = models.ManyToManyField(Parent)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = "invalid_models_tests"
|
||||||
|
|
||||||
|
error = (
|
||||||
|
"Field defines a relation involving model 'Child' which has a "
|
||||||
|
"CompositePrimaryKey and such relations are not supported."
|
||||||
|
)
|
||||||
|
field = Child._meta.get_field("parents")
|
||||||
|
self.assertEqual(
|
||||||
|
field.check(from_model=Child),
|
||||||
|
[Error(error, obj=field, id="fields.E347")],
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_foreign_key_to_non_unique_field(self):
|
def test_foreign_key_to_non_unique_field(self):
|
||||||
|
@ -1038,8 +1044,8 @@ class RelativeFieldTests(SimpleTestCase):
|
||||||
field.check(),
|
field.check(),
|
||||||
[
|
[
|
||||||
Error(
|
Error(
|
||||||
"Field defines a relation to the CompositePrimaryKey of model "
|
"Field defines a relation involving model 'Parent' which has a "
|
||||||
"'Parent' which is not supported.",
|
"CompositePrimaryKey and such relations are not supported.",
|
||||||
obj=field,
|
obj=field,
|
||||||
id="fields.E347",
|
id="fields.E347",
|
||||||
),
|
),
|
||||||
|
@ -1060,8 +1066,8 @@ class RelativeFieldTests(SimpleTestCase):
|
||||||
field.check(),
|
field.check(),
|
||||||
[
|
[
|
||||||
Error(
|
Error(
|
||||||
"Field defines a relation to the CompositePrimaryKey of model "
|
"Field defines a relation involving model 'Parent' which has a "
|
||||||
"'Parent' which is not supported.",
|
"CompositePrimaryKey and such relations are not supported.",
|
||||||
obj=field,
|
obj=field,
|
||||||
id="fields.E347",
|
id="fields.E347",
|
||||||
),
|
),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue