2015-09-10 164 views
1

我想構建一個具有字段級權限的API。我從數據庫表中獲得這些權限,但是REST框架中的哪個位置可以檢查用戶是否可以在對象的字段上執行CRUD操作?Django Rest框架和字段級權限

database --- model ---- ModelSerializer ---- ModelViewSet --- browser 

在ModelSerializer中?在這裏,我可以放下字段,然後他們到達視圖,但我沒有權限訪問request.user默認情況下,所以我必須實現,這可以做到,但不能很好地與其他第三方庫我很有效(django-rest-swagger)

還是在ModelViewset中?在哪裏我可以重寫列表,創建,更新和銷燬方法來刪除用戶無權訪問的字段。但是這對於我的Metadata實現並不合適,因爲它直接從序列化器獲取元數據。

或者兩者兼得?例如:DROP不被允許在讀取串行當模型被取通過串行和下拉不被允許,寫之前在視圖集中它們會傳回串行?

回答

1

關於權限here的DRF文檔中有很好的部分。處理(並檢查它們)的好地方是在視圖中。若要從文檔複製一個例子:

from rest_framework.permissions import IsAuthenticated 
from rest_framework.response import Response 
from rest_framework.views import APIView 

class ExampleView(APIView): 
    permission_classes = (IsAuthenticated,) 

    def get(self, request, format=None): 
     content = { 
      'status': 'request was permitted' 
     } 
     return Response(content) 

如果你想有一個自定義的許可檢查,你可以定義自己,並指定你自己的類取代IsAuthenticated

1

您可以創建根據不同的串行您需要特定請求的字段。然後,您需要覆蓋視圖中的get_serializer_class()函數,並根據邏輯決定串行器。

作爲每DRF文檔上get_serializer_class()

可以被覆蓋,以提供動態行爲,諸如使用不同 串行讀操作和寫操作,或不同類型的用戶提供不同的 串行。

例如:

class MyView(..): 

    def get_serializer_class(self): 
     if self.request.user.is_staff: # check if staff user 
      return FullAccountSerializer 
     return BasicAccountSerializer 
    ... 
0

如果要實現自定義權限良好的DRF使用modelviewset。

from rest_framework import status, viewsets 

class MyModelViewsets(viewsets.ModelViewSet): 
    queryset = # queryset 
    serializer_class = # serializer class 
    permission_classes = (# custom permission class her) 

如果希望所有應用自定義權限所有端點在settings.py

REST_FRAMEWORK = { 

    'DEFAULT_PERMISSION_CLASSES': [ 
     'rest_framework.permissions.IsAuthenticated', 
     # add custom permission here 
    ] 
} 
0

的指定它如果使用GenericView,默認情況下DRF把請求對象進入的情況下序列化器對象。您可以通過

self.context['request'].user

0
from utils.mixins import MultiSerializerViewSetMixin 


class UserViewSet(MultiSerializerViewSetMixin, ModelViewSet): 
    serializer_class = UserSerializer 
    serializer_action_classes = { 
     'update': UserDetailSerializer, 
    } 
    permission_classes = (UserPermission,) 
    queryset = User.objects.all() 

源代碼,MultiSerializerViewSetMixin訪問用戶信息: https://gist.github.com/gonz/10044002

我管理我的問題有兩個seriazliers:

from django.contrib.auth.models import User 
from rest_framework import serializers 


class UserSerializerMixin(serializers.Serializer): 
    id = serializers.IntegerField(read_only=True) 
    is_superuser = serializers.BooleanField(read_only=True) 
    first_name = serializers.CharField(max_length=30, required=False, allow_blank=True) 
    last_name = serializers.CharField(max_length=30, required=False, allow_blank=True) 
    email = serializers.EmailField(required=False, allow_blank=True) 

    def create(self, validated_data): 
     return User.objects.create_user(**validated_data) 

    def update(self, instance, validated_data): 
     instance.first_name = validated_data.get('first_name', instance.first_name) 
     instance.last_name = validated_data.get('last_name', instance.last_name) 
     instance.email = validated_data.get('email', instance.email) 
     password = validated_data.get('password', '') 
     if password: 
      instance.set_password(password) 
      instance.save() 
     return instance 

    class Meta: 
     model = User 


class UserSerializer(UserSerializerMixin): 
    username = serializers.CharField(max_length=30) 
    password = serializers.CharField(
     max_length=128, write_only=True, 
     style={'input_type': 'password'}) 


class UserDetailSerializer(UserSerializerMixin): 
    username = serializers.CharField(read_only=True) 
    password = serializers.CharField(
     max_length=128, write_only=True, 
     style={'input_type': 'password'}, 
     required=False, allow_blank=True 
    ) 

有可能你可以使用MultiSerializerViewSetMixin,去年我發現它使用mixins t o創建兩個不同但相似的串行器。