1
0
mirror of https://github.com/django/django.git synced 2025-07-22 18:49:25 +00:00

[2.0.x] Fixed #29195 -- Fixed Exists.output_field resolution on single-valued queries.

The Subquery class which Exists inherits from defaulted to using single-valued
querie's field if no output_field was explicitly specified on initialization
which was bypassing the Exists.output_field defined at the class level.

Moving Subquery's dynamic output_field resolution to _resolve_output_field
should make sure the fallback logic is only performed if required.

Regression in 08654a99bbdd09049d682ae57cc94241534b29f0.

Thanks Oli Warner for the detailed report.

Backport of 277ed072094ad87fc6b2c4669f21d43b1f39043c from master
This commit is contained in:
Simon Charette 2018-03-08 02:06:19 -05:00 committed by Tim Graham
parent 8d3bd724ab
commit 0fd21febe7
3 changed files with 11 additions and 3 deletions

View File

@ -972,10 +972,13 @@ class Subquery(Expression):
def __init__(self, queryset, output_field=None, **extra):
self.queryset = queryset
self.extra = extra
if output_field is None and len(self.queryset.query.select) == 1:
output_field = self.queryset.query.select[0].field
super().__init__(output_field)
def _resolve_output_field(self):
if len(self.queryset.query.select) == 1:
return self.queryset.query.select[0].field
return super()._resolve_output_field()
def copy(self):
clone = super().copy()
clone.queryset = clone.queryset.all()

View File

@ -9,4 +9,5 @@ Django 2.0.4 fixes several bugs in 2.0.3.
Bugfixes
========
* ...
* Fixed a crash when filtering with an ``Exists()`` annotation of a queryset
containing a single field (:ticket:`29195`).

View File

@ -417,6 +417,10 @@ class BasicExpressionsTests(TestCase):
outer = Employee.objects.annotate(is_point_of_contact=Exists(inner))
self.assertIs(outer.exists(), True)
def test_exist_single_field_output_field(self):
queryset = Company.objects.values('pk')
self.assertIsInstance(Exists(queryset).output_field, models.BooleanField)
def test_subquery(self):
Company.objects.filter(name='Example Inc.').update(
point_of_contact=Employee.objects.get(firstname='Joe', lastname='Smith'),