Saltar al contenido

Django rest framework allow_classes del método ViewSet

Esta es la contestación más exacta que te podemos compartir, pero primero obsérvala pausadamente y analiza si se puede adaptar a tu trabajo.

Solución:

Creo que no hay una solución incorporada para eso. Pero puede lograr esto anulando el get_permissions método:

from rest_framework.permissions import AllowAny, IsAdminUser

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    permission_classes_by_action = 'create': [AllowAny],
                                    'list': [IsAdminUser]

    def create(self, request, *args, **kwargs):
        return super(UserViewSet, self).create(request, *args, **kwargs)

    def list(self, request, *args, **kwargs):
        return super(UserViewSet, self).list(request, *args, **kwargs)

    def get_permissions(self):
        try:
            # return permission_classes depending on `action` 
            return [permission() for permission in self.permission_classes_by_action[self.action]]
        except KeyError: 
            # action is not set return default permission_classes
            return [permission() for permission in self.permission_classes]

Creé una superclase que se deriva de la respuesta de @ ilse2005. En todas las vistas posteriores de django, puede heredar esto para lograr el control de permisos de nivel de acción.

class MixedPermissionModelViewSet(viewsets.ModelViewSet):
   '''
   Mixed permission base model allowing for action level
   permission control. Subclasses may define their permissions
   by creating a 'permission_classes_by_action' variable.

   Example:
   permission_classes_by_action = 'list': [AllowAny],
                                   'create': [IsAdminUser]
   '''

   permission_classes_by_action = 

   def get_permissions(self):
      try:
        # return permission_classes depending on `action`
        return [permission() for permission in self.permission_classes_by_action[self.action]]
      except KeyError:
        # action is not set return default permission_classes
        return [permission() for permission in self.permission_classes]

Creo que todas las demás respuestas son geniales, pero no deberíamos suprimir las acciones predeterminadas. permission_classes definido en sus decoradores directamente. Entonces,

from rest_framework import viewsets
from rest_framework import permissions

class BaseModelViewSet(viewsets.ModelViewSet):
    queryset = ''
    serializer_class = ''
    permission_classes = (permissions.AllowAny,)

    # Refer to https://stackoverflow.com/a/35987077/1677041
    permission_classes_by_action = 
        'create': permission_classes,
        'list': permission_classes,
        'retrieve': permission_classes,
        'update': permission_classes,
        'destroy': permission_classes,
    

    def get_permissions(self):
        try:
            return [permission() for permission in self.permission_classes_by_action[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)]

Ahora podríamos definir el permission_classes de estas dos maneras. Dado que definimos el valor global predeterminado permission_classes_by_action en la superclase, podríamos descartar esa definición para todas las acciones en la opción 2.

class EntityViewSet(BaseModelViewSet):
    """EntityViewSet"""
    queryset = Entity.objects.all()
    serializer_class = EntitySerializer
    permission_classes_by_action = 
        'create': (permissions.IsAdminUser,),
        'list': (permissions.IsAuthenticatedOrReadOnly,),
        'retrieve': (permissions.AllowAny,),
        'update': (permissions.AllowAny,),
        'destroy': (permissions.IsAdminUser,),
        'search': (permissions.IsAuthenticated,)  # <--- Option 1
    

    @action(detail=False, methods=['post'], permission_classes=(permissions.IsAuthenticated,))  # <--- Option 2
    def search(self, request, format=None):
        pass

Al final de la artículo puedes encontrar las interpretaciones de otros gestores de proyectos, tú igualmente puedes dejar el tuyo si dominas el tema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *