簡體   English   中英

在視圖集中創建的Django-rest-framework權限

[英]Django-rest-framework permissions for create in viewset

我試圖創建一個REST API並停留在用戶注冊上:基本上,我需要在注冊之前具有訪問令牌。

這是視圖:

class UserViewSet(viewsets.ModelViewSet):

    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def metadata(self, request):
        """
        Don't include the view description in OPTIONS responses.
        """
        data = super(UserViewSet, self).metadata(request)
        return data

    def create(self, request):
        serializer = self.get_serializer(data=request.DATA, files=request.FILES)

        if serializer.is_valid():
            self.pre_save(serializer.object)
            self.object = serializer.save(force_insert=True)
            self.post_save(self.object, created=True)
            self.object.set_password(self.object.password)
            self.object.save()
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED,
                            headers=headers)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

這是解決方法:

@api_view(['POST'])
@permission_classes((AllowAny,))
@csrf_exempt
def create_auth(request, format=None):
    data = JSONParser().parse(request)
    serialized = UserSerializer(data=data)

    if serialized.is_valid():
        user = User.objects.create_user(
            serialized.init_data['email'],
            serialized.init_data['username'],
            serialized.init_data['password'],
        )
        user.groups = serialized.init_data['groups']

        user.save()

        serialized_user = UserSerializer(user)
        return Response(serialized_user.data, status=status.HTTP_201_CREATED, headers={"Access-Control-Allow-Origin": "http://127.0.0.1:8000/"})
    else:
        return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST, headers={"Access-Control-Allow-Origin": "http://127.0.0.1:8000/"})

我的問題是:如何在UserViewSet中指定不需要憑據的創建 還是指定自定義身份驗證方法? 我不想更改整個視圖集的身份驗證/權限類。

謝謝阿迪

編輯以澄清:未注冊的用戶應被允許POST注冊數據,並且不應被允許其他任何東西。 經過身份驗證的用戶可以獲取用戶列表並更新自己的個人資料...這是默認行為。 這就是為什么AllowAny 不是選項的原因。 在我看來,執行此功能的適當位置是create函數,但我沒有得到應重寫的內容。

自定義get_queryset方法:

def get_queryset(self):
    if self.request.user.is_superuser:
        return User.objects.all()
    else:
        return User.objects.filter(id=self.request.user.id)

這樣,經過身份驗證的用戶只能檢索,修改或刪除自己的對象。

指定permission_classes = (AllowAny,)以便經過身份驗證的用戶可以創建一個新的。

編輯 :評論中的進一步解釋

通過這種方式自定義get_queryset方法意味着:

  1. 是的,未經身份驗證的用戶可以發送GET請求以檢索用戶列表,但該列表為空,因為返回User.objects.filter(id = self.request.user.id)確保僅返回有關身份驗證用戶的信息。

  2. 對於其他方法也是如此,如果經過身份驗證的用戶嘗試刪除另一個用戶對象,則會返回詳細信息:未找到(因為它正在嘗試訪問的用戶不在查詢集中)。

  3. 經過身份驗證的用戶可以對用戶對象執行任何所需的操作。

您可以利用Django REST Framework定義自定義權限的功能。 您可以在自定義類中同時指定has_permissionhas_object_permission 這將為您提供預期的行為,即除了發布到創建端點外,所有其他事件都將403s投給匿名用戶。 它可能看起來像:

class IsAnonCreate(permissions.BasePermission):
    def has_permission(self, request, view):
        if request.method == "POST" and not request.user.is_authenticated():
            return True
        elif not request.user.is_authenticated() and request.method != "POST":
            return False
        elif request.method in permissions.SAFE_METHODS:
            return True

        return False

    def has_object_permission(self, request, view, obj):
        if not request.user.is_authenticated():
            return False
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.username == request.user.username

然后,您可以根據需要為經過身份驗證的用戶添加一些自定義處理。

然后,您需要做的就是將權限類添加到ModelViewSet

class UserViewSet(viewsets.ModelViewSet):

    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAnonCreate, )

這基於@argaen答案,對我有用:

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    permission_classes = (AllowAny,)
    authentication_classes = (NoAuthentication,)
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('id', 'email', 'name')

    def get_queryset(self):
        user = TokenAuthentication().authenticate(self.request)
        if user is not None:
            user = user[0]
            if user.is_superuser:
                return get_user_model().objects.all()
            else:
                return get_user_model().objects.filter(id=user.id)

        return get_user_model().objects.none() 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM