﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36530	System check for ManyToManyField & Composite Primary Key checks only one direction	Jacob Walls	Jason Hall	"#36034 added the system check E347 for `ManyToManyField` when the ""to_model"" has a composite pk, but the situation is just as unsupported when the composite primary key model is the ""from_model"", i.e. the one with *both* the `ManyToManyField` and the `CompositePrimaryKey`.

We should be able to just adjust [https://github.com/django/django/blob/45ba7683a6e399815731a13cceb3acb518a2f1f2/django/db/models/fields/related.py#L1544 this system check condition] to check the ""from"" table also.
----
e.g. this (purely for demo, not suggesting we edit this test model):
{{{#!diff
diff --git a/tests/composite_pk/models/tenant.py b/tests/composite_pk/models/tenant.py
index 65eb0feae8..ef777edff9 100644
--- a/tests/composite_pk/models/tenant.py
+++ b/tests/composite_pk/models/tenant.py
@@ -60,3 +60,4 @@ class TimeStamped(models.Model):
     id = models.SmallIntegerField(unique=True)
     created = models.DateTimeField(auto_now_add=True)
     text = models.TextField(default="""", blank=True)
+    tenants = models.ManyToManyField(Tenant)
}}}

gives:
{{{#!py
ERROR: test_serialize_datetime (composite_pk.tests.CompositePKFixturesTests.test_serialize_datetime)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ""/Users/jwalls/django/tests/composite_pk/tests.py"", line 368, in test_serialize_datetime
    result = serializers.serialize(""json"", TimeStamped.objects.all())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/core/serializers/__init__.py"", line 134, in serialize
    s.serialize(queryset, **options)
  File ""/Users/jwalls/django/django/core/serializers/base.py"", line 144, in serialize
    self.handle_m2m_field(obj, field)
  File ""/Users/jwalls/django/django/core/serializers/python.py"", line 95, in handle_m2m_field
    queryset_iterator(obj, field),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/core/serializers/python.py"", line 89, in queryset_iterator
    query_set = getattr(obj, field.name).select_related(None).only(""pk"")
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/manager.py"", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/query.py"", line 1632, in select_related
    self._not_support_combined_queries(""select_related"")
  File ""/Users/jwalls/django/django/db/models/query.py"", line 2052, in _not_support_combined_queries
    if self.query.combinator:
       ^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/query.py"", line 302, in query
    self._filter_or_exclude_inplace(negate, args, kwargs)
  File ""/Users/jwalls/django/django/db/models/query.py"", line 1549, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File ""/Users/jwalls/django/django/db/models/sql/query.py"", line 1667, in add_q
    clause, _ = self._add_q(q_object, can_reuse)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/sql/query.py"", line 1699, in _add_q
    child_clause, needed_inner = self.build_filter(
                                 ^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/sql/query.py"", line 1609, in build_filter
    condition = self.build_lookup(lookups, col, value)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/sql/query.py"", line 1436, in build_lookup
    lookup = lookup_class(lhs, rhs)
             ^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/lookups.py"", line 35, in __init__
    self.rhs = self.get_prep_lookup()
               ^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jwalls/django/django/db/models/fields/tuple_lookups.py"", line 55, in get_prep_lookup
    self.check_rhs_length_equals_lhs_length()
  File ""/Users/jwalls/django/django/db/models/fields/tuple_lookups.py"", line 69, in check_rhs_length_equals_lhs_length
    len_lhs = len(self.lhs)
              ^^^^^^^^^^^^^
TypeError: object of type 'Col' has no len()

----------------------------------------------------------------------
Ran 170 tests in 0.183s

FAILED (errors=1)
}}}"	Bug	closed	Database layer (models, ORM)	5.2	Release blocker	fixed	compositeprimarykey	Simon Charette	Ready for checkin	1	0	0	0	0	0
