summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/models/query.py17
-rw-r--r--tests/modeltests/many_to_one/models.py8
2 files changed, 23 insertions, 2 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index aa2138643e..8fbb942da2 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -10,8 +10,20 @@ import re
if not hasattr(__builtins__, 'set'):
from sets import Set as set
+# The string constant used to separate query parts
LOOKUP_SEPARATOR = '__'
+# The list of valid query types
+QUERY_TERMS=(
+ 'exact', 'iexact',
+ 'contains', 'icontains',
+ 'gt', 'gte', 'lt', 'lte',
+ 'in',
+ 'startswith', 'istartswith', 'endswith', 'iendswith',
+ 'range', 'year', 'month', 'day',
+ 'isnull'
+)
+
# Size of each "chunk" for get_iterator calls.
# Larger values are slightly faster at the expense of more storage space.
GET_ITERATOR_CHUNK_SIZE = 100
@@ -710,12 +722,13 @@ def parse_lookup(kwarg_items, opts):
# if we find "pk", make the clause "exact', and insert
# a dummy name of None, which we will replace when
# we know which table column to grab as the primary key.
- # 2) If there is only one part, assume it to be an __exact
+ # 2) If there is only one part, or the last part is not a query
+ # term, assume that the query is an __exact
clause = path.pop()
if clause == 'pk':
clause = 'exact'
path.append(None)
- elif len(path) == 0:
+ elif len(path) == 0 or clause not in QUERY_TERMS:
path.append(clause)
clause = 'exact'
diff --git a/tests/modeltests/many_to_one/models.py b/tests/modeltests/many_to_one/models.py
index b7d27e2ed3..d202975128 100644
--- a/tests/modeltests/many_to_one/models.py
+++ b/tests/modeltests/many_to_one/models.py
@@ -136,6 +136,10 @@ False
>>> Article.objects.filter(reporter__first_name__exact='John')
[<Article: John's second story>, <Article: This is a test>]
+# Check that implied __exact also works
+>>> Article.objects.filter(reporter__first_name='John')
+[<Article: John's second story>, <Article: This is a test>]
+
# Query twice over the related field.
>>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
[<Article: John's second story>, <Article: This is a test>]
@@ -237,6 +241,10 @@ TypeError: Cannot resolve keyword 'reporter_id' into field
>>> Reporter.objects.filter(article__reporter__exact=r).distinct()
[<Reporter: John Smith>]
+# Check that implied __exact also works
+>>> Reporter.objects.filter(article__reporter=r).distinct()
+[<Reporter: John Smith>]
+
# If you delete a reporter, his articles will be deleted.
>>> Article.objects.all()
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]