如何使用相同的URL为GET和POST请求设置不同的permission_classes?

Zho*_*ndr 4 python django django-rest-framework

我正在使用 DRF(Django Rest Framework)构建端点。

django==2.1.5
djangorestframework==3.9.1
django-rest-auth
djangorestframework-jwt
Run Code Online (Sandbox Code Playgroud)

我有模型“Item”,我想为 GET 和 POST 请求设置不同的permission_classes。

我是这样做的:

@csrf_exempt
@api_view(['GET', 'POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([AllowAny])
def item_list(request):
    if request.method == 'GET':
        items = Item.objects.all()
        serializer = ItemSerializer(items, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = ItemSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)
Run Code Online (Sandbox Code Playgroud)

我想对所有方法使用一个端点,如下所示:

urlpatterns = [
    path('api/item/', views.item_list),
    path('api/item/<int:pk>/', views.item_details),
]
Run Code Online (Sandbox Code Playgroud)

我想AllowAny用户GET请求方法并检查是否isAdminUser请求POST方法

我可以像 Flask 那样,即一种方法用一个装饰器吗?

JPG*_*JPG 9

由于您使用的是基于功能的视图,因此无法选择覆盖任何方法。您现在可以做的是,创建一个新的 Permission 类并将您的逻辑包含在其中

# permissions.py
from rest_framework.permissions import IsAdminUser


class MyCustomPermission(IsAdminUser):
    def has_permission(self, request, view):
        if request.method == 'GET':
            return True
        else:
            return super().has_permission(request, view)
Run Code Online (Sandbox Code Playgroud)

并在您看来将其用作,

# views.py
@csrf_exempt
@api_view(['GET', 'POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([MyCustomPermission]) # chage is here 
def item_list(request):
    if request.method == 'GET':
        items = Item.objects.all()
        serializer = ItemSerializer(items, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = ItemSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)
Run Code Online (Sandbox Code Playgroud)

如果您计划迁移到基于类的视图,您可以通过重写该方法来完成get_permissions()

你可以在这里找到一个简单的例子

def get_permissions(self):
    """
    Instantiates and returns the list of permissions that this view requires.
    """
    if self.request.method == 'GET':
        permission_classes = [AllowAny]
    else:
        permission_classes = [IsAdminUser]
    return [permission() for permission in permission_classes]
Run Code Online (Sandbox Code Playgroud)