From 0c41869e6ccf779e19032dede71a627c4370b68a Mon Sep 17 00:00:00 2001
From: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon, 25 Sep 2006 13:49:01 +0000
Subject: [PATCH] Made ``pk`` a generic expansion for the primary key, rather
 than just an expansion for __id__exact.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3826 bcc190cf-cafb-0310-a4f2-bffc1f526a37
---
 django/db/models/query.py            | 14 +++++---------
 docs/db-api.txt                      | 10 +++++++++-
 tests/modeltests/basic/models.py     |  4 ++++
 tests/modeltests/custom_pk/models.py |  4 ++++
 4 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/django/db/models/query.py b/django/db/models/query.py
index 0b85c3f515..eb4b3b63ae 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -712,14 +712,10 @@ def parse_lookup(kwarg_items, opts):
             # Extract the last elements of the kwarg.
             # The very-last is the lookup_type (equals, like, etc).
             # The second-last is the table column on which the lookup_type is
-            # to be performed.
-            # The exceptions to this are:
-            # 1)  "pk", which is an implicit id__exact;
-            #     if we find "pk", make the lookup_type "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, or the last part is not a query
-            #     term, assume that the query is an __exact
+            # to be performed. If this name is 'pk', it will be substituted with
+            # the name of the primary key.
+            # If there is only one part, or the last part is not a query
+            # term, assume that the query is an __exact
             lookup_type = path.pop()
             if lookup_type == 'pk':
                 lookup_type = 'exact'
@@ -766,7 +762,7 @@ def lookup_inner(path, lookup_type, value, opts, table, column):
     name = path.pop(0)
     # Has the primary key been requested? If so, expand it out
     # to be the name of the current class' primary key
-    if name is None:
+    if name is None or name == 'pk':
         name = current_opts.pk.name
 
     # Try to find the name in the fields associated with the current class
diff --git a/docs/db-api.txt b/docs/db-api.txt
index 7800ff324a..0d1f049601 100644
--- a/docs/db-api.txt
+++ b/docs/db-api.txt
@@ -1140,7 +1140,7 @@ The pk lookup shortcut
 ----------------------
 
 For convenience, Django provides a ``pk`` lookup type, which stands for
-"primary_key". This is shorthand for "an exact lookup on the primary-key."
+"primary_key". 
 
 In the example ``Blog`` model, the primary key is the ``id`` field, so these
 three statements are equivalent::
@@ -1149,6 +1149,14 @@ three statements are equivalent::
     Blog.objects.get(id=14) # __exact is implied
     Blog.objects.get(pk=14) # pk implies id__exact
 
+The use of ``pk`` isn't limited to ``__exact`` queries -- any query term 
+can be combined with ``pk`` to perform a query on the primary key of a model::
+
+    # Get blogs entries  with id 1, 4 and 7
+    Blog.objects.filter(pk__in=[1,4,7])
+    # Get all blog entries with id > 14
+    Blog.objects.filter(pk__gt=14) 
+    
 ``pk`` lookups also work across joins. For example, these three statements are
 equivalent::
 
diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py
index acbea0d1e0..5638865f31 100644
--- a/tests/modeltests/basic/models.py
+++ b/tests/modeltests/basic/models.py
@@ -86,6 +86,10 @@ DoesNotExist: Article matching query does not exist.
 >>> Article.objects.get(pk=1)
 <Article: Area woman programs in Python>
 
+# pk can be used as a shortcut for the primary key name in any query
+>>> Article.objects.filter(pk__in=[1])
+[<Article: Area woman programs in Python>]
+
 # Model instances of the same type and same ID are considered equal.
 >>> a = Article.objects.get(pk=1)
 >>> b = Article.objects.get(pk=1)
diff --git a/tests/modeltests/custom_pk/models.py b/tests/modeltests/custom_pk/models.py
index ca788f6aa5..fd0901da3c 100644
--- a/tests/modeltests/custom_pk/models.py
+++ b/tests/modeltests/custom_pk/models.py
@@ -51,6 +51,10 @@ DoesNotExist: Employee matching query does not exist.
 >>> Employee.objects.get(employee_code__exact='ABC123')
 <Employee: Dan Jones>
 
+# pk can be used as a substitute for the primary key.
+>>> Employee.objects.filter(pk__in=['ABC123','XYZ456'])
+[<Employee: Fran Bones>, <Employee: Dan Jones>]
+
 # Fran got married and changed her last name.
 >>> fran = Employee.objects.get(pk='XYZ456')
 >>> fran.last_name = 'Jones'