views.py 10.7 KB
Newer Older
1
from xml.dom.minidom import parseString
2

3
from django.contrib.auth.decorators import login_required, permission_required
4
from django.core import mail
5
from django.forms import fields
6
from django.forms.forms import Form, ValidationError
7
from django.forms.formsets import BaseFormSet, formset_factory
8
from django.http import (
9 10
    HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed,
    HttpResponseNotFound, HttpResponseRedirect,
11
)
12
from django.shortcuts import render
13
from django.template import Context, Template
14
from django.test import Client
15
from django.utils.decorators import method_decorator
16
from django.utils.six.moves.urllib.parse import urlencode
17

Jason Myers's avatar
Jason Myers committed
18

19 20 21
def get_view(request):
    "A simple view that expects a GET request, and returns a rendered template"
    t = Template('This is a test. {{ var }} is the value.', name='GET Template')
22
    c = Context({'var': request.GET.get('var', 42)})
23

24 25
    return HttpResponse(t.render(c))

Jason Myers's avatar
Jason Myers committed
26

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
def trace_view(request):
    """
    A simple view that expects a TRACE request and echoes its status line.

    TRACE requests should not have an entity; the view will return a 400 status
    response if it is present.
    """
    if request.method.upper() != "TRACE":
        return HttpResponseNotAllowed("TRACE")
    elif request.body:
        return HttpResponseBadRequest("TRACE requests MUST NOT include an entity")
    else:
        protocol = request.META["SERVER_PROTOCOL"]
        t = Template(
            '{{ method }} {{ uri }} {{ version }}',
            name="TRACE Template",
        )
        c = Context({
            'method': request.method,
            'uri': request.path,
            'version': protocol,
        })
        return HttpResponse(t.render(c))


52 53 54 55
def post_view(request):
    """A view that expects a POST, and returns a different template depending
    on whether any POST data is available
    """
56 57 58 59 60 61 62
    if request.method == 'POST':
        if request.POST:
            t = Template('Data received: {{ data }} is the value.', name='POST Template')
            c = Context({'data': request.POST['value']})
        else:
            t = Template('Viewing POST page.', name='Empty POST Template')
            c = Context()
63
    else:
64
        t = Template('Viewing GET page.', name='Empty GET Template')
65
        c = Context()
66

67
    return HttpResponse(t.render(c))
68

Jason Myers's avatar
Jason Myers committed
69

70 71 72 73 74
def view_with_header(request):
    "A view that has a custom header"
    response = HttpResponse()
    response['X-DJANGO-TEST'] = 'Slartibartfast'
    return response
75

Jason Myers's avatar
Jason Myers committed
76

77 78 79 80
def raw_post_view(request):
    """A view which expects raw XML to be posted and returns content extracted
    from the XML"""
    if request.method == 'POST':
81
        root = parseString(request.body)
82 83 84 85 86 87 88 89 90 91
        first_book = root.firstChild.firstChild
        title, author = [n.firstChild.nodeValue for n in first_book.childNodes]
        t = Template("{{ title }} - {{ author }}", name="Book template")
        c = Context({"title": title, "author": author})
    else:
        t = Template("GET request.", name="Book GET template")
        c = Context()

    return HttpResponse(t.render(c))

Jason Myers's avatar
Jason Myers committed
92

93 94
def redirect_view(request):
    "A view that redirects all requests to the GET view"
95 96 97 98
    if request.GET:
        query = '?' + urlencode(request.GET, True)
    else:
        query = ''
99
    return HttpResponseRedirect('/get_view/' + query)
100

Jason Myers's avatar
Jason Myers committed
101

102 103 104 105
def view_with_secure(request):
    "A view that indicates if the request was secure"
    response = HttpResponse()
    response.test_was_secure_request = request.is_secure()
106
    response.test_server_port = request.META.get('SERVER_PORT', 80)
107 108
    return response

Jason Myers's avatar
Jason Myers committed
109

