From e3e80da7a59f6fcef814b951f5a77a33584e3b62 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Wed, 28 Dec 2016 11:44:26 -0500 Subject: [PATCH] Fixed #27651 -- Allowed M2M to concrete and proxy through model. --- django/db/models/fields/related.py | 6 ++++-- tests/invalid_models_tests/test_models.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 3ba957f2d4..10ba7696ca 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -1447,8 +1447,10 @@ class ManyToManyField(RelatedField): if model != self.remote_field.through and model._meta.managed } m2m_db_table = self.m2m_db_table() - if m2m_db_table in registered_tables: - model = registered_tables[m2m_db_table] + model = registered_tables.get(m2m_db_table) + # The second condition allows multiple m2m relations on a model if + # some point to a through model that proxies another through model. + if model and model._meta.concrete_model != self.remote_field.through._meta.concrete_model: if model._meta.auto_created: def _get_field_name(model): for field in model._meta.auto_created._meta.many_to_many: diff --git a/tests/invalid_models_tests/test_models.py b/tests/invalid_models_tests/test_models.py index b50b265bd4..78f2164ed5 100644 --- a/tests/invalid_models_tests/test_models.py +++ b/tests/invalid_models_tests/test_models.py @@ -899,6 +899,24 @@ class OtherModelTests(SimpleTestCase): self.assertEqual(C1.check(), []) self.assertEqual(C2.check(), []) + def test_m2m_to_concrete_and_proxy_allowed(self): + class A(models.Model): + pass + + class Through(models.Model): + a = models.ForeignKey('A', models.CASCADE) + c = models.ForeignKey('C', models.CASCADE) + + class ThroughProxy(Through): + class Meta: + proxy = True + + class C(models.Model): + mm_a = models.ManyToManyField(A, through=Through) + mm_aproxy = models.ManyToManyField(A, through=ThroughProxy, related_name='proxied_m2m') + + self.assertEqual(C.check(), []) + @isolate_apps('django.contrib.auth', kwarg_name='apps') def test_lazy_reference_checks(self, apps): class DummyModel(models.Model):