Сделать PermissionRequiredMixin также проверяющим разрешение на уровне объекта
Я использую Django Guardian
, чтобы иметь разрешения на уровне объекта наряду с глобальными разрешениями. Некоторые из пользователей имеют группу с глобальными разрешениями, а некоторые имеют разрешения на уровне объекта. В связи с этим, мне кажется, что нужно изменить PermissionRequiredMixin
, чтобы проверить также разрешение на уровне объекта.
views.py
class MainPageView(PermissionRequiredMixin, TemplateView):
permission_required = "app.view_mainpage"
template_name = "web/mainpage.html"
Этот вариант работает, если пользователь имеет глобальные права, но если пользователь находится под группой с правами объектного уровня, то он не сработает. В guardian, чтобы проверить разрешение на уровне объекта, необходимо также передать экземпляр объекта.
пример:
self.request.user.has_perm('view_mainpage', obj)
На PermissionRequiredMixin
проверка проходит только так, self.request.user.has_perms(perms)
Итак, если у пользователя есть группа с разрешением view_mainpage
определенного объекта, как я могу проверить и его? Кстати, все мои разрешения имеют одинаковое значение content_type
. Могу ли я каким-либо образом выполнить это? Например, я должен передать экземпляр объекта в PermissionRequiredMixin
, если пользователь находится под группой объектного уровня, и None
, если пользователь находится под глобальной группой.
Вы можете реализовать такой миксин самостоятельно с помощью:
from django.core.exceptions import PermissionDenied
class ObjectPermissionRequiredMixin:
object_permission_required = None
object_permission_denied_message = None
def has_object_permission(self, obj):
return self.request.user.has_perm(self.object_permission_required, obj)
def get_object_permission_denied_message(self):
return self.object_permission_denied_message
def handle_no_object_permission(self):
raise PermissionDenied(self.get_object_permission_denied_message())
def get_object(self, *args, **kwargs):
obj = super().get_object(*args, **kwargs)
if not self.has_object_permission(obj)
return self.handle_no_object_permission()
return obj
Затем вы можете подмешать этот миксин в представление, например:
class MyUpdateView(ObjectPermissionRequiredMixin, UpdateView):
model = MyModel
object_permission_required = 'app.update_my_model'
object_permission_denied_message = 'You can not edit this object'
Это будет работать для всех View
, которые используют SingleObjectMixin
[Django-doc], таких как DetailView
, UpdateView
и DeleteView
.