Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[1.5.x] Fixed #21126 -- QuerySet value conversion failure

A .annotate().select_related() query resulted in misaligned rows vs
columns for compiler.resolve_columns() method.

Report & patch by Michael Manfre.

Backpatch of 83554b0 from master.
  • Loading branch information...
commit b7e5b5ba1ed03243f53f9f0bbaa58a33691c815d 1 parent 43ab759
@akaariai akaariai authored
View
2  django/db/backends/__init__.py
@@ -895,7 +895,7 @@ def convert_values(self, value, field):
Coerce the value returned by the database backend into a consistent type
that is compatible with the field type.
"""
- if value is None:
+ if value is None or field is None:
return value
internal_type = field.get_internal_type()
if internal_type == 'FloatField':
View
10 django/db/models/sql/compiler.py
@@ -774,6 +774,9 @@ def results_iter(self):
transaction.set_dirty(self.using)
for rows in self.execute_sql(MULTI):
for row in rows:
+ if has_aggregate_select:
+ aggregate_start = len(self.query.extra_select) + len(self.query.select)
+ aggregate_end = aggregate_start + len(self.query.aggregate_select)
if resolve_columns:
if fields is None:
# We only set this up here because
@@ -800,11 +803,14 @@ def results_iter(self):
db_table = self.query.model._meta.db_table
fields = [f for f in fields if db_table in only_load and
f.column in only_load[db_table]]
+ if has_aggregate_select:
+ # pad None in to fields for aggregates
+ fields = fields[:aggregate_start] + [
+ None for x in range(0, aggregate_end - aggregate_start)
+ ] + fields[aggregate_start:]
row = self.resolve_columns(row, fields)
if has_aggregate_select:
- aggregate_start = len(self.query.extra_select) + len(self.query.select)
- aggregate_end = aggregate_start + len(self.query.aggregate_select)
row = tuple(row[:aggregate_start]) + tuple([
self.query.resolve_aggregate(value, aggregate, self.connection)
for (alias, aggregate), value
View
11 tests/regressiontests/aggregation_regress/tests.py
@@ -383,6 +383,17 @@ def test_db_col_table(self):
qs = Entries.objects.annotate(clue_count=Count('clues__ID'))
self.assertQuerysetEqual(qs, [])
+ def test_boolean_conversion(self):
+ # Aggregates mixed up ordering of columns for backend's convert_values
+ # method. Refs #21126.
+ e = Entries.objects.create(Entry='foo')
+ c = Clues.objects.create(EntryID=e, Clue='bar')
+ qs = Clues.objects.select_related('EntryID').annotate(Count('ID'))
+ self.assertQuerysetEqual(
+ qs, [c], lambda x: x)
+ self.assertEqual(qs[0].EntryID, e)
+ self.assertIs(qs[0].EntryID.Exclude, False)
+
def test_empty(self):
# Regression for #10089: Check handling of empty result sets with
# aggregates
Please sign in to comment.
Something went wrong with that request. Please try again.