Django - 自定义对象权限视图

Django - Custom Object Permission View

我正在尝试授予店主查看权限。所以我制作了一个文件,在其中创建了不同的权限。在我的许可下,我首先检查用户是否使用 has_permission 函数登录。我现在试图确定用户是否真正拥有具有 has_object_permission 功能的商店。不幸的是,我觉得我的功能没有正确执行。 尽管我允许,但我始终可以从任何帐户(无论店主与否)提出请求。

以下是我使用的模型:

models.py

class Shop(models.Model):
    name = models.CharField(max_length=255)
    category = models.ForeignKey(ShopCategory, on_delete=models.SET_NULL, null=True, blank=True)
    description = models.TextField(blank=True, null=True)
    path = models.CharField(max_length=255, unique=True, null=True, blank=True) # Set a null and blank = True for serializer
    mustBeLogged = models.BooleanField(default=False)
    deliveries = models.FloatField(default=7)

    def __str__(self):
        return self.name

class UserShop(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    shop = models.ForeignKey(Shop, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.user.name} {self.user.surname} - {self.shop.name}"

这是我的权限:

utils.py

class IsOwner(BasePermission):
    """
    Check if the user who made the request is owner.
    Use like that : permission_classes = [IsOwner]
    """
    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated
    def has_object_permission(self, request, view, obj):
        try:
            user_shop = UserShop.objects.get(user=request.user, shop=obj)
            return True
        except:
            return False

class OwnerView(APIView):
    """
    Check if a user is owner
    """
    permission_classes = (IsOwner,)

这是我的观点:

views.py

class ShopDetail(OwnerView):
    """Edit ou delete a shop"""
    def put(self, request, path):
        """For admin or shop owner to edit a shop"""
        shop = get_object_or_404(Shop, path=path)
        serializer = ShopSerializer(shop, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)

这是我的序列化程序:

serializers.py

class ShopSerializer(serializers.ModelSerializer):    
    class Meta:
        model = Shop
        fields = '__all__'

提前感谢您的帮助

Custom permissions 的文档中所述:

Note: The instance-level has_object_permission method will only be called if the view-level has_permission checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call .check_object_permissions(request, obj). If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising PermissionDenied on failure.)

您已经自己实现了 put 方法并自己获取了对象,而不是使用 get_object 方法(调用 check_object_permissions 本身),因此永远不会调用 check_object_permissions .相反,您应该在视图 class 中将 lookup_field 设置为 path 并使用 get_object:

class ShopDetail(OwnerView):
    """Edit ou delete a shop"""
    <b>queryset = Shop.objects.all()
    lookup_field = 'path'</b>
    
    def put(self, request, path):
        """For admin or shop owner to edit a shop"""
        <b>shop = self.get_object()</b>
        serializer = ShopSerializer(shop, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)

也这样做 OwnerView 应该继承自 GenericAPIView:

from rest_framework.generics import GenericAPIView


class OwnerView(GenericAPIView):
    """
    Check if a user is owner
    """
    permission_classes = (IsOwner,)