Django DRF:限制视图集中的看跌期权

Django DRF:限制视图集中的看跌期权,django,django-rest-framework,Django,Django Rest Framework,我想限制我的视图集,以便它允许基于权限的不同输入: 我的模型: class Link(models.Model): name = models.CharField("name", max_length = 128) page = models.PositiveIntegerField("page", default = 1, choices = [(1, 1), (2, 2), (3, 3)]) layouts = models.M

我想限制我的视图集,以便它允许基于权限的不同输入:

我的模型:

class Link(models.Model):
    name = models.CharField("name", max_length = 128)
    page = models.PositiveIntegerField("page", default = 1, choices = [(1, 1), (2, 2), (3, 3)])
    layouts = models.ManyToManyField(Layout)

class Layout(models.Model):
    name = models.CharField("name", max_length = 32) 
序列化程序:

class LinkSerializer(serializers.ModelSerializer):
    test = serializers.SerializerMethodField("get_layouts")

    def get_layouts(self): ## this is not displayed?
        return "test" 

    class Meta:
        model = Link
        fields = ["name", "page", "test"]
例如,我有一个helper类,它提供
所有页面
权限。在restframework API中,我现在有一个从第1-3页的下拉列表,但是如果用户没有使用所有页面的权限,我只想显示
page 1
以供选择(或者将其设置为不带输入字段的文本字段)。 同样的问题也适用于
ManyToMany
字段:如何将布局下拉选项限制为我在管理计划中为该用户选择的选项

现在我手动检查
ViewSet
PUT
方法中的所有内容,并返回一个“用户不允许…->错误请求”

编辑:BC有人问我,现在我做了这样的事情:

class TestViewSet(viewsets.ViewSet):
    serializer_class = LinkSerializer
    http_method_names = ['get', 'put', 'head']
    authentication_classes = [SessionAuthentication,]
    permission_classes = [IsAuthenticated,]

    def list(self, request):
    ...

    def put(self, request):
        ## page logic
        if "app.all_pages" in request.user.get_user_permissions():
            try:
                if not 1 < int(request.data["page"]) <= 3:
                    return Response(data = "page not 2 or 3", 
                                    status = status.HTTP_406_NOT_ACCEPTABLE)
            except Exception as E:
                return Response(data = f"""Error in page selection: {E}""", 
                                status = status.HTTP_400_BAD_REQUEST)
            page = int(request.data["page"])
        else:
            page = 2
        
        ## layout logic:
        store = Store.objects.get(user = request.user)
        allowed_layouts = [l.id for l in store.layouts.all()]
        if not int(request.data["layout"]) in allowed_layouts:
            return Response(data = f"""layout not allowed for store {store}""", 
                            status = status.HTTP_406_NOT_ACCEPTABLE)
        layout = Layout.objects.get(pk = request.data["layout"])
        
        ## do something with page 2 and layout ... in DB/another API   
类TestViewSet(ViewSet.ViewSet):
serializer_class=LinkSerializer
http_method_names=['get','put','head']
身份验证\u类=[SessionAuthentication,]
权限\u类=[IsAuthenticated,]
def列表(自我、请求):
...
def put(自我,请求):
##页面逻辑
如果request.user.get_user_permissions()中的“app.all_pages”:
尝试:

如果不是1 p.1

DRF中的权限只是两个方法的包装,下面介绍它的工作原理

class PermissionX:
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj)
        return True
这是一个权限,
具有\u权限
表示(
请求。用户
具有访问 当前
视图
?)和
具有对象权限
说明(
请求。用户
有权对
对象
执行操作)

obj
是在视图内作用的对象。如果视图适用于用户,则对象将是
User
的实例

这与
权限\u类一起使用,如下所示

    permission_classes = [IsAuthenticated, PermissionX]
p.2

您通常使用
user.has\u perm(perm)
而不是user.permissions中的
'name'。这是因为权限可以存在于
user.groups
中,而不仅仅是
user.permissions

p.3

引发的任何异常都应属于DRF中存在的类型
PermissionDenied

p.4

在当前应用的permission.py文件夹中提取您的权限

p.5


您的权限不会集成到django管理员界面中。这是因为它没有使用DRF,也没有使用您的端点。它正在使用django提供给它的东西。这是正常的,我们讨论的逻辑将由API本身强制执行,当您创建自定义仪表板时,您还需要将其作为一种UX在前端强制执行。

发布与逻辑相关的视图集。将你的助手方法发布到我的解决方案更新了我的问题(这很有效,但我相信这是一个相当次优的解决方案)。首先:感谢你的详细回答。谢谢!但它并没有包含我问题的一个要点:例如,如果一个用户(a)登录并看到了第1-3页的下拉列表,我如何才能让一个用户(B)(不需要查看所有页面的权限)在登录时显示一个只有一个(第1页)条目的菜单?或者我认为所有这些都是错误的,这都是关于“显示所有内容并在拒绝perm时引发异常”?页面本身可能是一个有许可证的模型这就是CMS-s的工作方式是的,到目前为止我就是这样做的。我只是在想,也许最好是“隐藏”用户无论如何都无法访问的字段/选项。是的,最好是为此创建一个动态序列化程序(有文档记录)