2013-11-04 4 views
24

Sto scrivendo un'API utilizzando Django REST Framework e mi chiedo se è possibile specificare le autorizzazioni per metodo quando si utilizzano le viste basate sulla classe.Django REST Framework - Autorizzazioni separate per metodi

Reading the documentation Vedo che è abbastanza facile da fare se si stanno scrivendo viste basate su funzioni, semplicemente usando il decoratore @permission_classes sulla funzione delle viste che si desidera proteggere con le autorizzazioni. Tuttavia, non vedo un modo per fare lo stesso quando utilizzo i CBV con la classe APIView, perché in questo caso specificherò le autorizzazioni per la classe completa con l'attributo permission_classes, ma verrà applicato a tutti i metodi di classe (get, post , put ...).

Quindi, è possibile avere le viste API scritte con CBV e anche specificare autorizzazioni diverse per ogni metodo di una classe di visualizzazione?

+0

Che ne dite di creare una vista separata per ciascuno di essi? Oppure potresti sovrascrivere i metodi get/post/put nella tua vista e scrivere le tue autorizzazioni. –

risposta

28

Le autorizzazioni vengono applicate all'intera classe View ma è possibile tenere conto degli aspetti della richiesta (come il metodo GET o POST) nella decisione di autorizzazione.

Vedere il built-in IsAuthenticatedOrReadOnly come esempio:

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 
+0

Ci scusiamo per il ritardo. Grazie, Kevin. La tua risposta è stata perfetta. Esiste la classe di autorizzazione 'IsAuthenticatedOrReadOnly', che può usare' SAFE_METHODS'. –

+0

Molto bello, funzionerà anche con un'API POST-only, ad esempio per la creazione di lead da parte di affiliati di terze parti, ma per impedire l'elenco dell'intero elenco di lead? –

33

Ho incontrato lo stesso problema quando si utilizza CBV di, come ho abbastanza complessa logica di autorizzazioni in base al metodo di richiesta.

La soluzione mi è venuta è stato quello di utilizzare il 'rest_condition' app di terze parti elencati in fondo a questa pagina

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

https://github.com/caxap/rest_condition

Ho appena dividere la logica del flusso di autorizzazioni in modo che ogni ramo verrà eseguito, a seconda del metodo di richiesta.

from rest_condition import And, Or, Not 

class MyClassBasedView(APIView): 

    permission_classes = [Or(And(IsReadOnlyRequest, IsAllowedRetrieveThis, IsAllowedRetrieveThat), 
          And(IsPostRequest, IsAllowedToCreateThis, ...), 
          And(IsPutPatchRequest, ...), 
          And(IsDeleteRequest, ...)] 

Così la 'O' determina quale ramo dei permessi dovrebbe funzionare a seconda del metodo di richiesta e la 'E' avvolge i permessi relativi al metodo di richiesta accettata, quindi tutto deve passare per l'autorizzazione da concedere. Puoi anche mescolare "Or", "And" e "Not" all'interno di ogni flusso per creare autorizzazioni ancora più complesse.

Le classi permesso di eseguire ogni ramo semplicemente simile a questa,

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