110 111
def double_redirect_view(request):
    "A view that redirects all requests to a redirection view"
112
    return HttpResponseRedirect('/permanent_redirect_view/')
113

Jason Myers's avatar
Jason Myers committed
114

115 116 117 118
def bad_view(request):
    "A view that returns a 404 with some error content"
    return HttpResponseNotFound('Not found!. This page contains some MAGIC content')

119 120 121 122 123 124 125 126
TestChoices = (
    ('a', 'First Choice'),
    ('b', 'Second Choice'),
    ('c', 'Third Choice'),
    ('d', 'Fourth Choice'),
    ('e', 'Fifth Choice')
)

Jason Myers's avatar
Jason Myers committed
127

128 129 130 131 132 133
class TestForm(Form):
    text = fields.CharField()
    email = fields.EmailField()
    value = fields.IntegerField()
    single = fields.ChoiceField(choices=TestChoices)
    multi = fields.MultipleChoiceField(choices=TestChoices)
134

135 136 137 138 139 140
    def clean(self):
        cleaned_data = self.cleaned_data
        if cleaned_data.get("text") == "Raise non-field error":
            raise ValidationError("Non-field error.")
        return cleaned_data

Jason Myers's avatar
Jason Myers committed
141

142 143 144 145 146 147 148 149 150 151 152
def form_view(request):
    "A view that tests a simple form"
    if request.method == 'POST':
        form = TestForm(request.POST)
        if form.is_valid():
            t = Template('Valid POST data.', name='Valid POST Template')
            c = Context()
        else:
            t = Template('Invalid POST data. {{ form.errors }}', name='Invalid POST Template')
            c = Context({'form': form})
    else:
153
        form = TestForm(request.GET)
154 155
        t = Template('Viewing base form. {{ form }}.', name='Form GET Template')
        c = Context({'form': form})
156

157
    return HttpResponse(t.render(c))
158

Jason Myers's avatar
Jason Myers committed
159

160 161 162 163 164 165 166 167 168 169 170
def form_view_with_template(request):
    "A view that tests a simple form"
    if request.method == 'POST':
        form = TestForm(request.POST)
        if form.is_valid():
            message = 'POST data OK'
        else:
            message = 'POST data has errors'
    else:
        form = TestForm()
        message = 'GET form page'
171 172 173 174
    return render(request, 'form_view.html', {
        'form': form,
        'message': message,
    })
175

Jason Myers's avatar
Jason Myers committed
176

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
class BaseTestFormSet(BaseFormSet):
    def clean(self):
        """Checks that no two email addresses are the same."""
        if any(self.errors):
            # Don't bother validating the formset unless each form is valid
            return

        emails = []
        for i in range(0, self.total_form_count()):
            form = self.forms[i]
            email = form.cleaned_data['email']
            if email in emails:
                raise ValidationError(
                    "Forms in a set must have distinct email addresses."
                )
            emails.append(email)

TestFormSet = formset_factory(TestForm, BaseTestFormSet)

Jason Myers's avatar
Jason Myers committed
196

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
def formset_view(request):
    "A view that tests a simple formset"
    if request.method == 'POST':
        formset = TestFormSet(request.POST)
        if formset.is_valid():
            t = Template('Valid POST data.', name='Valid POST Template')
            c = Context()
        else:
            t = Template('Invalid POST data. {{ my_formset.errors }}',
                         name='Invalid POST Template')
            c = Context({'my_formset': formset})
    else:
        formset = TestForm(request.GET)
        t = Template('Viewing base formset. {{ my_formset }}.',
                     name='Formset GET Template')
        c = Context({'my_formset': formset})
    return HttpResponse(t.render(c))

Jason Myers's avatar
Jason Myers committed
215

216 217 218 219
def login_protected_view(request):
    "A simple view that is login protected."
    t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
    c = Context({'user': request.user})
220

221
    return HttpResponse(t.render(c))
222 223
login_protected_view = login_required(login_protected_view)

