Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #4373 -- Modified the get_object_or_404/get_list_or_404 shortcu…

…ts to also accept `QuerySet`s. Thanks SuperJared.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5746 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit cae92ae615b8622c25266463e392ef913066ea21 1 parent 63cc023
Gary Wilson Jr. authored July 22, 2007
1  AUTHORS
@@ -242,6 +242,7 @@ answer newbie questions, and generally made Django that much better:
242 242
     Thomas Steinacher <http://www.eggdrop.ch/>
243 243
     nowell strite
244 244
     Sundance
  245
+    SuperJared
245 246
     Radek Švarz <http://www.svarz.cz/translate/>
246 247
     Swaroop C H <http://www.swaroopch.info>
247 248
     Aaron Swartz <http://www.aaronsw.com/>
41  django/shortcuts/__init__.py
@@ -7,6 +7,7 @@
7 7
 from django.template import loader
8 8
 from django.http import HttpResponse, Http404
9 9
 from django.db.models.manager import Manager
  10
+from django.db.models.query import QuerySet
10 11
 
11 12
 def render_to_response(*args, **kwargs):
12 13
     """
@@ -16,40 +17,46 @@ def render_to_response(*args, **kwargs):
16 17
     return HttpResponse(loader.render_to_string(*args, **kwargs))
17 18
 load_and_render = render_to_response # For backwards compatibility.
18 19
 
  20
+def _get_queryset(klass):
  21
+    """
  22
+    Return a QuerySet from a Model, Manager, or QuerySet. Created to make
  23
+    get_object_or_404 and get_list_or_404 more DRY.
  24
+    """
  25
+    if isinstance(klass, QuerySet):
  26
+        return klass
  27
+    elif isinstance(klass, Manager):
  28
+        manager = klass
  29
+    else:
  30
+        manager = klass._default_manager
  31
+    return manager.all()
  32
+
19 33
 def get_object_or_404(klass, *args, **kwargs):
20 34
     """
21 35
     Use get() to return an object, or raise a Http404 exception if the object
22 36
     does not exist.
23 37
 
24  
-    klass may be a Model or Manager object.  All other passed
  38
+    klass may be a Model, Manager, or QuerySet object.  All other passed
25 39
     arguments and keyword arguments are used in the get() query.
26 40
 
27 41
     Note: Like with get(), an AssertionError will be raised if more than one
28 42
     object is found.
29 43
     """
30  
-    if isinstance(klass, Manager):
31  
-        manager = klass
32  
-        klass = manager.model
33  
-    else:
34  
-        manager = klass._default_manager
  44
+    queryset = _get_queryset(klass)
35 45
     try:
36  
-        return manager.get(*args, **kwargs)
37  
-    except klass.DoesNotExist:
38  
-        raise Http404('No %s matches the given query.' % klass._meta.object_name)
  46
+        return queryset.get(*args, **kwargs)
  47
+    except queryset.model.DoesNotExist:
  48
+        raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
39 49
 
40 50
 def get_list_or_404(klass, *args, **kwargs):
41 51
     """
42 52
     Use filter() to return a list of objects, or raise a Http404 exception if
43  
-    the list is empty.
  53
+    the list is emtpy.
44 54
 
45  
-    klass may be a Model or Manager object.  All other passed
  55
+    klass may be a Model, Manager, or QuerySet object.  All other passed
46 56
     arguments and keyword arguments are used in the filter() query.
