【发布时间】:2020-05-21 16:27:03
【问题描述】:
我对 Django 和 Django Rest Framework 还很陌生,我不知道为什么我的代码不起作用。 我有一个包含几个字段的 Biz 模型:
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
您可能注意到HasGroupPermission。这是我为确认请求用户在所需组中而做出的自定义权限,代码为:
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 请求时,权限功能也可以正常工作(如果用户不在两者中"member" 和 "biz_post" 组合请求被拒绝)。 当我尝试 PUT、PATCH 和 DELETE 等其他方法时,就会出现问题。 为什么会出现这个问题? 一半的方法有效,而另一半(有点)无效。目前我对 DRF 的了解有限,似乎无法解决问题。
【问题讨论】:
-
那肯定是您的视图集的完整代码?
-
@monio 是的,我的 Biz 视图集仅此而已,除了一些我认为与 BizViewSet 无关的导入和其他模型的视图集(?)。
-
我建议调试您的 HasGroupPermission.has_permission 方法并确保在“PUT”方法上,required_groups 和 request.method 变量是正确的(您可以调试或仅打印这些信息)。另一种选择是使用 view.action 变量而不是 request.method 进行映射。默认情况下,DRF 分别将 GET(在列表上)、POST、GET(在细节上)、PUT、DELETE 方法映射到 view.action 命名列表、创建、检索、更新、删除。
-
@monio 该功能与 POST 和 GET 请求权限完美配合。我打印了该功能并对其进行了调试。在我眼里没有错。它查询组 id 并检查用户是否在该组中。如果用户不在帖子组中,则只允许 GET。但是,无论指定的组要求如何,所有 PUT、PATCH 和 DELETE 请求都会被拒绝。
-
您需要调试您的应用程序,也许您没有发送带有 PUT、PATCH 和 DELETE 的身份验证令牌。抱歉,但我认为问题出在其他地方,它应该可以工作。我可以以某种方式与您联系并尝试帮助您(也许可以访问 git repo)。
标签: python django api http django-rest-framework