Skip to content

Commit

Permalink
Fixed #2756 -- Modified the get_object_or_404/get_list_or_404 shortcu…
Browse files Browse the repository at this point in the history
…ts 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
  • Loading branch information
freakboy3742 committed Jan 3, 2007
1 parent c3f8912 commit e1c6e98
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 4 deletions.
15 changes: 12 additions & 3 deletions django/shortcuts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
40 changes: 40 additions & 0 deletions docs/db-api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
=======================

Expand Down
2 changes: 1 addition & 1 deletion docs/tutorial03.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Empty file.
86 changes: 86 additions & 0 deletions tests/modeltests/get_object_or_404/models.py
Original file line number Diff line number Diff line change
@@ -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!>]
"""}

0 comments on commit e1c6e98

Please sign in to comment.