From 787f3130f751283140fe2be8188eb5299552232d Mon Sep 17 00:00:00 2001 From: Colleen Dunlap Date: Thu, 15 May 2025 15:41:59 -0400 Subject: [PATCH] [5.2.x] 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. Backport of 802baf5da5b8d8b44990a8214a43b951e7ab8b39 from main. --- 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 6fd36510c7..b300a6791d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -237,6 +237,7 @@ answer newbie questions, and generally made Django that much better: Ciaran McCormick Claude Paroz 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 b7d6aa28de..bb5462037c 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -1554,6 +1554,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):