Skip to content

Commit

Permalink
Fixed #26352 -- Made system check allow ManyToManyField to target the…
Browse files Browse the repository at this point in the history
… same model if through_fields differs.
  • Loading branch information
Simon Willison authored and timgraham committed Aug 22, 2018
1 parent f2d5daf commit 586a9dc
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
7 changes: 4 additions & 3 deletions django/db/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1301,12 +1301,13 @@ def _check_m2m_through_same_relationship(cls):
fields = (f for f in fields if isinstance(f.remote_field.through, ModelBase))

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:
errors.append(
checks.Error(
"The model has two many-to-many relations through "
"the intermediate model '%s'." % f.remote_field.through._meta.label,
"The model has two identical many-to-many relations "
"through the intermediate model '%s'." %
f.remote_field.through._meta.label,
obj=cls,
id='models.E003',
)
Expand Down
4 changes: 2 additions & 2 deletions docs/ref/checks.txt
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ Models
* **models.E001**: ``<swappable>`` is not of the form ``app_label.app_name``.
* **models.E002**: ``<SETTING>`` references ``<model>``, which has not been
installed, or is abstract.
* **models.E003**: The model has two many-to-many relations through the
intermediate model ``<app_label>.<model>``.
* **models.E003**: The model has two identical many-to-many relations through
the intermediate model ``<app_label>.<model>``.
* **models.E004**: ``id`` can only be used as a field name if the field also
sets ``primary_key=True``.
* **models.E005**: The field ``<field name>`` from parent model ``<model>``
Expand Down
24 changes: 23 additions & 1 deletion tests/invalid_models_tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -771,13 +771,35 @@ class Membership(models.Model):

self.assertEqual(Group.check(), [
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'.",
obj=Group,
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):
msg = 'Add parent_link=True to invalid_models_tests.ParkingLot.parent.'
with self.assertRaisesMessage(ImproperlyConfigured, msg):
Expand Down

0 comments on commit 586a9dc

Please sign in to comment.