Fixed #4373 -- Modified the get_object_or_404/get_list_or_404 shortcuts to also accept `QuerySet`s. Thanks SuperJared.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5746 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Gary Wilson Jr 2007-07-22 03:41:11 +00:00
parent 63cc023eea
commit cae92ae615
4 changed files with 60 additions and 23 deletions

View File

@ -242,6 +242,7 @@ answer newbie questions, and generally made Django that much better:
Thomas Steinacher <http://www.eggdrop.ch/> Thomas Steinacher <http://www.eggdrop.ch/>
nowell strite nowell strite
Sundance Sundance
SuperJared
Radek Švarz <http://www.svarz.cz/translate/> Radek Švarz <http://www.svarz.cz/translate/>
Swaroop C H <http://www.swaroopch.info> Swaroop C H <http://www.swaroopch.info>
Aaron Swartz <http://www.aaronsw.com/> Aaron Swartz <http://www.aaronsw.com/>

View File

@ -7,6 +7,7 @@ for convenience's sake.
from django.template import loader from django.template import loader
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.db.models.manager import Manager from django.db.models.manager import Manager
from django.db.models.query import QuerySet
def render_to_response(*args, **kwargs): def render_to_response(*args, **kwargs):
""" """
@ -16,40 +17,46 @@ def render_to_response(*args, **kwargs):
return HttpResponse(loader.render_to_string(*args, **kwargs)) return HttpResponse(loader.render_to_string(*args, **kwargs))
load_and_render = render_to_response # For backwards compatibility. load_and_render = render_to_response # For backwards compatibility.
def _get_queryset(klass):
"""
Return a QuerySet from a Model, Manager, or QuerySet. Created to make
get_object_or_404 and get_list_or_404 more DRY.
"""
if isinstance(klass, QuerySet):
return klass
elif isinstance(klass, Manager):
manager = klass
else:
manager = klass._default_manager
return manager.all()
def get_object_or_404(klass, *args, **kwargs): def get_object_or_404(klass, *args, **kwargs):
""" """
Use get() to return an object, or raise a Http404 exception if the object Use get() to return an object, or raise a Http404 exception if the object
does not exist. does not exist.
klass may be a Model or Manager object. All other passed klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query. arguments and keyword arguments are used in the get() query.
Note: Like with get(), an AssertionError will be raised if more than one Note: Like with get(), an AssertionError will be raised if more than one
object is found. object is found.
""" """
if isinstance(klass, Manager): queryset = _get_queryset(klass)
manager = klass
klass = manager.model
else:
manager = klass._default_manager
try: try:
return manager.get(*args, **kwargs) return queryset.get(*args, **kwargs)
except klass.DoesNotExist: except queryset.model.DoesNotExist:
raise Http404('No %s matches the given query.' % klass._meta.object_name) raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
def get_list_or_404(klass, *args, **kwargs): def get_list_or_404(klass, *args, **kwargs):
""" """
Use filter() to return a list of objects, or raise a Http404 exception if Use filter() to return a list of objects, or raise a Http404 exception if
the list is empty. the list is emtpy.
klass may be a Model or Manager object. All other passed klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the filter() query. arguments and keyword arguments are used in the filter() query.
""" """
if isinstance(klass, Manager): queryset = _get_queryset(klass)
manager = klass obj_list = list(queryset.filter(*args, **kwargs))
else:
manager = klass._default_manager
obj_list = list(manager.filter(*args, **kwargs))
if not obj_list: if not obj_list:
raise Http404('No %s matches the given query.' % manager.model._meta.object_name) raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
return obj_list return obj_list

View File

