tutorial test orderingfilter modelviewset listapiview has framework filter_queryset example django_filters attribute python django rest permissions django-rest-framework

python - test - Marco Django REST-Permisos separados por métodos



listapiview (2)

Estoy escribiendo una API usando Django REST Framework y me pregunto si se pueden especificar permisos por método cuando se usan vistas basadas en clases.

Leer la documentación que veo es bastante fácil de hacer si está escribiendo vistas basadas en funciones, simplemente usando el decorador @permission_classes sobre la función de las vistas que quiere proteger con permisos. Sin embargo, no veo una manera de hacer lo mismo cuando uso APIView con la clase APIView , porque luego especifico los permisos para la clase completa con el atributo permission_classes , pero eso se aplicará a todos los métodos de clase ( get , post , put ...).

Entonces, ¿es posible tener las vistas API escritas con CBV y también especificar permisos diferentes para cada método de una clase de vista?


Los permisos se aplican a toda la clase de Vista, pero puede tener en cuenta aspectos de la solicitud (como el método, como GET o POST) en su decisión de autorización.

Consulte el IsAuthenticatedOrReadOnly integrado como ejemplo:

SAFE_METHODS = [''GET'', ''HEAD'', ''OPTIONS''] class IsAuthenticatedOrReadOnly(BasePermission): """ The request is authenticated as a user, or is a read-only request. """ def has_permission(self, request, view): if (request.method in SAFE_METHODS or request.user and request.user.is_authenticated()): return True return False


Me encontré con el mismo problema cuando uso CBV, ya que tengo lógica de permisos bastante compleja dependiendo del método de solicitud.

La solución que se me ocurrió fue usar la aplicación de terceros ''rest_condition'' listada en la parte inferior de esta página

http://www.django-rest-framework.org/api-guide/permissions

https://github.com/caxap/rest_condition

Solo dividí la lógica de flujo de permisos para que cada rama se ejecute, dependiendo del método de solicitud.

from rest_condition import And, Or, Not class MyClassBasedView(APIView): permission_classes = [Or(And(IsReadOnlyRequest, IsAllowedRetrieveThis, IsAllowedRetrieveThat), And(IsPostRequest, IsAllowedToCreateThis, ...), And(IsPutPatchRequest, ...), And(IsDeleteRequest, ...)]

Entonces, el ''O'' determina qué rama de los permisos debe ejecutarse según el método de solicitud y el ''Y'' ajusta los permisos relacionados con el método de solicitud aceptado, por lo que todos deben pasar para que se otorgue el permiso. También puede mezclar ''O'', ''Y'' y ''No'' dentro de cada flujo para crear permisos aún más complejos.

Las clases de permisos para ejecutar cada rama simplemente se ven así,

class IsReadyOnlyRequest(permissions.BasePermission): def has_permission(self, request, view): return request.method in permissions.SAFE_METHODS class IsPostRequest(permissions.BasePermission): def has_permission(self, request, view): return request.method == "POST" ... #You get the idea