Code

Ticket #5535: 5535.2.diff

File 5535.2.diff, 4.3 KB (added by koniiiik, 3 years ago)

Patch with documentation

Line 
1diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
2index 9a5666b..02af89a 100644
3--- a/django/db/models/sql/query.py
4+++ b/django/db/models/sql/query.py
5@@ -1065,8 +1065,9 @@ class Query(object):
6 
7         try:
8             field, target, opts, join_list, last, extra_filters = self.setup_joins(
9-                    parts, opts, alias, True, allow_many, can_reuse=can_reuse,
10-                    negate=negate, process_extras=process_extras)
11+                    parts, opts, alias, True, allow_many, allow_explicit_fk=True,
12+                    can_reuse=can_reuse, negate=negate,
13+                    process_extras=process_extras)
14         except MultiJoin, e:
15             self.split_exclude(filter_expr, LOOKUP_SEP.join(parts[:e.level]),
16                     can_reuse)
17diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
18index 3457913..b63ff10 100644
19--- a/docs/topics/db/queries.txt
20+++ b/docs/topics/db/queries.txt
21@@ -365,6 +365,17 @@ translates (roughly) into the following SQL::
22 
23    .. _`Keyword Arguments`: http://docs.python.org/tutorial/controlflow.html#keyword-arguments
24 
25+.. versionchanged:: 1.4
26+
27+The field specified in a lookup has to be the name of a model field.
28+There's one exception though, in case of a
29+:class:`~django.db.models.fields.ForeignKey` you can specify the field
30+name suffixed with ``_id``. In this case, the value parameter is expected
31+to contain the raw value of the foreign model's primary key. For
32+example::
33+
34+    >>> Entry.objects.filter(blog_id__exact=4)
35+
36 If you pass an invalid keyword argument, a lookup function will raise
37 ``TypeError``.
38 
39diff --git a/tests/modeltests/many_to_one/tests.py b/tests/modeltests/many_to_one/tests.py
40index 2d474c0..b9ba711 100644
41--- a/tests/modeltests/many_to_one/tests.py
42+++ b/tests/modeltests/many_to_one/tests.py
43@@ -1,6 +1,6 @@
44 from datetime import datetime
45 from django.test import TestCase
46-from django.core.exceptions import FieldError
47+from django.core.exceptions import FieldError, MultipleObjectsReturned
48 from models import Article, Reporter
49 
50 class ManyToOneTests(TestCase):
51@@ -226,10 +226,6 @@ class ManyToOneTests(TestCase):
52                 "<Article: John's second story>",
53                 "<Article: This is a test>",
54             ])
55-        # You need two underscores between "reporter" and "id" -- not one.
56-        self.assertRaises(FieldError, Article.objects.filter, reporter_id__exact=self.r.id)
57-        # You need to specify a comparison clause
58-        self.assertRaises(FieldError, Article.objects.filter, reporter_id=self.r.id)
59 
60     def test_reverse_selects(self):
61         a3 = Article.objects.create(id=None, headline="Third article",
62@@ -370,3 +366,33 @@ class ManyToOneTests(TestCase):
63         self.r.cached_query = Article.objects.filter(reporter=self.r)
64         from copy import deepcopy
65         self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")
66+
67+    def test_explicit_fk(self):
68+        # Create a new Article with get_or_create using an explicit value
69+        # for a ForeignKey.
70+        a2, created = Article.objects.get_or_create(id=None,
71+                                                    headline="John's second test",
72+                                                    pub_date=datetime(2011, 5, 7),
73+                                                    reporter_id=self.r.id)
74+        self.assertTrue(created)
75+        self.assertEqual(a2.reporter.id, self.r.id)
76+
77+        # You can specify filters containing the explicit FK value.
78+        self.assertQuerysetEqual(Article.objects.filter(reporter_id__exact=self.r.id),
79+            [
80+                "<Article: John's second test>",
81+                "<Article: This is a test>",
82+            ])
83+
84+        # Create an Article by Paul for the same date.
85+        a3 = Article.objects.create(id=None, headline="Paul's commentary",
86+                                    pub_date=datetime(2011, 5, 7),
87+                                    reporter_id=self.r2.id)
88+        self.assertEqual(a3.reporter.id, self.r2.id)
89+
90+        # Get should respect explicit foreign keys as well.
91+        self.assertRaises(MultipleObjectsReturned,
92+                          Article.objects.get, reporter_id=self.r.id)
93+        self.assertEqual(repr(Article.objects.get(reporter_id=self.r2.id,
94+                                             pub_date=datetime(2011, 5, 7))),
95+                         repr(a3))