Django Rest框架中CreateAPIView的权限

问题描述:

我查看了CreateAPIView的代码,并且在创建过程中无处检查权限。所以我决定检查他们在perform_create钩如下:Django Rest框架中CreateAPIView的权限

class CourseList(generics.CreateAPIView): 
    """ 
    Create a course. 
    A user can create a course if he/she is an instructor in 
    the academy the course is to be created in. 
    """ 
    serializer_class = CourseRef 
    queryset = Course.objects.all() 
    permission_classes = (IsAuthenticated, IsInstructorInAcademy) 

    def perform_create(self, serializer): 
     self.check_object_permissions(self.request, serializer.validated_data.get('academy')) 
     serializer.save() 

该权限的样子:

class IsInstructorInAcademy(BasePermission): 
    def has_object_permission(self, request, view, academy): 
     return request.user.instructor_set.filter(academy=academy).exists() 

当我尝试创建过程中,最初的权限检查运行正常和课程被保存,但随即我得到以下错误:

ValueError at /api/courses/ 
Cannot query "Mathematics 11A": Must be "Academy" instance. 

,这提高在权限检查,其结果是POST返回500 ISE的结果。

(这是稍微哈克,因为我传递学院例如在权限检查在perform_create挂钩,而认为真正担心的课程。我考虑过使用许可IsInstructorInAcademyOfObject但对于这一点,我需要在传递对象,除非保存序列化程序,否则我无法获得该对象。)

什么是在此检查权限的最佳方法?

您遇到了问题,因为您正在使用权限绑定业务逻辑检查。

代替调用check_object_permission,请在执行反序列化后执行自己的检查,如果检查失败,请提出PermissionDenied

+0

我想了解'业务逻辑检查'和'权限'之间的区别,因为即使在这里,测试是在用户。我正在检查这是否是某种用户,请允许这个/那个。 – slider

+0

当然,但是您的测试意味着您在请求内容已知之前执行权限检查时知道请求的内容。 – Linovia

+0

我认为请求的内容不是问题。问题在于学院实例(或者当你提到'请求内容?'时,你的意思是?)。但除此之外,请求内容何时已知?除此之外,执行此检查的最佳位置是什么? 'perform_create'里面? – slider