2
This module collects helper functions and classes that "span" multiple levels
3
of MVC. In other words, these functions/classes introduce controlled coupling
4
for convenience's sake.
6
from django.template import loader, RequestContext
7
from django.http import HttpResponse, Http404
8
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
9
from django.db.models.base import ModelBase
10
from django.db.models.manager import Manager
11
from django.db.models.query import QuerySet
12
from django.core import urlresolvers
13
from django.utils import six
16
def render_to_response(*args, **kwargs):
18
Returns a HttpResponse whose content is filled with the result of calling
19
django.template.loader.render_to_string() with the passed arguments.
21
httpresponse_kwargs = {'content_type': kwargs.pop('content_type', None)}
23
return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
26
def render(request, *args, **kwargs):
28
Returns a HttpResponse whose content is filled with the result of calling
29
django.template.loader.render_to_string() with the passed arguments.
30
Uses a RequestContext by default.
32
httpresponse_kwargs = {
33
'content_type': kwargs.pop('content_type', None),
34
'status': kwargs.pop('status', None),
37
if 'context_instance' in kwargs:
38
context_instance = kwargs.pop('context_instance')
39
if kwargs.get('current_app', None):
40
raise ValueError('If you provide a context_instance you must '
41
'set its current_app before calling render()')
43
current_app = kwargs.pop('current_app', None)
44
context_instance = RequestContext(request, current_app=current_app)
46
kwargs['context_instance'] = context_instance
48
return HttpResponse(loader.render_to_string(*args, **kwargs),
49
**httpresponse_kwargs)
52
def redirect(to, *args, **kwargs):
54
Returns an HttpResponseRedirect to the appropriate URL for the arguments
57
The arguments could be:
59
* A model: the model's `get_absolute_url()` function will be called.
61
* A view name, possibly with arguments: `urlresolvers.reverse()` will
62
be used to reverse-resolve the name.
64
* A URL, which will be used as-is for the redirect location.
66
By default issues a temporary redirect; pass permanent=True to issue a
69
if kwargs.pop('permanent', False):
70
redirect_class = HttpResponsePermanentRedirect
72
redirect_class = HttpResponseRedirect
74
return redirect_class(resolve_url(to, *args, **kwargs))
77
def _get_queryset(klass):
79
Returns a QuerySet from a Model, Manager, or QuerySet. Created to make
80
get_object_or_404 and get_list_or_404 more DRY.
82
Raises a ValueError if klass is not a Model, Manager, or QuerySet.
84
if isinstance(klass, QuerySet):
86
elif isinstance(klass, Manager):
88
elif isinstance(klass, ModelBase):
89
manager = klass._default_manager
91
if isinstance(klass, type):
92
klass__name = klass.__name__
94
klass__name = klass.__class__.__name__
95
raise ValueError("Object is of type '%s', but must be a Django Model, "
96
"Manager, or QuerySet" % klass__name)
100
def get_object_or_404(klass, *args, **kwargs):
102
Uses get() to return an object, or raises a Http404 exception if the object
105
klass may be a Model, Manager, or QuerySet object. All other passed
106
arguments and keyword arguments are used in the get() query.
108
Note: Like with get(), an MultipleObjectsReturned will be raised if more than one
111
queryset = _get_queryset(klass)
113
return queryset.get(*args, **kwargs)
114
except queryset.model.DoesNotExist:
115
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
118
def get_list_or_404(klass, *args, **kwargs):
120
Uses filter() to return a list of objects, or raise a Http404 exception if
123
klass may be a Model, Manager, or QuerySet object. All other passed
124
arguments and keyword arguments are used in the filter() query.
126
queryset = _get_queryset(klass)
127
obj_list = list(queryset.filter(*args, **kwargs))
129
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
133
def resolve_url(to, *args, **kwargs):
135
Return a URL appropriate for the arguments passed.
137
The arguments could be:
139
* A model: the model's `get_absolute_url()` function will be called.
141
* A view name, possibly with arguments: `urlresolvers.reverse()` will
142
be used to reverse-resolve the name.
144
* A URL, which will be returned as-is.
147
# If it's a model, use get_absolute_url()
148
if hasattr(to, 'get_absolute_url'):
149
return to.get_absolute_url()
151
if isinstance(to, six.string_types):
152
# Handle relative URLs
153
if any(to.startswith(path) for path in ('./', '../')):
156
# Next try a reverse URL resolution.
158
return urlresolvers.reverse(to, args=args, kwargs=kwargs)
159
except urlresolvers.NoReverseMatch:
160
# If this is a callable, re-raise.
163
# If this doesn't "feel" like a URL, re-raise.
164
if '/' not in to and '.' not in to:
167
# Finally, fall back and assume it's a URL