diff --git a/django/db/models/query.py b/django/db/models/query.py index e019dd6db9..915acb629a 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -165,7 +165,9 @@ class RawModelIterable(BaseIterable): annotation_fields, ) = self.queryset.resolve_model_init_order() model_cls = self.queryset.model - if model_cls._meta.pk.attname not in model_init_names: + if any( + f.attname not in model_init_names for f in model_cls._meta.pk_fields + ): raise exceptions.FieldDoesNotExist( "Raw query must include the primary key" ) diff --git a/docs/releases/6.0.txt b/docs/releases/6.0.txt index 538d242b98..4b9ad92e92 100644 --- a/docs/releases/6.0.txt +++ b/docs/releases/6.0.txt @@ -201,6 +201,9 @@ Models :ref:`a forced update ` results in no affected rows, instead of a generic :exc:`django.db.DatabaseError`. +* :meth:`.QuerySet.raw` now supports models with a + :class:`~django.db.models.CompositePrimaryKey`. + Pagination ~~~~~~~~~~ diff --git a/tests/composite_pk/tests.py b/tests/composite_pk/tests.py index 18fa53d9c0..5dea23c9f2 100644 --- a/tests/composite_pk/tests.py +++ b/tests/composite_pk/tests.py @@ -11,7 +11,7 @@ except ImportError: from django import forms from django.core import serializers -from django.core.exceptions import FieldError +from django.core.exceptions import FieldDoesNotExist, FieldError from django.db import IntegrityError, connection from django.db.models import CompositePrimaryKey from django.forms import modelform_factory @@ -158,6 +158,20 @@ class CompositePKTests(TestCase): users = User.objects.values_list("pk").order_by("pk") self.assertNotIn('AS "pk"', str(users.query)) + def test_raw(self): + users = User.objects.raw("SELECT * FROM composite_pk_user") + self.assertEqual(len(users), 1) + user = users[0] + self.assertEqual(user.tenant_id, self.user.tenant_id) + self.assertEqual(user.id, self.user.id) + self.assertEqual(user.email, self.user.email) + + def test_raw_missing_PK_fields(self): + query = "SELECT tenant_id, email FROM composite_pk_user" + msg = "Raw query must include the primary key" + with self.assertRaisesMessage(FieldDoesNotExist, msg): + list(User.objects.raw(query)) + def test_only(self): users = User.objects.only("pk") self.assertSequenceEqual(users, (self.user,))