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