From 0c41869e6ccf779e19032dede71a627c4370b68a Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee 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 0b85c3f515c..eb4b3b63aee 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 7800ff324a4..0d1f0496014 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 acbea0d1e0b..5638865f310 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) +# pk can be used as a shortcut for the primary key name in any query +>>> Article.objects.filter(pk__in=[1]) +[] + # 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 ca788f6aa53..fd0901da3c7 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') +# pk can be used as a substitute for the primary key. +>>> Employee.objects.filter(pk__in=['ABC123','XYZ456']) +[, ] + # Fran got married and changed her last name. >>> fran = Employee.objects.get(pk='XYZ456') >>> fran.last_name = 'Jones'