diff --git a/django/db/models/query.py b/django/db/models/query.py index bb5462037c..1270141619 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -1149,7 +1149,9 @@ class QuerySet(AltersData): if not id_list: return {} filter_key = "{}__in".format(field_name) - batch_size = connections[self.db].features.max_query_params + max_params = connections[self.db].features.max_query_params or 0 + num_fields = len(opts.pk_fields) if field_name == "pk" else 1 + batch_size = max_params // num_fields id_list = tuple(id_list) # If the database has a limit on the number of query parameters # (e.g. SQLite), retrieve objects in batches if necessary. diff --git a/docs/releases/5.2.2.txt b/docs/releases/5.2.2.txt index 5647c0cc07..3870a3efa4 100644 --- a/docs/releases/5.2.2.txt +++ b/docs/releases/5.2.2.txt @@ -34,3 +34,7 @@ Bugfixes * Fixed a regression in Django 5.2 where admin's ``filter_horizontal`` buttons lacked ``type="button"``, causing them to intercept form submission when pressing the Enter key (:ticket:`36423`). + +* Fixed a bug in Django 5.2 where calling ``QuerySet.in_bulk()`` with an + ``id_list`` argument on models with a ``CompositePrimaryKey`` failed to + observe database parameter limits (:ticket:`36416`). diff --git a/tests/composite_pk/tests.py b/tests/composite_pk/tests.py index 1a28a585fa..2245a472e4 100644 --- a/tests/composite_pk/tests.py +++ b/tests/composite_pk/tests.py @@ -147,6 +147,22 @@ class CompositePKTests(TestCase): result = Comment.objects.in_bulk([self.comment.pk]) self.assertEqual(result, {self.comment.pk: self.comment}) + @unittest.mock.patch.object( + type(connection.features), "max_query_params", new_callable=lambda: 10 + ) + def test_in_bulk_batching(self, mocked_max_query_params): + Comment.objects.all().delete() + num_requiring_batching = (connection.features.max_query_params // 2) + 1 + comments = [ + Comment(id=i, tenant=self.tenant, user=self.user) + for i in range(1, num_requiring_batching + 1) + ] + Comment.objects.bulk_create(comments) + id_list = list(Comment.objects.values_list("pk", flat=True)) + with self.assertNumQueries(2): + comment_dict = Comment.objects.in_bulk(id_list=id_list) + self.assertQuerySetEqual(comment_dict, id_list) + def test_iterator(self): """ Test the .iterator() method of composite_pk models.