47 57
     """
48  
-    if isinstance(klass, Manager):
49  
-        manager = klass
50  
-    else:
51  
-        manager = klass._default_manager
52  
-    obj_list = list(manager.filter(*args, **kwargs))
  58
+    queryset = _get_queryset(klass)
  59
+    obj_list = list(queryset.filter(*args, **kwargs))
53 60
     if not obj_list:
54  
-        raise Http404('No %s matches the given query.' % manager.model._meta.object_name)
  61
+        raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
55 62
     return obj_list
14  docs/db-api.txt
@@ -1891,8 +1891,8 @@ get_object_or_404()
1891 1891
 One common idiom to use ``get()`` and raise ``Http404`` if the
1892 1892
 object doesn't exist. This idiom is captured by ``get_object_or_404()``.
1893 1893
 This function takes a Django model as its first argument and an
1894  
-arbitrary number of keyword arguments, which it passes to the manager's
1895  
-``get()`` function. It raises ``Http404`` if the object doesn't
  1894
+arbitrary number of keyword arguments, which it passes to the default
  1895
+manager's ``get()`` function. It raises ``Http404`` if the object doesn't
1896 1896
 exist. For example::
1897 1897
 
1898 1898
     # Get the Entry with a primary key of 3
@@ -1901,7 +1901,7 @@ exist. For example::
1901 1901
 When you provide a model to this shortcut function, the default manager
1902 1902
 is used to execute the underlying ``get()`` query. If you don't want to
1903 1903
 use the default manager, or if you want to search a list of related objects,
1904  
-you can provide ``get_object_or_404()`` with a manager object instead.
  1904
+you can provide ``get_object_or_404()`` with a ``Manager`` object instead.
1905 1905
 For example::
1906 1906
 
1907 1907
     # Get the author of blog instance e with a name of 'Fred'
@@ -1911,6 +1911,14 @@ For example::
1911 1911
     # entry with a primary key of 3
1912 1912
     e = get_object_or_404(Entry.recent_entries, pk=3)
1913 1913
 
  1914
+If you need to use a custom method that you added to a custom manager,
  1915
+then you can provide ``get_object_or_404()`` with a ``QuerySet`` object.
  1916
+For example::
  1917
+
  1918
+    # Use a QuerySet returned from a 'published' method of a custom manager
  1919
+    # in the search for an entry with primary key of 5
  1920
+    e = get_object_or_404(Entry.objects.published(), pk=5)
  1921
+
1914 1922
 get_list_or_404()
1915 1923
 -----------------
1916 1924
 
27  tests/modeltests/get_object_or_404/models.py
@@ -3,11 +3,11 @@
3 3
 
4 4
 get_object_or_404 is a shortcut function to be used in view functions for
5 5
 performing a get() lookup and raising a Http404 exception if a DoesNotExist
6  
-exception was rasied during the get() call.
  6
+exception was raised during the get() call.
7 7
 
8 8
 get_list_or_404 is a shortcut function to be used in view functions for
9 9
 performing a filter() lookup and raising a Http404 exception if a DoesNotExist
10  
-exception was rasied during the filter() call.
  10
+exception was raised during the filter() call.
11 11
 """
12 12
 
13 13
 from django.db import models
@@ -69,11 +69,28 @@ def __unicode__(self):
69 69
 >>> get_object_or_404(Article.by_a_sir, title="Run away!")
70 70
 <Article: Run away!>
71 71
 
  72
+# QuerySets can be used too.
  73
+>>> get_object_or_404(Article.objects.all(), title__contains="Run")
  74
+<Article: Run away!>
  75
+
  76
+# Just as when using a get() lookup, you will get an error if more than one
  77
+# object is returned.
  78
+>>> get_object_or_404(Author.objects.all())
  79
+Traceback (most recent call last):
  80
+...
  81
+AssertionError: get() returned more than one Author -- it returned ...! Lookup parameters were {}
  82
+
  83
+# Using an EmptyQuerySet raises a Http404 error.
  84
+>>> get_object_or_404(Article.objects.none(), title__contains="Run")
  85
+Traceback (most recent call last):
  86
+...
  87
+Http404: No Article matches the given query.
  88
+
72 89
 # get_list_or_404 can be used to get lists of objects
73 90
 >>> get_list_or_404(a.article_set, title__icontains='Run')
74 91
 [<Article: Run away!>]
75 92
 
76  
-# Http404 is returned if the list is empty
  93
+# Http404 is returned if the list is empty.
77 94
 >>> get_list_or_404(a.article_set, title__icontains='Shrubbery')
78 95
 Traceback (most recent call last):
79 96
 ...
@@ -83,4 +100,8 @@ def __unicode__(self):
83 100
 >>> get_list_or_404(Article.by_a_sir, title__icontains="Run")
84 101
 [<Article: Run away!>]
85 102
 
  103
+# QuerySets can be used too.
  104
+>>> get_list_or_404(Article.objects.all(), title__icontains="Run")
  105
+[<Article: Run away!>]
  106
+
86 107
 """}

0 notes on commit cae92ae

Please sign in to comment.
Something went wrong with that request. Please try again.