~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to django/shortcuts.py

  • Committer: Package Import Robot
  • Author(s): Raphaël Hertzog
  • Date: 2014-09-17 14:15:11 UTC
  • mfrom: (1.3.17) (6.2.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140917141511-icneokthe9ww5sk4
Tags: 1.7-2
* Release to unstable.
* Add a migrate-south sample script to help users apply their South
  migrations. Thanks to Brian May.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
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.
 
5
"""
 
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
 
14
 
 
15
 
 
16
def render_to_response(*args, **kwargs):
 
17
    """
 
18
    Returns a HttpResponse whose content is filled with the result of calling
 
19
    django.template.loader.render_to_string() with the passed arguments.
 
20
    """
 
21
    httpresponse_kwargs = {'content_type': kwargs.pop('content_type', None)}
 
22
 
 
23
    return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
 
24
 
 
25
 
 
26
def render(request, *args, **kwargs):
 
27
    """
 
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.
 
31
    """
 
32
    httpresponse_kwargs = {
 
33
        'content_type': kwargs.pop('content_type', None),
 
34
        'status': kwargs.pop('status', None),
 
35
    }
 
36
 
 
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()')
 
42
    else:
 
43
        current_app = kwargs.pop('current_app', None)
 
44
        context_instance = RequestContext(request, current_app=current_app)
 
45
 
 
46
    kwargs['context_instance'] = context_instance
 
47
 
 
48
    return HttpResponse(loader.render_to_string(*args, **kwargs),
 
49
                        **httpresponse_kwargs)
 
50
 
 
51
 
 
52
def redirect(to, *args, **kwargs):
 
53
    """
 
54
    Returns an HttpResponseRedirect to the appropriate URL for the arguments
 
55
    passed.
 
56
 
 
57
    The arguments could be:
 
58
 
 
59
        * A model: the model's `get_absolute_url()` function will be called.
 
60
 
 
61
        * A view name, possibly with arguments: `urlresolvers.reverse()` will
 
62
          be used to reverse-resolve the name.
 
63
 
 
64
        * A URL, which will be used as-is for the redirect location.
 
65
 
 
66
    By default issues a temporary redirect; pass permanent=True to issue a
 
67
    permanent redirect
 
68
    """
 
69
    if kwargs.pop('permanent', False):
 
70
        redirect_class = HttpResponsePermanentRedirect
 
71
    else:
 
72
        redirect_class = HttpResponseRedirect
 
73
 
 
74
    return redirect_class(resolve_url(to, *args, **kwargs))
 
75
 
 
76
 
 
77
def _get_queryset(klass):
 
78
    """
 
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.
 
81
 
 
82
    Raises a ValueError if klass is not a Model, Manager, or QuerySet.
 
83
    """
 
84
    if isinstance(klass, QuerySet):
 
85
        return klass
 
86
    elif isinstance(klass, Manager):
 
87
        manager = klass
 
88
    elif isinstance(klass, ModelBase):
 
89
        manager = klass._default_manager
 
90
    else:
 
91
        if isinstance(klass, type):
 
92
            klass__name = klass.__name__
 
93
        else:
 
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)
 
97
    return manager.all()
 
98
 
 
99
 
 
100
def get_object_or_404(klass, *args, **kwargs):
 
101
    """
 
102
    Uses get() to return an object, or raises a Http404 exception if the object
 
103
    does not exist.
 
104
 
 
105
    klass may be a Model, Manager, or QuerySet object. All other passed
 
106
    arguments and keyword arguments are used in the get() query.
 
107
 
 
108
    Note: Like with get(), an MultipleObjectsReturned will be raised if more than one
 
109
    object is found.
 
110
    """
 
111
    queryset = _get_queryset(klass)
 
112
    try:
 
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)
 
116
 
 
117
 
 
118
def get_list_or_404(klass, *args, **kwargs):
 
119
    """
 
120
    Uses filter() to return a list of objects, or raise a Http404 exception if
 
121
    the list is empty.
 
122
 
 
123
    klass may be a Model, Manager, or QuerySet object. All other passed
 
124
    arguments and keyword arguments are used in the filter() query.
 
125
    """
 
126
    queryset = _get_queryset(klass)
 
127
    obj_list = list(queryset.filter(*args, **kwargs))
 
128
    if not obj_list:
 
129
        raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
 
130
    return obj_list
 
131
 
 
132
 
 
133
def resolve_url(to, *args, **kwargs):
 
134
    """
 
135
    Return a URL appropriate for the arguments passed.
 
136
 
 
137
    The arguments could be:
 
138
 
 
139
        * A model: the model's `get_absolute_url()` function will be called.
 
140
 
 
141
        * A view name, possibly with arguments: `urlresolvers.reverse()` will
 
142
          be used to reverse-resolve the name.
 
143
 
 
144
        * A URL, which will be returned as-is.
 
145
 
 
146
    """
 
147
    # If it's a model, use get_absolute_url()
 
148
    if hasattr(to, 'get_absolute_url'):
 
149
        return to.get_absolute_url()
 
150
 
 
151
    if isinstance(to, six.string_types):
 
152
        # Handle relative URLs
 
153
        if any(to.startswith(path) for path in ('./', '../')):
 
154
            return to
 
155
 
 
156
    # Next try a reverse URL resolution.
 
157
    try:
 
158
        return urlresolvers.reverse(to, args=args, kwargs=kwargs)
 
159
    except urlresolvers.NoReverseMatch:
 
160
        # If this is a callable, re-raise.
 
161
        if callable(to):
 
162
            raise
 
163
        # If this doesn't "feel" like a URL, re-raise.
 
164
        if '/' not in to and '.' not in to:
 
165
            raise
 
166
 
 
167
    # Finally, fall back and assume it's a URL
 
168
    return to