2013-10-11 21 views
14

Tôi là một người mới trong việc phát triển với Django + Django Rest-framework và tôi đang làm việc trên một dự án cung cấp truy cập REST Api. Tôi đã tự hỏi thực hành tốt nhất để gán một quyền khác nhau cho mỗi hành động của một ApiView hoặc Viewset đã cho là gì. Hãy giả sử tôi đã định nghĩa một số lớp quyền hạn như 'IsAdmin', 'IsRole1', 'IsRole2', ... và tôi muốn cấp các quyền khác nhau cho các hành động đơn lẻ (ví dụ: người dùng có Role1 có thể tạo hoặc truy xuất , người dùng có Role2 có thể cập nhật và chỉ Quản trị viên mới có thể xóa).Django rest-framework cho phép hành động

Làm cách nào để cấu trúc chế độ xem dựa trên lớp học để gán lớp quyền cho các hành động 'tạo', 'danh sách', 'truy xuất', 'cập nhật', 'xóa'? Tôi đang cố gắng làm như vậy để có một lớp có thể được sử dụng lại cho các bảng khác nhau có cùng mẫu quyền.

Có lẽ tôi chỉ chìm đắm trong một chút nước, cảm ơn bạn đã trả lời.

Trả lời

12

Bạn có thể tạo custom permission class mở rộng DRF's BasePermission.

Bạn triển khai has_permission nơi bạn có quyền truy cập vào các đối tượng requestview. Bạn có thể kiểm tra request.user để biết vai trò thích hợp và trả lại True/False nếu thích hợp.

Hãy xem lớp học được cung cấp IsAuthenticatedOrReadOnly (và các loại khác) để có ví dụ điển hình về mức độ dễ dàng.

Tôi hy vọng điều đó sẽ hữu ích.

2

Chế độ xem dựa trên lớp của RestFramework có các phương thức cho mỗi động từ HTTP (ví dụ: HTTP GET => view.get() v.v.). Bạn chỉ cần sử dụng quyền, người dùng, nhóm và trang trí của django.contrib.auth như được ghi lại.

+0

trang trí django.contrib.auth của không phải lúc nào những gì hữu ích khi sử dụng quan điểm chung DRF của. Khá thường xuyên bạn không thực hiện các phương thức HTTP - vì vậy không có gì để trang trí. (Và thực hiện chúng, hoặc công văn, chỉ để trang trí chúng là không có niềm vui.) Tốt hơn để sử dụng hệ thống quyền riêng của DRF trong trường hợp này. http://django-rest-framework.org/api-guide/permissions.html –

3

Django có một lớp học được gọi là DjangoObjectPermissions sử dụng Django Guardian làm phụ trợ xác thực.

Khi bạn có người giám hộ Django hoạt động trong cài đặt, bạn chỉ cần thêm permission_classes = [DjandoObjectPermissions] vào chế độ xem của mình và tự động xác thực quyền, để bạn có thể 'CRUD' dựa trên quyền được đặt thành nhóm hoặc người dùng cụ thể django.contrib.auth.

Xem ví dụ gist.

Bạn có thể đặt Django The Guardian như xác thực của bạn được hỗ trợ http://django-guardian.readthedocs.org/en/latest/installation.html

24

Trong tài liệu DRF,

Lưu ý: Phương pháp dụ cấp has_object_permission sẽ chỉ được gọi là nếu kiểm tra has_permission xem cấp đã qua

giả sử sau phép về user đối tượng

  • liệt kê: nhân viên chỉ
  • Tạo: ai
  • Lấy: tự mình hoặc nhân viên
  • Update, cập nhật từng phần: tự mình hoặc nhân viên
  • Phá hủy: nhân viên chỉ

permissons.py

from rest_framework import permissions                