Jason Myers's avatar
Jason Myers committed
224

225 226 227 228
def login_protected_view_changed_redirect(request):
    "A simple view that is login protected with a custom redirect field set"
    t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
    c = Context({'user': request.user})
229

230
    return HttpResponse(t.render(c))
231 232 233
login_protected_view_changed_redirect = (
    login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect)
)
234

Jason Myers's avatar
Jason Myers committed
235

236
def _permission_protected_view(request):
237 238 239
    "A simple view that is permission protected."
    t = Template('This is a permission protected test. '
                 'Username is {{ user.username }}. '
240
                 'Permissions are {{ user.get_all_permissions }}.',
241 242 243
                 name='Permissions Template')
    c = Context({'user': request.user})
    return HttpResponse(t.render(c))
244
permission_protected_view = permission_required('permission_not_granted')(_permission_protected_view)
245 246 247
permission_protected_view_exception = (
    permission_required('permission_not_granted', raise_exception=True)(_permission_protected_view)
)
248

Jason Myers's avatar
Jason Myers committed
249

250
class _ViewManager(object):
251
    @method_decorator(login_required)
252 253 254 255 256 257 258
    def login_protected_view(self, request):
        t = Template('This is a login protected test using a method. '
                     'Username is {{ user.username }}.',
                     name='Login Method Template')
        c = Context({'user': request.user})
        return HttpResponse(t.render(c))

259
    @method_decorator(permission_required('permission_not_granted'))
260 261 262
    def permission_protected_view(self, request):
        t = Template('This is a permission protected test using a method. '
                     'Username is {{ user.username }}. '
263
                     'Permissions are {{ user.get_all_permissions }}.',
264 265 266 267 268 269 270 271
                     name='Permissions Template')
        c = Context({'user': request.user})
        return HttpResponse(t.render(c))

_view_manager = _ViewManager()
login_protected_method_view = _view_manager.login_protected_view
permission_protected_method_view = _view_manager.permission_protected_view

Jason Myers's avatar
Jason Myers committed
272

273 274 275
def session_view(request):
    "A view that modifies the session"
    request.session['tobacconist'] = 'hovercraft'
276 277

    t = Template('This is a view that modifies the session.',
278 279 280
                 name='Session Modifying View Template')
    c = Context()
    return HttpResponse(t.render(c))
281

Jason Myers's avatar
Jason Myers committed
282

283 284 285
def broken_view(request):
    """A view which just raises an exception, simulating a broken view."""
    raise KeyError("Oops! Looks like you wrote some bad code.")
286

Jason Myers's avatar
Jason Myers committed
287

288
def mail_sending_view(request):
289
    mail.EmailMessage(
290 291 292
        "Test message",
        "This is a test email",
        "from@example.com",
293 294 295
        ['first@example.com', 'second@example.com']).send()
    return HttpResponse("Mail sent")

Jason Myers's avatar
Jason Myers committed
296

297
def mass_mail_sending_view(request):
298
    m1 = mail.EmailMessage(
299 300 301
        'First Test message',
        'This is the first test email',
        'from@example.com',
302
        ['first@example.com', 'second@example.com'])
303
    m2 = mail.EmailMessage(
304 305 306
        'Second Test message',
        'This is the second test email',
        'from@example.com',
307
        ['second@example.com', 'third@example.com'])
308

309
    c = mail.get_connection()
Alex Gaynor's avatar
Alex Gaynor committed
310
    c.send_messages([m1, m2])
311

312
    return HttpResponse("Mail sent")
313

Jason Myers's avatar
Jason Myers committed
314

315 316 317 318 319 320 321 322 323 324
def nesting_exception_view(request):
    """
    A view that uses a nested client to call another view and then raises an
    exception.
    """
    client = Client()
    client.get('/get_view/')
    raise Exception('exception message')


325 326
def django_project_redirect(request):
    return HttpResponseRedirect('https://www.djangoproject.com/')