@ -1891,8 +1891,8 @@ get_object_or_404()
One common idiom to use ``get()`` and raise ``Http404`` if the One common idiom to use ``get()`` and raise ``Http404`` if the
object doesn't exist. This idiom is captured by ``get_object_or_404()``. object doesn't exist. This idiom is captured by ``get_object_or_404()``.
This function takes a Django model as its first argument and an This function takes a Django model as its first argument and an
arbitrary number of keyword arguments, which it passes to the manager's arbitrary number of keyword arguments, which it passes to the default
``get()`` function. It raises ``Http404`` if the object doesn't manager's ``get()`` function. It raises ``Http404`` if the object doesn't
exist. For example:: exist. For example::
# Get the Entry with a primary key of 3 # Get the Entry with a primary key of 3
@ -1901,7 +1901,7 @@ exist. For example::
When you provide a model to this shortcut function, the default manager When you provide a model to this shortcut function, the default manager
is used to execute the underlying ``get()`` query. If you don't want to is used to execute the underlying ``get()`` query. If you don't want to
use the default manager, or if you want to search a list of related objects, use the default manager, or if you want to search a list of related objects,
you can provide ``get_object_or_404()`` with a manager object instead. you can provide ``get_object_or_404()`` with a ``Manager`` object instead.
For example:: For example::
# Get the author of blog instance e with a name of 'Fred' # Get the author of blog instance e with a name of 'Fred'
@ -1911,6 +1911,14 @@ For example::
# entry with a primary key of 3 # entry with a primary key of 3
e = get_object_or_404(Entry.recent_entries, pk=3) e = get_object_or_404(Entry.recent_entries, pk=3)
If you need to use a custom method that you added to a custom manager,
then you can provide ``get_object_or_404()`` with a ``QuerySet`` object.
For example::
# Use a QuerySet returned from a 'published' method of a custom manager
# in the search for an entry with primary key of 5
e = get_object_or_404(Entry.objects.published(), pk=5)
get_list_or_404() get_list_or_404()
----------------- -----------------

View File

@ -3,11 +3,11 @@
get_object_or_404 is a shortcut function to be used in view functions for get_object_or_404 is a shortcut function to be used in view functions for
performing a get() lookup and raising a Http404 exception if a DoesNotExist performing a get() lookup and raising a Http404 exception if a DoesNotExist
exception was rasied during the get() call. exception was raised during the get() call.
get_list_or_404 is a shortcut function to be used in view functions for get_list_or_404 is a shortcut function to be used in view functions for
performing a filter() lookup and raising a Http404 exception if a DoesNotExist performing a filter() lookup and raising a Http404 exception if a DoesNotExist
exception was rasied during the filter() call. exception was raised during the filter() call.
""" """
from django.db import models from django.db import models
@ -69,11 +69,28 @@ Http404: No Article matches the given query.
>>> get_object_or_404(Article.by_a_sir, title="Run away!") >>> get_object_or_404(Article.by_a_sir, title="Run away!")
<Article: Run away!> <Article: Run away!>
# QuerySets can be used too.
>>> get_object_or_404(Article.objects.all(), title__contains="Run")
<Article: Run away!>
# Just as when using a get() lookup, you will get an error if more than one
# object is returned.
>>> get_object_or_404(Author.objects.all())
Traceback (most recent call last):
...
AssertionError: get() returned more than one Author -- it returned ...! Lookup parameters were {}
# Using an EmptyQuerySet raises a Http404 error.
>>> get_object_or_404(Article.objects.none(), title__contains="Run")
Traceback (most recent call last):
...
Http404: No Article matches the given query.
# get_list_or_404 can be used to get lists of objects # get_list_or_404 can be used to get lists of objects
>>> get_list_or_404(a.article_set, title__icontains='Run') >>> get_list_or_404(a.article_set, title__icontains='Run')
[<Article: Run away!>] [<Article: Run away!>]
# Http404 is returned if the list is empty # Http404 is returned if the list is empty.
>>> get_list_or_404(a.article_set, title__icontains='Shrubbery') >>> get_list_or_404(a.article_set, title__icontains='Shrubbery')
Traceback (most recent call last): Traceback (most recent call last):
... ...
@ -83,4 +100,8 @@ Http404: No Article matches the given query.
>>> get_list_or_404(Article.by_a_sir, title__icontains="Run") >>> get_list_or_404(Article.by_a_sir, title__icontains="Run")
[<Article: Run away!>] [<Article: Run away!>]
# QuerySets can be used too.
>>> get_list_or_404(Article.objects.all(), title__icontains="Run")
[<Article: Run away!>]
"""} """}