views.py 12 KB

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