summaryrefslogtreecommitdiff
path: root/django/db/models/sql/query.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/sql/query.py')
-rw-r--r--django/db/models/sql/query.py18
1 files changed, 16 insertions, 2 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 88847d87e1..4e46da6424 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -18,6 +18,7 @@ from django.db.models import signals
from django.db.models.fields import FieldDoesNotExist
from django.db.models.query_utils import select_related_descend
from django.db.models.sql import aggregates as base_aggregates_module
+from django.db.models.sql.expressions import SQLEvaluator
from django.db.models.sql.where import WhereNode, Constraint, EverythingNode, AND, OR
from django.core.exceptions import FieldError
from datastructures import EmptyResultSet, Empty, MultiJoin
@@ -1271,6 +1272,10 @@ class BaseQuery(object):
else:
lookup_type = parts.pop()
+ # By default, this is a WHERE clause. If an aggregate is referenced
+ # in the value, the filter will be promoted to a HAVING
+ having_clause = False
+
# Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all
# uses of None as a query value.
if value is None:
@@ -1284,6 +1289,10 @@ class BaseQuery(object):
value = True
elif callable(value):
value = value()
+ elif hasattr(value, 'evaluate'):
+ # If value is a query expression, evaluate it
+ value = SQLEvaluator(value, self)
+ having_clause = value.contains_aggregate
for alias, aggregate in self.aggregate_select.items():
if alias == parts[0]:
@@ -1340,8 +1349,13 @@ class BaseQuery(object):
self.promote_alias_chain(join_it, join_promote)
self.promote_alias_chain(table_it, table_promote)
- self.where.add((Constraint(alias, col, field), lookup_type, value),
- connector)
+
+ if having_clause:
+ self.having.add((Constraint(alias, col, field), lookup_type, value),
+ connector)
+ else:
+ self.where.add((Constraint(alias, col, field), lookup_type, value),
+ connector)
if negate:
self.promote_alias_chain(join_list)