2014-05-18 117 views
6

我在想Django Rest Framework的最佳實踐。我一直在通過每個用戶使用不同的序列化程序(工作人員與帳戶所有者與其他任何人)和HTTP方法來限制訪問權限,以改變帳戶中的某些屬性,但我感覺這太過於混亂。Django Rest框架:最佳實踐?

這是完成我的任務分離出「權限」以更改對象的不同字段的最佳方式嗎?還是有更好,更pythonic的方式來完成我目前以這種方式做的事情?

任何和所有批評與下面的代碼被接受,因爲我覺得我已經削減了一些角落。

非常感謝。

from rest_framework import serializers, viewsets 
from rest_framework.permissions import SAFE_METHODS 
from accounts.models import User 
from cpapi.permissions import * 


class UserSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = User 
     fields = ('id', 'url', 'username', 'password') 
     write_only_fields = ('password',) 

    def restore_object(self, attrs, instance=None): 
     user = super(UserSerializer, self).restore_object(attrs, instance) 
     if 'password' in attrs.keys(): 
      user.set_password(attrs['password']) 
     return user 

class UserDetailsSerializer(UserSerializer): 
    class Meta(UserSerializer.Meta): 
     fields = ('id', 'url', 'username', 'password', 'email') 

class UserListSerializer(UserSerializer): 
    class Meta(UserSerializer.Meta): 
     fields = ('id', 'url', 'username') 

class UserWithoutNameSerializer(UserSerializer): 
    class Meta(UserSerializer.Meta): 
     fields = ('id', 'url', 'password', 'email') 


class UserViewSet(viewsets.ModelViewSet): 
    """ 
    API endpoint that allows users to be viewed or edited. 
    """ 
    serializer_class = UserSerializer 
    model = User 

    def get_serializer_class(self): # Modify to allow different information for different access (userlist vs staff) 
     serializer_class = self.serializer_class 
     if 'List' in self.get_view_name(): 
      serializer_class = UserListSerializer 
     elif self.request.method in ['PUT', 'PATCH']: 
      serializer_class = UserWithoutNameSerializer 
     elif self.get_object() == self.request.user or self.request.user.is_staff: 
      serializer_class = UserDetailsSerializer 
     return serializer_class 

    def get_permissions(self): 
     if self.request.method in SAFE_METHODS or self.request.method == 'POST': 
      return [AllowAny()] 
     elif self.request.method == 'DELETE': 
      return [IsAdminUser()] 
     else: 
      return [IsStaffOrTargetUser()] 

回答

1

如果我正確理解你想要的是每個字段的權限,而不是Django,也不是Django-REST-Framework直接支持它們。您可以安裝像Django Fine-Grained Permissions這樣的軟件包,但由於無法將這些權限交給REST API視圖,因此您會遇到同樣的解決方案。

我建議你堅持你的解決方案,或將序列化程序選擇邏輯放在一個包含所有字段的序列化程序中,並將該角色傳遞給構造函數,然後讓序列化程序根據它建立一個字段列表,但爲了工作,您需要編寫自己的Serializer子類。