summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJannis Leidel <jannis@leidel.info>2011-06-28 10:16:18 +0000
committerJannis Leidel <jannis@leidel.info>2011-06-28 10:16:18 +0000
commitdbffffa7dc95fc62cbecfd00284bde62ee796f48 (patch)
treed481cff58c0a77044407d99d0ccbe5a50004d842
parentf54135fa4dc9fd45d86ea2944191d58e00725779 (diff)
Fixed #5535 -- Allow using an explicit foreign key in get() calls. Thanks, Michal Petrucha.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16473 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/db/models/sql/query.py5
-rw-r--r--docs/topics/db/queries.txt10
-rw-r--r--tests/modeltests/many_to_one/tests.py37
3 files changed, 45 insertions, 7 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 99663b646b..110e3179d5 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1068,8 +1068,9 @@ class Query(object):
try:
field, target, opts, join_list, last, extra_filters = self.setup_joins(
- parts, opts, alias, True, allow_many, can_reuse=can_reuse,
- negate=negate, process_extras=process_extras)
+ parts, opts, alias, True, allow_many, allow_explicit_fk=True,
+ can_reuse=can_reuse, negate=negate,
+ process_extras=process_extras)
except MultiJoin, e:
self.split_exclude(filter_expr, LOOKUP_SEP.join(parts[:e.level]),
can_reuse)
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index 3457913011..a4267489b9 100644
--- a/docs/topics/db/queries.txt
+++ b/docs/topics/db/queries.txt
@@ -365,6 +365,16 @@ translates (roughly) into the following SQL::
.. _`Keyword Arguments`: http://docs.python.org/tutorial/controlflow.html#keyword-arguments
+.. versionchanged:: 1.4
+
+ The field specified in a lookup has to be the name of a model field.
+ There's one exception though, in case of a
+ :class:`~django.db.models.fields.ForeignKey` you can specify the field
+ name suffixed with ``_id``. In this case, the value parameter is expected
+ to contain the raw value of the foreign model's primary key. For example::
+
+ >>> Entry.objects.filter(blog_id__exact=4)
+
If you pass an invalid keyword argument, a lookup function will raise
``TypeError``.
diff --git a/tests/modeltests/many_to_one/tests.py b/tests/modeltests/many_to_one/tests.py
index 8a2af2157b..83e984dc6d 100644
--- a/tests/modeltests/many_to_one/tests.py
+++ b/tests/modeltests/many_to_one/tests.py
@@ -2,7 +2,7 @@ from copy import deepcopy
from datetime import datetime
from django.test import TestCase
-from django.core.exceptions import FieldError
+from django.core.exceptions import FieldError, MultipleObjectsReturned
from models import Article, Reporter
@@ -229,10 +229,6 @@ class ManyToOneTests(TestCase):
"<Article: John's second story>",
"<Article: This is a test>",
])
- # You need two underscores between "reporter" and "id" -- not one.
- self.assertRaises(FieldError, Article.objects.filter, reporter_id__exact=self.r.id)
- # You need to specify a comparison clause
- self.assertRaises(FieldError, Article.objects.filter, reporter_id=self.r.id)
def test_reverse_selects(self):
a3 = Article.objects.create(id=None, headline="Third article",
@@ -372,3 +368,34 @@ class ManyToOneTests(TestCase):
# recursive don't cause recursion depth problems under deepcopy.
self.r.cached_query = Article.objects.filter(reporter=self.r)
self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")
+
+ def test_explicit_fk(self):
+ # Create a new Article with get_or_create using an explicit value
+ # for a ForeignKey.
+ a2, created = Article.objects.get_or_create(id=None,
+ headline="John's second test",
+ pub_date=datetime(2011, 5, 7),
+ reporter_id=self.r.id)
+ self.assertTrue(created)
+ self.assertEqual(a2.reporter.id, self.r.id)
+
+ # You can specify filters containing the explicit FK value.
+ self.assertQuerysetEqual(
+ Article.objects.filter(reporter_id__exact=self.r.id),
+ [
+ "<Article: John's second test>",
+ "<Article: This is a test>",
+ ])
+
+ # Create an Article by Paul for the same date.
+ a3 = Article.objects.create(id=None, headline="Paul's commentary",
+ pub_date=datetime(2011, 5, 7),
+ reporter_id=self.r2.id)
+ self.assertEqual(a3.reporter.id, self.r2.id)
+
+ # Get should respect explicit foreign keys as well.
+ self.assertRaises(MultipleObjectsReturned,
+ Article.objects.get, reporter_id=self.r.id)
+ self.assertEqual(repr(a3),
+ repr(Article.objects.get(reporter_id=self.r2.id,
+ pub_date=datetime(2011, 5, 7))))