通过POST创建对象时,Django Rest Framework对象级别权限问题

时间:2018-09-19 10:53:37

标签: django python-3.x django-models django-rest-framework

我的文件如下:

BusinessActionsPermission

class BusinessActionsPermission(BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        business_obj = view.get_business_obj()
        if request.method in ['GET']:
            return request.user.has_perm('act_on_business', business_obj)
        if request.method in ['PUT', 'PATCH', 'DELETE']:
            return request.user.has_perm('act_on_business', business_obj)
        return False

EmployeeViewSet

class EmployeeViewSet(viewsets.ModelViewSet):
    serializer_class = EmployeeSerializer
    permission_classes = (permissions.IsAuthenticated, BusinessActionsPermission)

    def get_business_obj(self, **kwargs):
        return Business.objects.filter(pk=self.kwargs['business_id'])

    def get_queryset(self, **kwargs):
        return Employee.objects.filter(business__id=self.kwargs['business_id'])

    def create(self, request, *args, **kwargs):
        business = Business.objects.get(pk=self.kwargs['business_id'])
        employee = Employee(business=business)
        serializer = EmployeePOSTSerializer(employee, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)

在调用BusinessActionsPermissionPOST来创建新的Employee方法时,EmployeeViewSet不起作用。没有act_on_busienss的用户可以post并创建员工。

Django Rest Framework文档here说:

  

出于性能方面的考虑,当返回对象列表时,通用视图不会自动将对象级别权限应用于查询集中的每个实例。

这很好。 BusinessActionsPermission正在为detailed retrievals with pk工作。但是不能在不是post的{​​{1}}上工作。

请帮助。

注意:上面的list可以很好地用于详细视图,并且不检查列表视图,这在文档中已经提到了。但是BusinessActionsPermission呢?

2 个答案:

答案 0 :(得分:0)

由于还没有对象,因此DRF永远不会调用has_object_permission方法,因此您应该在POST方法中确定对has_permission方法的许可。

  

还请注意,通用视图将仅检查对象级别   检索单个模型实例的视图的权限。

基本上,如果调用了get_object方法,将检查对象级别权限。 drf source code

答案 1 :(得分:0)

如果您在rest_framework中查看ModelViewSet和泛型的实现,则可以了解何时检查了对象的权限。

使用has_object_permission类的get_object方法检索对象时,将调用BusinessActionsPermission GenericAPIView方法。

因此,据此了解,在您的情况下,创建新对象时不会调用此方法。

您需要做的是将逻辑从has_object_permission移到has_permission

您可以使用has_object_permission来检查已创建的特定对象的权限(例如所有权)。