Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在DRF ModelViewSet中为单独的请求方法设置权限?_Python_Django_Api_Http_Django Rest Framework - Fatal编程技术网

Python 如何在DRF ModelViewSet中为单独的请求方法设置权限?

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

我对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 = 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_权限并不重要,但在这种情况下,这不是我最自豪的时刻,但在未来的某个地方,这可能是其他人的问题,因为在本文中,很多人都是像我这样的新手。