Python 如何在DRF ModelViewSet中为单独的请求方法设置权限?
我对Django和Django Rest框架相当陌生,我不明白为什么我的代码不能工作。 我有一个商业模型,它有几个字段:Python 如何在DRF ModelViewSet中为单独的请求方法设置权限?,python,django,api,http,django-rest-framework,Python,Django,Api,Http,Django Rest Framework,我对Django和Django Rest框架相当陌生,我不明白为什么我的代码不能工作。 我有一个商业模型,它有几个字段: class Biz(models.Model): uuid = models.UUIDField(default=uuid.uuid4, editable=False) title = models.CharField(max_length=200) description = models.TextField() address = mode
class Biz(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
description = models.TextField()
address = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=100)
phone = PhoneNumberField()
我使用ModelSerializer将其序列化为:
class BizSerializer(serializers.ModelSerializer):
class Meta:
model = Biz
fields = "__all__"
我使用ModelViewSet为其设置端点:
class BizViewSet(viewsets.ModelViewSet):
queryset = Biz.objects.all()
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = [HasGroupPermission]
required_groups = {
"GET": ["__all__"],
"POST": ["member", "biz_post"],
"PUT": ["member", "biz_edit"],
"PATCH": ["member", "biz_edit"],
}
serializer_class = BizSerializer
你可能已经注意到了。这是我为确认请求用户在所需组中而设置的自定义权限。代码为:
def is_in_group(user, group_name):
"""
Takes a user and a group name, and returns `True` if the user is in that group.
"""
try:
return Group.objects.get(name=group_name).user_set.filter(id=user.id).exists()
except Group.DoesNotExist:
return None
class HasGroupPermission(permissions.BasePermission):
"""
Ensure user is in required groups.
"""
def has_permission(self, request, view):
# Get a mapping of methods -> required group.
required_groups_mapping = getattr(view, "required_groups", {})
# Determine the required groups for this particular request method.
required_groups = required_groups_mapping.get(request.method, [])
# Return True if the user has all the required groups or is staff.
return all(
[
is_in_group(request.user, group_name)
if group_name != "__all__"
else True
for group_name in required_groups
]
) or (request.user and request.user.is_staff)
但是,当我发出GET请求时,权限功能的工作方式与预期的一样,允许每个人发出请求。当我发出POST请求时,如果用户不在成员组和biz_POST组中,则权限功能也可以完美工作,请求被拒绝。
当我尝试其他方法(如PUT、PATCH和DELETE)时,问题就出现了。为什么会发生这个问题?一半的方法有效,另一半几乎无效。目前我对DRF的知识有限,似乎无法解决这个问题 您好,您可以使用DjangoModelPermissions而不是HasGroupPermission 首先,您必须导入它
from rest_framework.permissions import DjangoModelPermissions
此权限检查用户是否具有放置、发布和删除权限
所有用户都有权限
您必须在“管理”中为用户设置权限或为用户组设置权限
我希望它能帮助您的权限方法不提供对象级权限,而PUT和PATCH需要对象级权限
您必须创建对象级权限,这些权限仅针对通过使用permissions.BasePermission类的has_object_permission方法影响特定对象实例的操作运行
看这个
希望能有帮助。我意识到我的问题很愚蠢。我的BizViewSet实际上是一个ViewSet,我没有意识到我必须制作补丁,并像localhost:8000/api/biz/$id那样删除对对象链接的请求。由于我的用户序列化程序不是一个视图集,所以我认为修补方法的工作方式与我传递JSON主键以及我想要修补的数据的方式相同,但视图集不同,我不知道这一点。愚蠢。这肯定是您的视图集的完整代码吗?@monio是的,对于我的Biz视图集,仅此而已,除了一些导入和其他模型的视图集,我认为它们与BizViewSet无关。我建议调试您的HasGroupPermission.has_permission方法,并确保on-PUT方法,必需的_组和request.method变量是正确的。您可以调试这些信息,也可以在那里打印这些信息。另一个选项是使用view.action变量而不是request.method进行映射。默认情况下,DRF分别映射用于查看的GET on list、POST、GET on detail、PUT、DELETE方法。操作名为list、create、retrieve、update、DELETE。@monio该函数与POST和GET request权限完美配合。我打印了这个函数,并对它进行了调试。在我眼里没有什么不对劲。它查询组id并检查用户是否在该组中。若用户不在post组中,则只允许GET。但是,无论指定的组要求如何,所有PUT、PATCH和DELETE请求都将被拒绝。您需要调试应用程序,可能您没有使用PUT、PATCH和DELETE发送身份验证令牌。抱歉,但我认为问题出在其他地方,应该可以解决。我可以通过某种方式与您联系,并尝试帮助您访问git repo。问题仍然存在。它正确地运行GET和POST请求,但不管组权限、用户权限、超级用户状态和/或is_人员状态如何,都不允许使用其他方法。编辑:虽然我认为这种方法更好,我想我会有一个更干净的代码。在DjangoModelPermissions for PUT DELETE和PATCH check中,用户有一个permissionI测试,它工作得非常好!如果组的用户没有删除、放置或路径的权限。用户不能这样做。谢谢您的努力!那么,问题一定是别的。我会稍微调整一下我的代码,看看是否有任何变化。如果答案是真的,请接受答案。始终在viewset初始方法上调用thankshas_权限方法。除非您需要访问对象,否则您是否会使用has_object_权限并不重要,但在这种情况下,这不是我最自豪的时刻,但在未来的某个地方,这可能是其他人的问题,因为在本文中,很多人都是像我这样的新手。