1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Fixed #28289 -- Fixed crash of RawSQL annotations on inherited model fields.

This commit is contained in:
can 2019-07-10 15:07:48 +03:00 committed by Mariusz Felisiak
parent a9c6ab0356
commit 52545e788d
3 changed files with 33 additions and 0 deletions

View File

@ -699,6 +699,16 @@ class RawSQL(Expression):
def get_group_by_cols(self, alias=None): def get_group_by_cols(self, alias=None):
return [self] return [self]
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
# Resolve parents fields used in raw SQL.
for parent in query.model._meta.get_parent_list():
for parent_field in parent._meta.local_fields:
_, column_name = parent_field.get_attname_column()
if column_name.lower() in self.sql.lower():
query.resolve_ref(parent_field.name, allow_joins, reuse, summarize)
break
return super().resolve_expression(query, allow_joins, reuse, summarize, for_save)
class Star(Expression): class Star(Expression):
def __repr__(self): def __repr__(self):

View File

@ -38,6 +38,7 @@ class Store(models.Model):
books = models.ManyToManyField(Book) books = models.ManyToManyField(Book)
original_opening = models.DateTimeField() original_opening = models.DateTimeField()
friday_night_closing = models.TimeField() friday_night_closing = models.TimeField()
area = models.IntegerField(null=True, db_column='surface')
def __str__(self): def __str__(self):
return self.name return self.name

View File

@ -405,6 +405,28 @@ class NonAggregateAnnotationTestCase(TestCase):
lambda a: (a['age'], a['age_count']) lambda a: (a['age'], a['age_count'])
) )
def test_raw_sql_with_inherited_field(self):
DepartmentStore.objects.create(
name='Angus & Robinson',
original_opening=datetime.date(2014, 3, 8),
friday_night_closing=datetime.time(21),
chain='Westfield',
area=123,
)
tests = (
('name', 'Angus & Robinson'),
('surface', 123),
("case when name='Angus & Robinson' then chain else name end", 'Westfield'),
)
for sql, expected_result in tests:
with self.subTest(sql=sql):
self.assertSequenceEqual(
DepartmentStore.objects.annotate(
annotation=RawSQL(sql, ()),
).values_list('annotation', flat=True),
[expected_result],
)
def test_annotate_exists(self): def test_annotate_exists(self):
authors = Author.objects.annotate(c=Count('id')).filter(c__gt=1) authors = Author.objects.annotate(c=Count('id')).filter(c__gt=1)
self.assertFalse(authors.exists()) self.assertFalse(authors.exists())