middleware.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. from __future__ import unicode_literals
  2. import sys
  3. from django.conf import settings
  4. from django.db import ProgrammingError
  5. from django.http import Http404, HttpResponseRedirect
  6. from django.shortcuts import render
  7. from django.urls import reverse
  8. BASE_PATH = getattr(settings, 'BASE_PATH', False)
  9. LOGIN_REQUIRED = getattr(settings, 'LOGIN_REQUIRED', False)
  10. class LoginRequiredMiddleware(object):
  11. """
  12. If LOGIN_REQUIRED is True, redirect all non-authenticated users to the login page.
  13. """
  14. def __init__(self, get_response):
  15. self.get_response = get_response
  16. def __call__(self, request):
  17. if LOGIN_REQUIRED and not request.user.is_authenticated():
  18. # Redirect unauthenticated requests to the login page. API requests are exempt from redirection as the API
  19. # performs its own authentication.
  20. api_path = reverse('api-root')
  21. if not request.path_info.startswith(api_path) and request.path_info != settings.LOGIN_URL:
  22. return HttpResponseRedirect('{}?next={}'.format(settings.LOGIN_URL, request.path_info))
  23. return self.get_response(request)
  24. class APIVersionMiddleware(object):
  25. """
  26. If the request is for an API endpoint, include the API version as a response header.
  27. """
  28. def __init__(self, get_response):
  29. self.get_response = get_response
  30. def __call__(self, request):
  31. api_path = reverse('api-root')
  32. response = self.get_response(request)
  33. if request.path_info.startswith(api_path):
  34. response['API-Version'] = settings.REST_FRAMEWORK_VERSION
  35. return response
  36. class ExceptionHandlingMiddleware(object):
  37. """
  38. Intercept certain exceptions which are likely indicative of installation issues and provide helpful instructions
  39. to the user.
  40. """
  41. def __init__(self, get_response):
  42. self.get_response = get_response
  43. def __call__(self, request):
  44. return self.get_response(request)
  45. def process_exception(self, request, exception):
  46. # Don't catch exceptions when in debug mode
  47. if settings.DEBUG:
  48. return
  49. # Ignore Http404s (defer to Django's built-in 404 handling)
  50. if isinstance(exception, Http404):
  51. return
  52. # Determine the type of exception
  53. if isinstance(exception, ProgrammingError):
  54. template_name = 'exceptions/programming_error.html'
  55. elif isinstance(exception, ImportError):
  56. template_name = 'exceptions/import_error.html'
  57. elif (
  58. sys.version_info[0] >= 3 and isinstance(exception, PermissionError)
  59. ) or (
  60. isinstance(exception, OSError) and exception.errno == 13
  61. ):
  62. template_name = 'exceptions/permission_error.html'
  63. else:
  64. template_name = '500.html'
  65. # Return an error message
  66. type_, error, traceback = sys.exc_info()
  67. return render(request, template_name, {
  68. 'exception': str(type_),
  69. 'error': error,
  70. }, status=500)