Fixed #26352 -- Made system check allow ManyToManyField to target the same model if through_fields differs.
This commit is contained in:
parent
f2d5dafec9
commit
586a9dc429
|
@ -1301,12 +1301,13 @@ class Model(metaclass=ModelBase):
|
||||||
fields = (f for f in fields if isinstance(f.remote_field.through, ModelBase))
|
fields = (f for f in fields if isinstance(f.remote_field.through, ModelBase))
|
||||||
|
|
||||||
for f in fields:
|
for f in fields:
|
||||||
signature = (f.remote_field.model, cls, f.remote_field.through)
|
signature = (f.remote_field.model, cls, f.remote_field.through, f.remote_field.through_fields)
|
||||||
if signature in seen_intermediary_signatures:
|
if signature in seen_intermediary_signatures:
|
||||||
errors.append(
|
errors.append(
|
||||||
checks.Error(
|
checks.Error(
|
||||||
"The model has two many-to-many relations through "
|
"The model has two identical many-to-many relations "
|
||||||
"the intermediate model '%s'." % f.remote_field.through._meta.label,
|
"through the intermediate model '%s'." %
|
||||||
|
f.remote_field.through._meta.label,
|
||||||
obj=cls,
|
obj=cls,
|
||||||
id='models.E003',
|
id='models.E003',
|
||||||
)
|
)
|
||||||
|
|
|
@ -252,8 +252,8 @@ Models
|
||||||
* **models.E001**: ``<swappable>`` is not of the form ``app_label.app_name``.
|
* **models.E001**: ``<swappable>`` is not of the form ``app_label.app_name``.
|
||||||
* **models.E002**: ``<SETTING>`` references ``<model>``, which has not been
|
* **models.E002**: ``<SETTING>`` references ``<model>``, which has not been
|
||||||
installed, or is abstract.
|
installed, or is abstract.
|
||||||
* **models.E003**: The model has two many-to-many relations through the
|
* **models.E003**: The model has two identical many-to-many relations through
|
||||||
intermediate model ``<app_label>.<model>``.
|
the intermediate model ``<app_label>.<model>``.
|
||||||
* **models.E004**: ``id`` can only be used as a field name if the field also
|
* **models.E004**: ``id`` can only be used as a field name if the field also
|
||||||
sets ``primary_key=True``.
|
sets ``primary_key=True``.
|
||||||
* **models.E005**: The field ``<field name>`` from parent model ``<model>``
|
* **models.E005**: The field ``<field name>`` from parent model ``<model>``
|
||||||
|
|
|
@ -771,13 +771,35 @@ class OtherModelTests(SimpleTestCase):
|
||||||
|
|
||||||
self.assertEqual(Group.check(), [
|
self.assertEqual(Group.check(), [
|
||||||
Error(
|
Error(
|
||||||
"The model has two many-to-many relations through "
|
"The model has two identical many-to-many relations through "
|
||||||
"the intermediate model 'invalid_models_tests.Membership'.",
|
"the intermediate model 'invalid_models_tests.Membership'.",
|
||||||
obj=Group,
|
obj=Group,
|
||||||
id='models.E003',
|
id='models.E003',
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_two_m2m_through_same_model_with_different_through_fields(self):
|
||||||
|
class Country(models.Model):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ShippingMethod(models.Model):
|
||||||
|
to_countries = models.ManyToManyField(
|
||||||
|
Country, through='ShippingMethodPrice',
|
||||||
|
through_fields=('method', 'to_country'),
|
||||||
|
)
|
||||||
|
from_countries = models.ManyToManyField(
|
||||||
|
Country, through='ShippingMethodPrice',
|
||||||
|
through_fields=('method', 'from_country'),
|
||||||
|
related_name='+',
|
||||||
|
)
|
||||||
|
|
||||||
|
class ShippingMethodPrice(models.Model):
|
||||||
|
method = models.ForeignKey(ShippingMethod, models.CASCADE)
|
||||||
|
to_country = models.ForeignKey(Country, models.CASCADE)
|
||||||
|
from_country = models.ForeignKey(Country, models.CASCADE)
|
||||||
|
|
||||||
|
self.assertEqual(ShippingMethod.check(), [])
|
||||||
|
|
||||||
def test_missing_parent_link(self):
|
def test_missing_parent_link(self):
|
||||||
msg = 'Add parent_link=True to invalid_models_tests.ParkingLot.parent.'
|
msg = 'Add parent_link=True to invalid_models_tests.ParkingLot.parent.'
|
||||||
with self.assertRaisesMessage(ImproperlyConfigured, msg):
|
with self.assertRaisesMessage(ImproperlyConfigured, msg):
|
||||||
|
|
Loading…
Reference in New Issue