下面是我的一个视图类:

from rest_framework.views import APIView
class MyView(APIView):
    permission_classes = [CustomAccessPermission]

    def get(self, request, id: int) -> Response:
        object = get_object_or_404(MyObjectClass, id)
        serializer = MySerializer(object)
        return Response(serializer.data)

    def delete(self, request, id: int):
        object = get_object_or_404(MyObjectClass, id)
        object.status = MyObjectClass.Status.DELETED
        object.save()
        return Response(status=status.HTTP_200_OK, data=id)

下面是我的自定义访问权限类:

from rest_framework import permissions
from django.core.exceptions import PermissionDenied


class CustomAccessPermission(permissions.BasePermission):
    message = "You cannot access objects created by other users."

    def has_object_permission(self, request, view, obj):
        if obj.user_id != request.user.id:
            raise PermissionDenied(self.message)
        return True

因此,在我的对象中,我存储了user_id,它包含创建该对象的用户的ID.我想判断请求中的id是否等于该user_id,以了解用户是否可以看到此对象.因此,例如,当我运行Get:http://localhost:8050/api/objects/4时,我想获取id=4的对象的USER_ID,如果它等于quest.user.id,那么我们将允许用户看到它,否则我们应该拒绝.删除请求也是如此,应该首先根据对象的user_id进行判断.

上面的代码不起作用,它不能访问权限类中的HAS_OBJECT_PERMISSION()方法. 我应该修改什么?

推荐答案

它没有,因为您自己实现了getdelete,并使用了APIView.就像Django的View一样,AN APIView只实现了处理API请求的视图的基本功能.它有一个.check_object_permissions(…)可以判断对象的权限,但你需要自己做这件事.

这就是为什么一个人几乎总是从提供更多功能的GenericAPIView开始.的确,

from rest_framework.views import GenericAPIView


class MyView(GenericAPIView):
    permission_classes = [CustomAccessPermission]
    queryset = MyObjectClass.objects.all()
    serializer_class = MySerializer
    lookup_url_kwarg = 'id'

    def get(self, request, id: int) -> Response:
        object = self.get_object()
        serializer = MySerializer(object)
        return Response(serializer.data)

    def delete(self, request, id: int):
        object = self.get_object()
        object.status = MyObjectClass.Status.DELETED
        object.save()
        return Response(status=status.HTTP_200_OK, data=id)

但是,我们仍然可以减少样板代码的数量,并让Django REST框架实现方法本身:

from rest_framework.generics import RetrieveDestroyAPIView


class MyView(RetrieveDestroyAPIView):
    permission_classes = [CustomAccessPermission]
    queryset = MyObjectClass.objects.all()
    serializer_class = MySerializer
    lookup_url_kwarg = 'id'

    def perform_destroy(self, instance):
        instance.status = MyObjectClass.Status.DELETED
        instance.save()

就是这样.如果您在模型本身上实现了"软删除":即覆盖101本身的.delete()方法,则不需要覆盖perform_destroy.

Django相关问答推荐

Django-Values()并按月分组

Django迁移嵌套模型时出错,不带迁移基本模型

未强制执行枚举值

更改Django的创建时间字段

如何在Django管理自定义筛选器中包含自定义模型方法?

是否可以在 Django 中重命名应用程序的组名?

Playframework 和 Django

如何使用 matplotlib 在绘图的角落插入小图像?

Django:在模板中呈现表单字段时添加 CSS 类

如何在django中生成临时文件然后销毁

更新Django模型对象多个字段的有效方法

Django:在管理界面中显示图像

Django 默认=timezone.now + delta

如何覆盖 django 管理员翻译?

Django:在还原(迁移)后try 访问数据库时权限被拒绝

如何在 Django 中更改上传文件的文件名?

ModelForm 上的 Django 和字段集

在 django 中获取空查询集的类名

Django - TypeError - save() 得到了一个意外的关键字参数force_insert

获取'str'对象在Django中没有属性'get'