From 1831f7733d3ef03d1ca7fac3e8d9f4c5e3e3375e Mon Sep 17 00:00:00 2001 From: SaJH Date: Tue, 15 Apr 2025 03:06:49 +0900 Subject: [PATCH] Fixed #36326 -- Added CompositePrimaryKey support in QuerySet.raw(). Signed-off-by: SaJH --- django/db/models/query.py | 4 +++- docs/releases/6.0.txt | 3 +++ tests/composite_pk/tests.py | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) 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,))