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
This commit is contained in:
Jannis Leidel 2011-06-28 10:16:18 +00:00
parent f54135fa4d
commit dbffffa7dc
3 changed files with 45 additions and 7 deletions

View File

@ -1068,8 +1068,9 @@ class Query(object):
try: try:
field, target, opts, join_list, last, extra_filters = self.setup_joins( field, target, opts, join_list, last, extra_filters = self.setup_joins(
parts, opts, alias, True, allow_many, can_reuse=can_reuse, parts, opts, alias, True, allow_many, allow_explicit_fk=True,
negate=negate, process_extras=process_extras) can_reuse=can_reuse, negate=negate,
process_extras=process_extras)
except MultiJoin, e: except MultiJoin, e:
self.split_exclude(filter_expr, LOOKUP_SEP.join(parts[:e.level]), self.split_exclude(filter_expr, LOOKUP_SEP.join(parts[:e.level]),
can_reuse) can_reuse)

View File

@ -365,6 +365,16 @@ translates (roughly) into the following SQL::
.. _`Keyword Arguments`: http://docs.python.org/tutorial/controlflow.html#keyword-arguments .. _`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 If you pass an invalid keyword argument, a lookup function will raise
``TypeError``. ``TypeError``.

View File

@ -2,7 +2,7 @@ from copy import deepcopy
from datetime import datetime from datetime import datetime
from django.test import TestCase from django.test import TestCase
from django.core.exceptions import FieldError from django.core.exceptions import FieldError, MultipleObjectsReturned
from models import Article, Reporter from models import Article, Reporter
@ -229,10 +229,6 @@ class ManyToOneTests(TestCase):
"<Article: John's second story>", "<Article: John's second story>",
"<Article: This is a test>", "<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): def test_reverse_selects(self):
a3 = Article.objects.create(id=None, headline="Third article", 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. # recursive don't cause recursion depth problems under deepcopy.
self.r.cached_query = Article.objects.filter(reporter=self.r) self.r.cached_query = Article.objects.filter(reporter=self.r)
self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>") 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))))