【发布时间】:2022-09-23 01:43:28
【问题描述】:
DRF 上的 Permission 的 has_object_permission 方法显然不会在 Create 上执行,因为该对象还不存在。但是,在某些用例中,权限取决于相关对象。例如:
class Daddy(models.Model):
name = models.CharField(max_length=20)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Kiddy:
title = models.CharField(max_length=12)
daddy = models.ForeignKey(Daddy, on_delete=models.CASCADE)
如果我们只想允许Daddy 的所有者创建Kiddy 的Daddy,我们将不得不在某个地方验证它。
我知道这是一个非常普遍的讨论,在this question 和更多其他地方也提到过。它还在DRF GitHub itself 上进行了讨论,其中为此目的进行了文档更新,并参考 DRF 文档解决了问题here with the following sentence:
...为了限制对象的创建,您需要在您的 Serializer 类中实现权限检查或覆盖 ViewSet 类的 perform_create() 方法。
因此,参考 DRF 文档,我们可以执行以下解决方案之一:
class KiddySerializer(viewsets.ModelViewSet): validate_daddy(self, daddy): if not daddy.owner == self.context[\'request\'].user: raise ValidationError(\"You cannot create Kiddies of that Daddy\") return daddy或者
class KiddyViewSet(ModelViewSet): def perform_create(self, serializer): if (self.request.user != serializer.validated_data[\'daddy\'].owner) raise ValidationError(\"You cannot create Kiddies of that Daddy\") serializer.save()现在,有一个问题也提出了我的问题。如果我关心在未经授权的请求下共享给用户的信息怎么办。因此,在
Daddy不存在的情况下,用户将获得:Invalid pk \\\"11\\\" - object does not exist并且在对象存在但用户无权访问的情况下,它将返回You cannot create Kiddies of that Daddy我想在两种情况下都显示相同的消息:
The Daddy does not exist or you don\'t have permission to use it.如果我使用如下 PermissionClass 是可能的:
class OwnsDaddy(BasePermission): def has_permission(self, request, view): if not Daddy.objects.allowed_daddies(request.user).filter(pk=request.data[\'daddy\']).exists(): return False这也可以,但是由于权限是在序列化程序之前验证的,如果用户传递的 daddy 的 ID 不正确(比如说字符串),就会导致 500 错误。我们可以通过 try-except 子句来防止这种情况,但仍然感觉不对。
所以,最后。什么是解决这个问题的好方法?
标签: python django django-rest-framework permissions django-permissions