mirror of
https://github.com/django/django.git
synced 2024-12-23 01:25:58 +00:00
Fixed #31377 -- Disabled grouping by aliases on QuerySet.values()/values_list() when they collide with field names.
Regression in fb3f034f1c
.
Thanks Holovashchenko Vadym for the report.
This commit is contained in:
parent
895f28f9cb
commit
10866a10fe
@ -1927,6 +1927,19 @@ class Query(BaseExpression):
|
|||||||
primary key, and the query would be equivalent, the optimization
|
primary key, and the query would be equivalent, the optimization
|
||||||
will be made automatically.
|
will be made automatically.
|
||||||
"""
|
"""
|
||||||
|
# Column names from JOINs to check collisions with aliases.
|
||||||
|
if allow_aliases:
|
||||||
|
column_names = set()
|
||||||
|
seen_models = set()
|
||||||
|
for join in list(self.alias_map.values())[1:]: # Skip base table.
|
||||||
|
model = join.join_field.related_model
|
||||||
|
if model not in seen_models:
|
||||||
|
column_names.update({
|
||||||
|
field.column
|
||||||
|
for field in model._meta.local_concrete_fields
|
||||||
|
})
|
||||||
|
seen_models.add(model)
|
||||||
|
|
||||||
group_by = list(self.select)
|
group_by = list(self.select)
|
||||||
if self.annotation_select:
|
if self.annotation_select:
|
||||||
for alias, annotation in self.annotation_select.items():
|
for alias, annotation in self.annotation_select.items():
|
||||||
@ -1940,7 +1953,7 @@ class Query(BaseExpression):
|
|||||||
warnings.warn(msg, category=RemovedInDjango40Warning)
|
warnings.warn(msg, category=RemovedInDjango40Warning)
|
||||||
group_by_cols = annotation.get_group_by_cols()
|
group_by_cols = annotation.get_group_by_cols()
|
||||||
else:
|
else:
|
||||||
if not allow_aliases:
|
if not allow_aliases or alias in column_names:
|
||||||
alias = None
|
alias = None
|
||||||
group_by_cols = annotation.get_group_by_cols(alias=alias)
|
group_by_cols = annotation.get_group_by_cols(alias=alias)
|
||||||
group_by.extend(group_by_cols)
|
group_by.extend(group_by_cols)
|
||||||
|
@ -11,3 +11,7 @@ Bugfixes
|
|||||||
|
|
||||||
* Added the ability to handle ``.po`` files containing different plural
|
* Added the ability to handle ``.po`` files containing different plural
|
||||||
equations for the same language (:ticket:`30439`).
|
equations for the same language (:ticket:`30439`).
|
||||||
|
|
||||||
|
* Fixed a regression in Django 3.0 where ``QuerySet.values()`` and
|
||||||
|
``values_list()`` crashed if a queryset contained an aggregation and
|
||||||
|
``Subquery()`` annotation that collides with a field name (:ticket:`31377`).
|
||||||
|
@ -5,6 +5,7 @@ class Author(models.Model):
|
|||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
age = models.IntegerField()
|
age = models.IntegerField()
|
||||||
friends = models.ManyToManyField('self', blank=True)
|
friends = models.ManyToManyField('self', blank=True)
|
||||||
|
rating = models.FloatField(null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -1191,6 +1191,22 @@ class AggregateTestCase(TestCase):
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_aggregation_subquery_annotation_values_collision(self):
|
||||||
|
books_rating_qs = Book.objects.filter(
|
||||||
|
publisher=OuterRef('pk'),
|
||||||
|
price=Decimal('29.69'),
|
||||||
|
).values('rating')
|
||||||
|
publisher_qs = Publisher.objects.filter(
|
||||||
|
book__contact__age__gt=20,
|
||||||
|
name=self.p1.name,
|
||||||
|
).annotate(
|
||||||
|
rating=Subquery(books_rating_qs),
|
||||||
|
contacts_count=Count('book__contact'),
|
||||||
|
).values('rating').annotate(total_count=Count('rating'))
|
||||||
|
self.assertEqual(list(publisher_qs), [
|
||||||
|
{'rating': 4.0, 'total_count': 2},
|
||||||
|
])
|
||||||
|
|
||||||
@skipUnlessDBFeature('supports_subqueries_in_group_by')
|
@skipUnlessDBFeature('supports_subqueries_in_group_by')
|
||||||
@skipIf(
|
@skipIf(
|
||||||
connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode,
|
connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode,
|
||||||
|
Loading…
Reference in New Issue
Block a user