1. import json
    
  2. from urllib.parse import urlencode
    
  3. from xml.dom.minidom import parseString
    
  4. 
    
  5. from django.contrib.auth.decorators import login_required, permission_required
    
  6. from django.core import mail
    
  7. from django.core.exceptions import ValidationError
    
  8. from django.forms import fields
    
  9. from django.forms.forms import Form
    
  10. from django.http import (
    
  11.     HttpResponse,
    
  12.     HttpResponseBadRequest,
    
  13.     HttpResponseNotAllowed,
    
  14.     HttpResponseNotFound,
    
  15.     HttpResponseRedirect,
    
  16. )
    
  17. from django.shortcuts import render
    
  18. from django.template import Context, Template
    
  19. from django.test import Client
    
  20. from django.utils.decorators import method_decorator
    
  21. 
    
  22. 
    
  23. def get_view(request):
    
  24.     "A simple view that expects a GET request, and returns a rendered template"
    
  25.     t = Template("This is a test. {{ var }} is the value.", name="GET Template")
    
  26.     c = Context({"var": request.GET.get("var", 42)})
    
  27. 
    
  28.     return HttpResponse(t.render(c))
    
  29. 
    
  30. 
    
  31. async def async_get_view(request):
    
  32.     return HttpResponse(b"GET content.")
    
  33. 
    
  34. 
    
  35. def trace_view(request):
    
  36.     """
    
  37.     A simple view that expects a TRACE request and echoes its status line.
    
  38. 
    
  39.     TRACE requests should not have an entity; the view will return a 400 status
    
  40.     response if it is present.
    
  41.     """
    
  42.     if request.method.upper() != "TRACE":
    
  43.         return HttpResponseNotAllowed("TRACE")
    
  44.     elif request.body:
    
  45.         return HttpResponseBadRequest("TRACE requests MUST NOT include an entity")
    
  46.     else:
    
  47.         protocol = request.META["SERVER_PROTOCOL"]
    
  48.         t = Template(
    
  49.             "{{ method }} {{ uri }} {{ version }}",
    
  50.             name="TRACE Template",
    
  51.         )
    
  52.         c = Context(
    
  53.             {
    
  54.                 "method": request.method,
    
  55.                 "uri": request.path,
    
  56.                 "version": protocol,
    
  57.             }
    
  58.         )
    
  59.         return HttpResponse(t.render(c))
    
  60. 
    
  61. 
    
  62. def put_view(request):
    
  63.     if request.method == "PUT":
    
  64.         t = Template("Data received: {{ data }} is the body.", name="PUT Template")
    
  65.         c = Context(
    
  66.             {
    
  67.                 "Content-Length": request.META["CONTENT_LENGTH"],
    
  68.                 "data": request.body.decode(),
    
  69.             }
    
  70.         )
    
  71.     else:
    
  72.         t = Template("Viewing GET page.", name="Empty GET Template")
    
  73.         c = Context()
    
  74.     return HttpResponse(t.render(c))
    
  75. 
    
  76. 
    
  77. def post_view(request):
    
  78.     """A view that expects a POST, and returns a different template depending
    
  79.     on whether any POST data is available
    
  80.     """
    
  81.     if request.method == "POST":
    
  82.         if request.POST:
    
  83.             t = Template(
    
  84.                 "Data received: {{ data }} is the value.", name="POST Template"
    
  85.             )
    
  86.             c = Context({"data": request.POST["value"]})
    
  87.         else:
    
  88.             t = Template("Viewing POST page.", name="Empty POST Template")
    
  89.             c = Context()
    
  90.     else:
    
  91.         t = Template("Viewing GET page.", name="Empty GET Template")
    
  92.         c = Context()
    
  93.     return HttpResponse(t.render(c))
    
  94. 
    
  95. 
    
  96. def post_then_get_view(request):
    
  97.     """
    
  98.     A view that expects a POST request, returns a redirect response
    
  99.     to itself providing only a ?success=true querystring,
    
  100.     the value of this querystring is then rendered upon GET.
    
  101.     """
    
  102.     if request.method == "POST":
    
  103.         return HttpResponseRedirect("?success=true")
    
  104. 
    
  105.     t = Template("The value of success is {{ value }}.", name="GET Template")
    
  106.     c = Context({"value": request.GET.get("success", "false")})
    
  107. 
    
  108.     return HttpResponse(t.render(c))
    
  109. 
    
  110. 
    
  111. def json_view(request):
    
  112.     """
    
  113.     A view that expects a request with the header 'application/json' and JSON
    
  114.     data, which is deserialized and included in the context.
    
  115.     """
    
  116.     if request.META.get("CONTENT_TYPE") != "application/json":
    
  117.         return HttpResponse()
    
  118. 
    
  119.     t = Template("Viewing {} page. With data {{ data }}.".format(request.method))
    
  120.     data = json.loads(request.body.decode("utf-8"))
    
  121.     c = Context({"data": data})
    
  122.     return HttpResponse(t.render(c))
    
  123. 
    
  124. 
    
  125. def view_with_header(request):
    
  126.     "A view that has a custom header"
    
  127.     response = HttpResponse()
    
  128.     response.headers["X-DJANGO-TEST"] = "Slartibartfast"
    
  129.     return response
    
  130. 
    
  131. 
    
  132. def raw_post_view(request):
    
  133.     """A view which expects raw XML to be posted and returns content extracted
    
  134.     from the XML"""
    
  135.     if request.method == "POST":
    
  136.         root = parseString(request.body)
    
  137.         first_book = root.firstChild.firstChild
    
  138.         title, author = [n.firstChild.nodeValue for n in first_book.childNodes]
    
  139.         t = Template("{{ title }} - {{ author }}", name="Book template")
    
  140.         c = Context({"title": title, "author": author})
    
  141.     else:
    
  142.         t = Template("GET request.", name="Book GET template")
    
  143.         c = Context()
    
  144. 
    
  145.     return HttpResponse(t.render(c))
    
  146. 
    
  147. 
    
  148. def redirect_view(request):
    
  149.     "A view that redirects all requests to the GET view"
    
  150.     if request.GET:
    
  151.         query = "?" + urlencode(request.GET, True)
    
  152.     else:
    
  153.         query = ""
    
  154.     return HttpResponseRedirect("/get_view/" + query)
    
  155. 
    
  156. 
    
  157. def method_saving_307_redirect_query_string_view(request):
    
  158.     return HttpResponseRedirect("/post_view/?hello=world", status=307)
    
  159. 
    
  160. 
    
  161. def method_saving_308_redirect_query_string_view(request):
    
  162.     return HttpResponseRedirect("/post_view/?hello=world", status=308)
    
  163. 
    
  164. 
    
  165. def _post_view_redirect(request, status_code):
    
  166.     """Redirect to /post_view/ using the status code."""
    
  167.     redirect_to = request.GET.get("to", "/post_view/")
    
  168.     return HttpResponseRedirect(redirect_to, status=status_code)
    
  169. 
    
  170. 
    
  171. def method_saving_307_redirect_view(request):
    
  172.     return _post_view_redirect(request, 307)
    
  173. 
    
  174. 
    
  175. def method_saving_308_redirect_view(request):
    
  176.     return _post_view_redirect(request, 308)
    
  177. 
    
  178. 
    
  179. def view_with_secure(request):
    
  180.     "A view that indicates if the request was secure"
    
  181.     response = HttpResponse()
    
  182.     response.test_was_secure_request = request.is_secure()
    
  183.     response.test_server_port = request.META.get("SERVER_PORT", 80)
    
  184.     return response
    
  185. 
    
  186. 
    
  187. def double_redirect_view(request):
    
  188.     "A view that redirects all requests to a redirection view"
    
  189.     return HttpResponseRedirect("/permanent_redirect_view/")
    
  190. 
    
  191. 
    
  192. def bad_view(request):
    
  193.     "A view that returns a 404 with some error content"
    
  194.     return HttpResponseNotFound("Not found!. This page contains some MAGIC content")
    
  195. 
    
  196. 
    
  197. TestChoices = (
    
  198.     ("a", "First Choice"),
    
  199.     ("b", "Second Choice"),
    
  200.     ("c", "Third Choice"),
    
  201.     ("d", "Fourth Choice"),
    
  202.     ("e", "Fifth Choice"),
    
  203. )
    
  204. 
    
  205. 
    
  206. class TestForm(Form):
    
  207.     text = fields.CharField()
    
  208.     email = fields.EmailField()
    
  209.     value = fields.IntegerField()
    
  210.     single = fields.ChoiceField(choices=TestChoices)
    
  211.     multi = fields.MultipleChoiceField(choices=TestChoices)
    
  212. 
    
  213.     def clean(self):
    
  214.         cleaned_data = self.cleaned_data
    
  215.         if cleaned_data.get("text") == "Raise non-field error":
    
  216.             raise ValidationError("Non-field error.")
    
  217.         return cleaned_data
    
  218. 
    
  219. 
    
  220. def form_view(request):
    
  221.     "A view that tests a simple form"
    
  222.     if request.method == "POST":
    
  223.         form = TestForm(request.POST)
    
  224.         if form.is_valid():
    
  225.             t = Template("Valid POST data.", name="Valid POST Template")
    
  226.             c = Context()
    
  227.         else:
    
  228.             t = Template(
    
  229.                 "Invalid POST data. {{ form.errors }}", name="Invalid POST Template"
    
  230.             )
    
  231.             c = Context({"form": form})
    
  232.     else:
    
  233.         form = TestForm(request.GET)
    
  234.         t = Template("Viewing base form. {{ form }}.", name="Form GET Template")
    
  235.         c = Context({"form": form})
    
  236. 
    
  237.     return HttpResponse(t.render(c))
    
  238. 
    
  239. 
    
  240. def form_view_with_template(request):
    
  241.     "A view that tests a simple form"
    
  242.     if request.method == "POST":
    
  243.         form = TestForm(request.POST)
    
  244.         if form.is_valid():
    
  245.             message = "POST data OK"
    
  246.         else:
    
  247.             message = "POST data has errors"
    
  248.     else:
    
  249.         form = TestForm()
    
  250.         message = "GET form page"
    
  251.     return render(
    
  252.         request,
    
  253.         "form_view.html",
    
  254.         {
    
  255.             "form": form,
    
  256.             "message": message,
    
  257.         },
    
  258.     )
    
  259. 
    
  260. 
    
  261. @login_required
    
  262. def login_protected_view(request):
    
  263.     "A simple view that is login protected."
    
  264.     t = Template(
    
  265.         "This is a login protected test. Username is {{ user.username }}.",
    
  266.         name="Login Template",
    
  267.     )
    
  268.     c = Context({"user": request.user})
    
  269. 
    
  270.     return HttpResponse(t.render(c))
    
  271. 
    
  272. 
    
  273. @login_required(redirect_field_name="redirect_to")
    
  274. def login_protected_view_changed_redirect(request):
    
  275.     "A simple view that is login protected with a custom redirect field set"
    
  276.     t = Template(
    
  277.         "This is a login protected test. Username is {{ user.username }}.",
    
  278.         name="Login Template",
    
  279.     )
    
  280.     c = Context({"user": request.user})
    
  281.     return HttpResponse(t.render(c))
    
  282. 
    
  283. 
    
  284. def _permission_protected_view(request):
    
  285.     "A simple view that is permission protected."
    
  286.     t = Template(
    
  287.         "This is a permission protected test. "
    
  288.         "Username is {{ user.username }}. "
    
  289.         "Permissions are {{ user.get_all_permissions }}.",
    
  290.         name="Permissions Template",
    
  291.     )
    
  292.     c = Context({"user": request.user})
    
  293.     return HttpResponse(t.render(c))
    
  294. 
    
  295. 
    
  296. permission_protected_view = permission_required("permission_not_granted")(
    
  297.     _permission_protected_view
    
  298. )
    
  299. permission_protected_view_exception = permission_required(
    
  300.     "permission_not_granted", raise_exception=True
    
  301. )(_permission_protected_view)
    
  302. 
    
  303. 
    
  304. class _ViewManager:
    
  305.     @method_decorator(login_required)
    
  306.     def login_protected_view(self, request):
    
  307.         t = Template(
    
  308.             "This is a login protected test using a method. "
    
  309.             "Username is {{ user.username }}.",
    
  310.             name="Login Method Template",
    
  311.         )
    
  312.         c = Context({"user": request.user})
    
  313.         return HttpResponse(t.render(c))
    
  314. 
    
  315.     @method_decorator(permission_required("permission_not_granted"))
    
  316.     def permission_protected_view(self, request):
    
  317.         t = Template(
    
  318.             "This is a permission protected test using a method. "
    
  319.             "Username is {{ user.username }}. "
    
  320.             "Permissions are {{ user.get_all_permissions }}.",
    
  321.             name="Permissions Template",
    
  322.         )
    
  323.         c = Context({"user": request.user})
    
  324.         return HttpResponse(t.render(c))
    
  325. 
    
  326. 
    
  327. _view_manager = _ViewManager()
    
  328. login_protected_method_view = _view_manager.login_protected_view
    
  329. permission_protected_method_view = _view_manager.permission_protected_view
    
  330. 
    
  331. 
    
  332. def session_view(request):
    
  333.     "A view that modifies the session"
    
  334.     request.session["tobacconist"] = "hovercraft"
    
  335. 
    
  336.     t = Template(
    
  337.         "This is a view that modifies the session.",
    
  338.         name="Session Modifying View Template",
    
  339.     )
    
  340.     c = Context()
    
  341.     return HttpResponse(t.render(c))
    
  342. 
    
  343. 
    
  344. def broken_view(request):
    
  345.     """A view which just raises an exception, simulating a broken view."""
    
  346.     raise KeyError("Oops! Looks like you wrote some bad code.")
    
  347. 
    
  348. 
    
  349. def mail_sending_view(request):
    
  350.     mail.EmailMessage(
    
  351.         "Test message",
    
  352.         "This is a test email",
    
  353.         "[email protected]",
    
  354.         ["[email protected]", "[email protected]"],
    
  355.     ).send()
    
  356.     return HttpResponse("Mail sent")
    
  357. 
    
  358. 
    
  359. def mass_mail_sending_view(request):
    
  360.     m1 = mail.EmailMessage(
    
  361.         "First Test message",
    
  362.         "This is the first test email",
    
  363.         "[email protected]",
    
  364.         ["[email protected]", "[email protected]"],
    
  365.     )
    
  366.     m2 = mail.EmailMessage(
    
  367.         "Second Test message",
    
  368.         "This is the second test email",
    
  369.         "[email protected]",
    
  370.         ["[email protected]", "[email protected]"],
    
  371.     )
    
  372. 
    
  373.     c = mail.get_connection()
    
  374.     c.send_messages([m1, m2])
    
  375. 
    
  376.     return HttpResponse("Mail sent")
    
  377. 
    
  378. 
    
  379. def nesting_exception_view(request):
    
  380.     """
    
  381.     A view that uses a nested client to call another view and then raises an
    
  382.     exception.
    
  383.     """
    
  384.     client = Client()
    
  385.     client.get("/get_view/")
    
  386.     raise Exception("exception message")
    
  387. 
    
  388. 
    
  389. def django_project_redirect(request):
    
  390.     return HttpResponseRedirect("https://www.djangoproject.com/")
    
  391. 
    
  392. 
    
  393. def no_trailing_slash_external_redirect(request):
    
  394.     """
    
  395.     RFC 2616 3.2.2: A bare domain without any abs_path element should be
    
  396.     treated as having the trailing `/`.
    
  397. 
    
  398.     Use https://testserver, rather than an external domain, in order to allow
    
  399.     use of follow=True, triggering Client._handle_redirects().
    
  400.     """
    
  401.     return HttpResponseRedirect("https://testserver")
    
  402. 
    
  403. 
    
  404. def index_view(request):
    
  405.     """Target for no_trailing_slash_external_redirect with follow=True."""
    
  406.     return HttpResponse("Hello world")
    
  407. 
    
  408. 
    
  409. def upload_view(request):
    
  410.     """Prints keys of request.FILES to the response."""
    
  411.     return HttpResponse(", ".join(request.FILES))
    
  412. 
    
  413. 
    
  414. class TwoArgException(Exception):
    
  415.     def __init__(self, one, two):
    
  416.         pass
    
  417. 
    
  418. 
    
  419. def two_arg_exception(request):
    
  420.     raise TwoArgException("one", "two")