You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mixins.py 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. from django.conf import settings
  2. from django.contrib.auth import REDIRECT_FIELD_NAME
  3. from django.contrib.auth.views import redirect_to_login
  4. from django.core.exceptions import ImproperlyConfigured, PermissionDenied
  5. class AccessMixin:
  6. """
  7. Abstract CBV mixin that gives access mixins the same customizable
  8. functionality.
  9. """
  10. login_url = None
  11. permission_denied_message = ''
  12. raise_exception = False
  13. redirect_field_name = REDIRECT_FIELD_NAME
  14. def get_login_url(self):
  15. """
  16. Override this method to override the login_url attribute.
  17. """
  18. login_url = self.login_url or settings.LOGIN_URL
  19. if not login_url:
  20. raise ImproperlyConfigured(
  21. '{0} is missing the login_url attribute. Define {0}.login_url, settings.LOGIN_URL, or override '
  22. '{0}.get_login_url().'.format(self.__class__.__name__)
  23. )
  24. return str(login_url)
  25. def get_permission_denied_message(self):
  26. """
  27. Override this method to override the permission_denied_message attribute.
  28. """
  29. return self.permission_denied_message
  30. def get_redirect_field_name(self):
  31. """
  32. Override this method to override the redirect_field_name attribute.
  33. """
  34. return self.redirect_field_name
  35. def handle_no_permission(self):
  36. if self.raise_exception or self.request.user.is_authenticated:
  37. raise PermissionDenied(self.get_permission_denied_message())
  38. return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
  39. class LoginRequiredMixin(AccessMixin):
  40. """Verify that the current user is authenticated."""
  41. def dispatch(self, request, *args, **kwargs):
  42. if not request.user.is_authenticated:
  43. return self.handle_no_permission()
  44. return super().dispatch(request, *args, **kwargs)
  45. class PermissionRequiredMixin(AccessMixin):
  46. """Verify that the current user has all specified permissions."""
  47. permission_required = None
  48. def get_permission_required(self):
  49. """
  50. Override this method to override the permission_required attribute.
  51. Must return an iterable.
  52. """
  53. if self.permission_required is None:
  54. raise ImproperlyConfigured(
  55. '{0} is missing the permission_required attribute. Define {0}.permission_required, or override '
  56. '{0}.get_permission_required().'.format(self.__class__.__name__)
  57. )
  58. if isinstance(self.permission_required, str):
  59. perms = (self.permission_required,)
  60. else:
  61. perms = self.permission_required
  62. return perms
  63. def has_permission(self):
  64. """
  65. Override this method to customize the way permissions are checked.
  66. """
  67. perms = self.get_permission_required()
  68. return self.request.user.has_perms(perms)
  69. def dispatch(self, request, *args, **kwargs):
  70. if not self.has_permission():
  71. return self.handle_no_permission()
  72. return super().dispatch(request, *args, **kwargs)
  73. class UserPassesTestMixin(AccessMixin):
  74. """
  75. Deny a request with a permission error if the test_func() method returns
  76. False.
  77. """
  78. def test_func(self):
  79. raise NotImplementedError(
  80. '{0} is missing the implementation of the test_func() method.'.format(self.__class__.__name__)
  81. )
  82. def get_test_func(self):
  83. """
  84. Override this method to use a different test_func method.
  85. """
  86. return self.test_func
  87. def dispatch(self, request, *args, **kwargs):
  88. user_test_result = self.get_test_func()()
  89. if not user_test_result:
  90. return self.handle_no_permission()
  91. return super().dispatch(request, *args, **kwargs)