3
3
of MVC. In other words, these functions/classes introduce controlled coupling
4
4
for convenience's sake.
5
5
"""
6
- from django .db .models .base import ModelBase
7
- from django .db .models .manager import Manager
8
- from django .db .models .query import QuerySet
9
6
from django .http import (
10
7
Http404 , HttpResponse , HttpResponsePermanentRedirect , HttpResponseRedirect ,
11
8
)
@@ -61,25 +58,15 @@ def redirect(to, *args, **kwargs):
61
58
62
59
def _get_queryset (klass ):
63
60
"""
64
- Returns a QuerySet from a Model, Manager, or QuerySet. Created to make
65
- get_object_or_404 and get_list_or_404 more DRY.
66
-
67
- Raises a ValueError if klass is not a Model, Manager, or QuerySet .
61
+ Return a QuerySet or a Manager.
62
+ Duck typing in action: any class with a `get()` method (for
63
+ get_object_or_404) or a `filter()` method (for get_list_or_404) might do
64
+ the job .
68
65
"""
69
- if isinstance (klass , QuerySet ):
70
- return klass
71
- elif isinstance (klass , Manager ):
72
- manager = klass
73
- elif isinstance (klass , ModelBase ):
74
- manager = klass ._default_manager
75
- else :
76
- if isinstance (klass , type ):
77
- klass__name = klass .__name__
78
- else :
79
- klass__name = klass .__class__ .__name__
80
- raise ValueError ("Object is of type '%s', but must be a Django Model, "
81
- "Manager, or QuerySet" % klass__name )
82
- return manager .all ()
66
+ # If it is a model class or anything else with ._default_manager
67
+ if hasattr (klass , '_default_manager' ):
68
+ return klass ._default_manager .all ()
69
+ return klass
83
70
84
71
85
72
def get_object_or_404 (klass , * args , ** kwargs ):
@@ -96,6 +83,12 @@ def get_object_or_404(klass, *args, **kwargs):
96
83
queryset = _get_queryset (klass )
97
84
try :
98
85
return queryset .get (* args , ** kwargs )
86
+ except AttributeError :
87
+ klass__name = klass .__name__ if isinstance (klass , type ) else klass .__class__ .__name__
88
+ raise ValueError (
89
+ "First argument to get_object_or_404() must be a Model, Manager, "
90
+ "or QuerySet, not '%s'." % klass__name
91
+ )
99
92
except queryset .model .DoesNotExist :
100
93
raise Http404 ('No %s matches the given query.' % queryset .model ._meta .object_name )
101
94
@@ -109,7 +102,14 @@ def get_list_or_404(klass, *args, **kwargs):
109
102
arguments and keyword arguments are used in the filter() query.
110
103
"""
111
104
queryset = _get_queryset (klass )
112
- obj_list = list (queryset .filter (* args , ** kwargs ))
105
+ try :
106
+ obj_list = list (queryset .filter (* args , ** kwargs ))
107
+ except AttributeError :
108
+ klass__name = klass .__name__ if isinstance (klass , type ) else klass .__class__ .__name__
109
+ raise ValueError (
110
+ "First argument to get_list_or_404() must be a Model, Manager, or "
111
+ "QuerySet, not '%s'." % klass__name
112
+ )
113
113
if not obj_list :
114
114
raise Http404 ('No %s matches the given query.' % queryset .model ._meta .object_name )
115
115
return obj_list
0 commit comments