views.py 13 KB

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