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,)
我正在尝试授予店主查看权限。所以我制作了一个文件,在其中创建了不同的权限。在我的许可下,我首先检查用户是否使用 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-levelhas_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, raisingPermissionDenied
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,)