summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2012-05-09 20:33:31 +0300
committerAnssi Kääriäinen <akaariai@gmail.com>2012-05-09 20:33:31 +0300
commitc2e1ecb4b136016ab2996712aa0583fd91657bc9 (patch)
tree1a263f7a93ac5c2887b7ad2425a37b8dc191fecc
parent1b05546bd50d1bf99e3d0e7def1238edf8d44065 (diff)
Fix proxy model Query.remove_inherited_models()
Fixed #18248 -- proxy models were added to included_inherited_models in sql.query.Query. The variable is meant to be used for multitable inheritance only. This mistake caused problems in situations where proxy model's query was reused.
-rw-r--r--django/db/models/sql/compiler.py13
-rw-r--r--django/db/models/sql/query.py15
-rw-r--r--tests/regressiontests/queries/models.py4
-rw-r--r--tests/regressiontests/queries/tests.py14
4 files changed, 27 insertions, 19 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 69b508fe97..33949f5a71 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -261,12 +261,12 @@ class SQLCompiler(object):
result = []
if opts is None:
opts = self.query.model._meta
+ # Skip all proxy to the root proxied model
+ opts = opts.concrete_model._meta
qn = self.quote_name_unless_alias
qn2 = self.connection.ops.quote_name
aliases = set()
only_load = self.deferred_to_columns()
- # Skip all proxy to the root proxied model
- proxied_model = opts.concrete_model
if start_alias:
seen = {None: start_alias}
@@ -277,12 +277,9 @@ class SQLCompiler(object):
try:
alias = seen[model]
except KeyError:
- if model is proxied_model:
- alias = start_alias
- else:
- link_field = opts.get_ancestor_link(model)
- alias = self.query.join((start_alias, model._meta.db_table,
- link_field.column, model._meta.pk.column))
+ link_field = opts.get_ancestor_link(model)
+ alias = self.query.join((start_alias, model._meta.db_table,
+ link_field.column, model._meta.pk.column))
seen[model] = alias
else:
# If we're starting from the base model of the queryset, the
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index efbc0c95a3..c91215fa9e 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -933,21 +933,16 @@ class Query(object):
whereas column determination is a later part, and side-effect, of
as_sql()).
"""
- opts = self.model._meta
+ # Skip all proxy models
+ opts = self.model._meta.concrete_model._meta
root_alias = self.tables[0]
seen = {None: root_alias}
- # Skip all proxy to the root proxied model
- proxied_model = opts.concrete_model
-
for field, model in opts.get_fields_with_model():
if model not in seen:
- if model is proxied_model:
- seen[model] = root_alias
- else:
- link_field = opts.get_ancestor_link(model)
- seen[model] = self.join((root_alias, model._meta.db_table,
- link_field.column, model._meta.pk.column))
+ link_field = opts.get_ancestor_link(model)
+ seen[model] = self.join((root_alias, model._meta.db_table,
+ link_field.column, model._meta.pk.column))
self.included_inherited_models = seen
def remove_inherited_models(self):
diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
index 89eefdf48e..07aa6db67b 100644
--- a/tests/regressiontests/queries/models.py
+++ b/tests/regressiontests/queries/models.py
@@ -10,6 +10,10 @@ from django.db import models
class DumbCategory(models.Model):
pass
+class ProxyCategory(DumbCategory):
+ class Meta:
+ proxy = True
+
class NamedCategory(DumbCategory):
name = models.CharField(max_length=10)
diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
index 416970d493..8e86903724 100644
--- a/tests/regressiontests/queries/tests.py
+++ b/tests/regressiontests/queries/tests.py
@@ -19,7 +19,7 @@ from .models import (Annotation, Article, Author, Celebrity, Child, Cover,
ManagedModel, Member, NamedCategory, Note, Number, Plaything, PointerA,
Ranking, Related, Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten,
Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory,
- SpecialCategory, OneToOneCategory, NullableName)
+ SpecialCategory, OneToOneCategory, NullableName, ProxyCategory)
class BaseQuerysetTest(TestCase):
@@ -1952,3 +1952,15 @@ class EmptyStringsAsNullTest(TestCase):
DumbCategory.objects.exclude(namedcategory__name__in=['nonexisting']),
[self.nc.pk], attrgetter('pk')
)
+
+class ProxyQueryCleanupTest(TestCase):
+ def test_evaluated_proxy_count(self):
+ """
+ Test that generating the query string doesn't alter the query's state
+ in irreversible ways. Refs #18248.
+ """
+ ProxyCategory.objects.create()
+ qs = ProxyCategory.objects.all()
+ self.assertEqual(qs.count(), 1)
+ str(qs.query)
+ self.assertEqual(qs.count(), 1)