defaults.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from django import http
  2. from django.template import Context, Engine, TemplateDoesNotExist, loader
  3. from django.utils import six
  4. from django.utils.encoding import force_text
  5. from django.views.decorators.csrf import requires_csrf_token
  6. ERROR_404_TEMPLATE_NAME = '404.html'
  7. ERROR_403_TEMPLATE_NAME = '403.html'
  8. ERROR_400_TEMPLATE_NAME = '400.html'
  9. ERROR_500_TEMPLATE_NAME = '500.html'
  10. # This can be called when CsrfViewMiddleware.process_view has not run,
  11. # therefore need @requires_csrf_token in case the template needs
  12. # {% csrf_token %}.
  13. @requires_csrf_token
  14. def page_not_found(request, exception, template_name=ERROR_404_TEMPLATE_NAME):
  15. """
  16. Default 404 handler.
  17. Templates: :template:`404.html`
  18. Context:
  19. request_path
  20. The path of the requested URL (e.g., '/app/pages/bad_page/')
  21. exception
  22. The message from the exception which triggered the 404 (if one was
  23. supplied), or the exception class name
  24. """
  25. exception_repr = exception.__class__.__name__
  26. # Try to get an "interesting" exception message, if any (and not the ugly
  27. # Resolver404 dictionary)
  28. try:
  29. message = exception.args[0]
  30. except (AttributeError, IndexError):
  31. pass
  32. else:
  33. if isinstance(message, six.text_type):
  34. exception_repr = message
  35. context = {
  36. 'request_path': request.path,
  37. 'exception': exception_repr,
  38. }
  39. try:
  40. template = loader.get_template(template_name)
  41. body = template.render(context, request)
  42. content_type = None # Django will use DEFAULT_CONTENT_TYPE
  43. except TemplateDoesNotExist:
  44. if template_name != ERROR_404_TEMPLATE_NAME:
  45. # Reraise if it's a missing custom template.
  46. raise
  47. template = Engine().from_string(
  48. '<h1>Not Found</h1>'
  49. '<p>The requested URL {{ request_path }} was not found on this server.</p>')
  50. body = template.render(Context(context))
  51. content_type = 'text/html'
  52. return http.HttpResponseNotFound(body, content_type=content_type)
  53. @requires_csrf_token
  54. def server_error(request, template_name=ERROR_500_TEMPLATE_NAME):
  55. """
  56. 500 error handler.
  57. Templates: :template:`500.html`
  58. Context: None
  59. """
  60. try:
  61. template = loader.get_template(template_name)
  62. except TemplateDoesNotExist:
  63. if template_name != ERROR_500_TEMPLATE_NAME:
  64. # Reraise if it's a missing custom template.
  65. raise
  66. return http.HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
  67. return http.HttpResponseServerError(template.render())
  68. @requires_csrf_token
  69. def bad_request(request, exception, template_name=ERROR_400_TEMPLATE_NAME):
  70. """
  71. 400 error handler.
  72. Templates: :template:`400.html`
  73. Context: None
  74. """
  75. try:
  76. template = loader.get_template(template_name)
  77. except TemplateDoesNotExist:
  78. if template_name != ERROR_400_TEMPLATE_NAME:
  79. # Reraise if it's a missing custom template.
  80. raise
  81. return http.HttpResponseBadRequest('<h1>Bad Request (400)</h1>', content_type='text/html')
  82. # No exception content is passed to the template, to not disclose any sensitive information.
  83. return http.HttpResponseBadRequest(template.render())
  84. # This can be called when CsrfViewMiddleware.process_view has not run,
  85. # therefore need @requires_csrf_token in case the template needs
  86. # {% csrf_token %}.
  87. @requires_csrf_token
  88. def permission_denied(request, exception, template_name=ERROR_403_TEMPLATE_NAME):
  89. """
  90. Permission denied (403) handler.
  91. Templates: :template:`403.html`
  92. Context: None
  93. If the template does not exist, an Http403 response containing the text
  94. "403 Forbidden" (as per RFC 7231) will be returned.
  95. """
  96. try:
  97. template = loader.get_template(template_name)
  98. except TemplateDoesNotExist:
  99. if template_name != ERROR_403_TEMPLATE_NAME:
  100. # Reraise if it's a missing custom template.
  101. raise
  102. return http.HttpResponseForbidden('<h1>403 Forbidden</h1>', content_type='text/html')
  103. return http.HttpResponseForbidden(
  104. template.render(request=request, context={'exception': force_text(exception)})
  105. )