Fixed #2756 -- Modified the get_object_or_404/get_list_or_404 shortcuts to accept model managers as well as model classes. Thanks, Gary Wilson.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4275 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2007-01-03 14:16:58 +00:00
parent c3f891210a
commit e1c6e987d0
5 changed files with 139 additions and 4 deletions

View File

@ -4,20 +4,29 @@
from django.template import loader
from django.http import HttpResponse, Http404
from django.db.models.manager import Manager
def render_to_response(*args, **kwargs):
return HttpResponse(loader.render_to_string(*args, **kwargs))
load_and_render = render_to_response # For backwards compatibility.
def get_object_or_404(klass, *args, **kwargs):
if isinstance(klass, Manager):
manager = klass
klass = manager.model
else:
manager = klass._default_manager
try:
return klass._default_manager.get(*args, **kwargs)
return manager.get(*args, **kwargs)
except klass.DoesNotExist:
raise Http404
def get_list_or_404(klass, *args, **kwargs):
obj_list = list(klass._default_manager.filter(*args, **kwargs))
if isinstance(klass, Manager):
manager = klass
else:
manager = klass._default_manager
obj_list = list(manager.filter(*args, **kwargs))
if not obj_list:
raise Http404
return obj_list

View File

@ -1704,6 +1704,46 @@ For every ``ImageField``, the object will have ``get_FOO_height()`` and
``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This
returns the height (or width) of the image, as an integer, in pixels.
Shortcuts
=========
As you develop views, you will discover a number of common idioms in the
way you use the database API. Django encodes some of these idioms as
shortcuts that can be used to simplify the process of writing views.
get_object_or_404()
-------------------
One common idiom to use ``get()`` and raise ``Http404`` if the
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
arbitrary number of keyword arguments, which it passes to the manager's
``get()`` function. It raises ``Http404`` if the object doesn't
exist. For example::
# Get the Entry with a primary key of 3
e = get_object_or_404(Entry, pk=3)
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
use the default manager, or you want to search a list of related objects,
you can provide ``get_object_or_404()`` with a manager object, instead.
For example::
# Get the author of blog instance `e` with a name of 'Fred'
a = get_object_or_404(e.authors, name='Fred')
# Use a custom manager 'recent_entries' in the search for an
# entry with a primary key of 3
e = get_object_or_404(Entry.recent_entries, pk=3)
get_list_or_404()
-----------------
``get_list_or_404`` behaves the same was as ``get_object_or_404()``
-- except the it uses using ``filter()`` instead of ``get()``. It raises
``Http404`` if the list is empty.
Falling back to raw SQL
=======================

View File

@ -300,7 +300,7 @@ rewritten::
The ``get_object_or_404()`` function takes a Django model module as its first
argument and an arbitrary number of keyword arguments, which it passes to the
module's ``get_object()`` function. It raises ``Http404`` if the object doesn't
module's ``get()`` function. It raises ``Http404`` if the object doesn't
exist.
.. admonition:: Philosophy

View File

@ -0,0 +1,86 @@
"""
34. DB-API Shortcuts
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
exception was rasied during the get() call.
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
exception was rasied during the filter() call.
"""
from django.db import models
from django.http import Http404
from django.shortcuts import get_object_or_404, get_list_or_404
class Author(models.Model):
name = models.CharField(maxlength=50)
def __str__(self):
return self.name
class ArticleManager(models.Manager):
def get_query_set(self):
return super(ArticleManager, self).get_query_set().filter(authors__name__icontains='sir')
class Article(models.Model):
authors = models.ManyToManyField(Author)
title = models.CharField(maxlength=50)
objects = models.Manager()
by_a_sir = ArticleManager()
def __str__(self):
return self.title
__test__ = {'API_TESTS':"""
# Create some Authors.
>>> a = Author.objects.create(name="Brave Sir Robin")
>>> a.save()
>>> a2 = Author.objects.create(name="Patsy")
>>> a2.save()
# No Articles yet, so we should get a Http404 error.
>>> get_object_or_404(Article, title="Foo")
Traceback (most recent call last):
...
Http404
# Create an Article.
>>> article = Article.objects.create(title="Run away!")
>>> article.authors = [a, a2]
>>> article.save()
# get_object_or_404 can be passed a Model to query.
>>> get_object_or_404(Article, title__contains="Run")
<Article: Run away!>
# We can also use the the Article manager through an Author object.
>>> get_object_or_404(a.article_set, title__contains="Run")
<Article: Run away!>
# No articles containing "Camelot". This should raise a Http404 error.
>>> get_object_or_404(a.article_set, title__contains="Camelot")
Traceback (most recent call last):
...
Http404
# Custom managers can be used too.
>>> get_object_or_404(Article.by_a_sir, title="Run away!")
<Article: Run away!>
# get_list_or_404 can be used to get lists of objects
>>> get_list_or_404(a.article_set, title__icontains='Run')
[<Article: Run away!>]
# Http404 is returned if the list is empty
>>> get_list_or_404(a.article_set, title__icontains='Shrubbery')
Traceback (most recent call last):
...
Http404
# Custom managers can be used too.
>>> get_list_or_404(Article.by_a_sir, title__icontains="Run")
[<Article: Run away!>]
"""}