Skip to content

Instantly share code, notes, and snippets.

@ivlevdenis
Last active November 24, 2019 20:20
Show Gist options
  • Save ivlevdenis/a0c8f5b472b6b8550bbb016c6a30e0be to your computer and use it in GitHub Desktop.
Save ivlevdenis/a0c8f5b472b6b8550bbb016c6a30e0be to your computer and use it in GitHub Desktop.
from rest_framework import viewsets
from rest_framework.response import Response
# https://gist.github.com/ivlevdenis/a0c8f5b472b6b8550bbb016c6a30e0be
class ExtendViewSet(object):
"""
This viewset mixin class with extended options list.
"""
permission_map = {}
throttle_scope_map = {}
serializer_class_map = {}
def get_serializer_class(self):
ser = self.serializer_class_map.get(self.action, None)
self.serializer_class = ser or self.serializer_class
return super().get_serializer_class()
def initialize_request(self, request, *args, **kwargs):
request = super().initialize_request(request, *args, **kwargs)
throttle_scope = self.throttle_scope_map.get(self.action, None)
cls_throttle_scope = getattr(self, 'throttle_scope', None)
self.throttle_scope = throttle_scope or cls_throttle_scope or ''
return request
def get_permissions(self):
perms = self.permission_map.get(self.action, None)
if perms and not isinstance(perms, (tuple, list)):
perms = [perms, ]
self.permission_classes = perms or self.permission_classes
return super().get_permissions()
def options(self, request, *args, **kwargs):
if self.metadata_class is None:
return self.http_method_not_allowed(request, *args, **kwargs)
data = self.metadata_class().determine_metadata(request, self)
data['actions']['GET'] = self.query_metadata
return Response(data, status=status.HTTP_200_OK)
class ExtendedModelViewSet(ExtendViewSet, viewsets.ModelViewSet):
"""
Examples:
class MyModelViewSet(ExtendedModelViewSet):
serializer_class_map = {
'list': ListMyModelSerializer,
'retrieve': RetrieveMyModelSerializer,
'update': UpdateMyModelSerializer,
...
}
"""
pass
@dmwyatt
Copy link

dmwyatt commented Nov 17, 2018

I find it easy to accidentally type the wrong action name into one of the mappings.

For example, I might type "delete" instead of "destroy" in the permission_map. If you do this, then you've just silently opened your HTTP DELETE to everyone.

I added some checks for valid actions (including custom actions) in my fork of this gist.

@ivlevdenis
Copy link
Author

@dmwyatt thnx. First time check i'm find many calls of self.get_all_action_names() in one context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment