mirror of https://github.com/django/django.git
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
|
||||
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)
|
||||
if self.annotation_select:
|
||||
for alias, annotation in self.annotation_select.items():
|
||||
|
@ -1940,7 +1953,7 @@ class Query(BaseExpression):
|
|||
warnings.warn(msg, category=RemovedInDjango40Warning)
|
||||
group_by_cols = annotation.get_group_by_cols()
|
||||
else:
|
||||
if not allow_aliases:
|
||||
if not allow_aliases or alias in column_names:
|
||||
alias = None
|
||||
group_by_cols = annotation.get_group_by_cols(alias=alias)
|
||||
group_by.extend(group_by_cols)
|
||||
|
|
|
@ -11,3 +11,7 @@ Bugfixes
|
|||
|
||||
* Added the ability to handle ``.po`` files containing different plural
|
||||
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)
|
||||
age = models.IntegerField()
|
||||
friends = models.ManyToManyField('self', blank=True)
|
||||
rating = models.FloatField(null=True)
|
||||
|
||||
def __str__(self):
|
||||
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')
|
||||
@skipIf(
|
||||
connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode,
|
||||
|
|
Loading…
Reference in New Issue