From 802baf5da5b8d8b44990a8214a43b951e7ab8b39 Mon Sep 17 00:00:00 2001 From: Colleen Dunlap Date: Thu, 15 May 2025 15:41:59 -0400 Subject: [PATCH] Fixed #36388 -- Made QuerySet.union() return self when called with no arguments. Regression in 9cb8baa0c4fa2c10789c5c8b65f4465932d4d172. Thank you to Antoine Humeau for the report and Simon Charette for the review. --- AUTHORS | 1 + django/db/models/query.py | 2 ++ docs/releases/5.2.2.txt | 3 +++ tests/queries/test_qs_combinators.py | 7 +++++++ 4 files changed, 13 insertions(+) diff --git a/AUTHORS b/AUTHORS index 89626872ab..a3adeceae1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -239,6 +239,7 @@ answer newbie questions, and generally made Django that much better: Claude Paroz Clifford Gama Clint Ecker + Colleen Dunlap colin@owlfish.com Colin Wood Collin Anderson diff --git a/django/db/models/query.py b/django/db/models/query.py index 663f8bade4..8e753e6455 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -1550,6 +1550,8 @@ class QuerySet(AltersData): if len(qs) == 1: return qs[0] return qs[0]._combinator_query("union", *qs[1:], all=all) + elif not other_qs: + return self return self._combinator_query("union", *other_qs, all=all) def intersection(self, *other_qs): diff --git a/docs/releases/5.2.2.txt b/docs/releases/5.2.2.txt index 22f3009c34..f6787bff08 100644 --- a/docs/releases/5.2.2.txt +++ b/docs/releases/5.2.2.txt @@ -15,3 +15,6 @@ Bugfixes * Fixed a bug in Django 5.2 where subqueries using ``"pk"`` to reference models with a ``CompositePrimaryKey`` failed to raise ``ValueError`` when too many or too few columns were selected (:ticket:`36392`). + +* Fixed a regression in Django 5.2 that caused a crash when no arguments were + passed into ``QuerySet.union()`` (:ticket:`36388`). diff --git a/tests/queries/test_qs_combinators.py b/tests/queries/test_qs_combinators.py index ba44b5ed87..e329d0c4f0 100644 --- a/tests/queries/test_qs_combinators.py +++ b/tests/queries/test_qs_combinators.py @@ -88,6 +88,13 @@ class QuerySetSetOperationTests(TestCase): qs3 = qs1.union(qs2) self.assertNumbersEqual(qs3[:1], [0]) + def test_union_empty_slice(self): + qs = Number.objects.union() + self.assertNumbersEqual(qs[:1], [0]) + qs = Number.objects.union(all=True) + self.assertNumbersEqual(qs[:1], [0]) + self.assertNumbersEqual(qs.order_by("num")[0:], list(range(0, 10))) + def test_union_all_none_slice(self): qs = Number.objects.filter(id__in=[]) with self.assertNumQueries(0):