I\'m writing a rest API with the Django REST framework, and I\'d like to protect certain endpoints with permissions. The permission classes look like they provide an elegant
I'm probably late to answer this, but I used a mixin, as one of the commenters pointed out. Taking the answer from @Itachi, this is my mixin implementation:
class ViewSetActionPermissionMixin:
def get_permissions(self):
"""Return the permission classes based on action.
Look for permission classes in a dict mapping action to
permission classes array, ie.:
class MyViewSet(ViewSetActionPermissionMixin, ViewSet):
...
permission_classes = [AllowAny]
permission_action_classes = {
'list': [IsAuthenticated]
'create': [IsAdminUser]
'my_action': [MyCustomPermission]
}
@action(...)
def my_action:
...
If there is no action in the dict mapping, then the default
permission_classes is returned. If a custom action has its
permission_classes defined in the action decorator, then that
supercedes the value defined in the dict mapping.
"""
try:
return [
permission()
for permission in self.permission_action_classes[self.action]
]
except KeyError:
if self.action:
action_func = getattr(self, self.action, {})
action_func_kwargs = getattr(action_func, "kwargs", {})
permission_classes = action_func_kwargs.get(
"permission_classes"
)
else:
permission_classes = None
return [
permission()
for permission in (
permission_classes or self.permission_classes
)
]
And here's how to use the mixin:
class MyViewSet(ViewSetActionPermissionMixin, ModelViewSet):
...
permission_action_classes = {
"list": [AllowAny],
"create": [IsAdminUser],
"custom_action": [MyCustomPermission],
}
@action(...)
def custom_action(self, request, *args, **kwargs):
...