class UserPermission(permissions.BasePermission): 

    def has_permission(self, request, view):               
     if view.action == 'list':                 
      return request.user.is_authenticated() and request.user.is_admin       
     elif view.action == 'create':                
      return True                    
     elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:      
      return True                    
     else:                      
      return False                    

    def has_object_permission(self, request, view, obj):            
     if view.action == 'retrieve':                
      return request.user.is_authenticated() and (obj == request.user or request.user.is_admin)  
     elif view.action in ['update', 'partial_update']:           
      return request.user.is_authenticated() and (obj == request.user or request.user.is_admin)  
     elif view.action == 'destroy': 
      return request.user.is_authenticated() and request.user.is_admin       
     else: 
      return False 

views.py

from .models import User 
from .permissions import UserPermission 
from .serializers import UserSerializer 
from rest_framework import viewsets 


class UserViewSet(viewsets.ModelViewSet): 
    queryset = User.objects.all() 
    serializer_class = UserSerializer 
    permission_classes = (UserPermission,) 
+2

'view.action' có vẻ trực quan hơn nhiều so với' request.method'. +1 – PritishC

1

Cá nhân tôi ghét loại quyền frankenmonster tùy chỉnh, theo ý kiến ​​của tôi, nó không phải là rất thành ngữ khi nói đến khuôn khổ Django; Vì vậy, tôi đã đưa ra giải pháp sau đây - nó rất giống với cách trang trí @list_route và @detail_route hoạt động. Chúng tôi đang dựa trên thực tế là các phương pháp/chức năng là đối tượng hạng nhất

Trước hết tôi là tạo ra dectorator ví dụ:

decorators.py

def route_action_arguments(**kwargs): 
""" 
Add arguments to the action method 
""" 
def decorator(func): 
    func.route_action_kwargs = kwargs 
    return func 
return decorator 

Như bạn có thể nhìn thấy nó thêm một từ điển vào hàm mà nó trang trí với các tham số được truyền dưới dạng danh sách arg

Bây giờ tôi đã tạo hỗn hợp như vậy: mixin. py

class RouteActionArgumentsMixin (object): 
    """ 
    Use action specific parameters to 
    provide: 
    - serializer 
    - permissions 
    """ 

def _get_kwargs(self): 
    action = getattr(self, 'action') 
    if not action: 
     raise AttributeError 
    print('getting route kwargs for action:' + action) 
    action_method = getattr(self, action) 
    kwargs = getattr(action_method, 'route_action_kwargs') 
    print(dir(kwargs)) 
    return kwargs 

def get_serializer_class(self): 
    try: 
     kwargs = self._get_kwargs() 
     return kwargs['serializer'] 
    except (KeyError, AttributeError): 
     return super(RouteActionArgumentsMixin, self).get_serializer_class() 

def get_permissions(self): 
    try: 
     kwargs = self._get_kwargs() 
     return kwargs['permission_classes'] 
    except (KeyError, AttributeError): 
     return super(RouteActionArgumentsMixin, self).get_permissions() 

Mixin thực hiện hai việc; khi get_permissions được gọi, nó sẽ kiểm tra mà 'hành động' được thực thi, và looksup bộ sưu tập permission_classes từ 'route_action_kwargs' liên quan đến việc viewset.action_method.route_action_kwargs

khi get_serializer_class được gọi, nó cũng làm như vậy và chọn các ' serializer' từ '

Bây giờ cách route_action_kwargs' chúng ta có thể sử dụng nó:

@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create') 
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet): 
    """ 
    User and profile managment viewset 
    """ 

    queryset = User.objects.all() 
    serializer_class = UserSerializer 

    @list_route(methods=['post']) 
    @route_action_arguments(permission_classes=(AllowAny,), serializer=LoginSerializer) 
    def login(self, request): 
     serializer = self.get_serializer_class()(data=request.data) 

Đối với tùy chỉnh routse chúng ta định nghĩa một cách rõ ràng, chúng tôi chỉ có thể đặt @route_action_arguments một cách rõ ràng về phương pháp này.

Về viewsets và phương pháp chung chung, chúng tôi vẫn có thể thêm chúng bằng cách sử dụng @method_decorator

@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create') 
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet): 
Các vấn đề liên quan