在视图集中创建的 Django-rest-framework 权限

     2023-02-24     144

关键词:

【中文标题】在视图集中创建的 Django-rest-framework 权限【英文标题】:Django-rest-framework permissions for create in viewset 【发布时间】:2014-05-10 17:03:02 【问题描述】:

我正在尝试创建一个 REST API 并且卡在用户注册上:基本上我需要在注册之前获得访问令牌。

这是视图:

class UserViewSet(viewsets.ModelViewSet):

    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def metadata(self, request):
        """
        Don't include the view description in OPTIONS responses.
        """
        data = super(UserViewSet, self).metadata(request)
        return data

    def create(self, request):
        serializer = self.get_serializer(data=request.DATA, files=request.FILES)

        if serializer.is_valid():
            self.pre_save(serializer.object)
            self.object = serializer.save(force_insert=True)
            self.post_save(self.object, created=True)
            self.object.set_password(self.object.password)
            self.object.save()
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED,
                            headers=headers)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

这是解决方法:

@api_view(['POST'])
@permission_classes((AllowAny,))
@csrf_exempt
def create_auth(request, format=None):
    data = JSONParser().parse(request)
    serialized = UserSerializer(data=data)

    if serialized.is_valid():
        user = User.objects.create_user(
            serialized.init_data['email'],
            serialized.init_data['username'],
            serialized.init_data['password'],
        )
        user.groups = serialized.init_data['groups']

        user.save()

        serialized_user = UserSerializer(user)
        return Response(serialized_user.data, status=status.HTTP_201_CREATED, headers="Access-Control-Allow-Origin": "http://127.0.0.1:8000/")
    else:
        return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST, headers="Access-Control-Allow-Origin": "http://127.0.0.1:8000/")

我的问题是:如何在 UserViewSet 中指定 create 我不需要凭据?还是指定自定义身份验证方法?我不想更改整个视图集的身份验证/权限类。

谢谢, 阿迪

编辑 澄清:应允许未注册用户发布注册数据,不应允许其他任何内容。经过身份验证的用户可以获取用户列表并更新他们自己的个人资料……这是默认行为。这就是为什么 AllowAny 不是一个选项的原因。在我看来,这个合适的地方是 create 函数,但我没有得到我应该覆盖的东西。

【问题讨论】:

【参考方案1】:

自定义get_queryset方法:

def get_queryset(self):
    if self.request.user.is_superuser:
        return User.objects.all()
    else:
        return User.objects.filter(id=self.request.user.id)

这样,经过身份验证的用户只能检索、修改或删除自己的对象。

指定permission_classes = (AllowAny,),以便经过身份验证的用户可以创建一个新用户。

编辑:来自 cmets 的进一步解释

以这种方式自定义 get_queryset 方法意味着:

    是的,未经身份验证的用户可以发送 GET 请求来检索用户列表,但它将为空,因为返回 User.objects.filter(id=self.request.user.id) 确保只有信息返回关于经过身份验证的用户的信息。

    这同样适用于其他方法,如果经过身份验证的用户尝试删除另一个用户对象,则会返回详细信息:未找到(因为它尝试访问的用户不在查询集中)。

    经过身份验证的用户可以对其用户对象做任何他们想做的事情。

【讨论】:

感谢您的回复。在这种情况下,我将失去注册用户的所有权限检查和内在功能,例如检索完整的用户列表。 否,因为注册用户只能使用自己的对象而不是其他对象,视图中的 get_queryset 方法确保这一行: return User.objects.filter(id = self. request.user.id). 这允许未通过身份验证的用户获取用户列表...我不希望这样。我在原帖中添加了一些说明。 以这种方式自定义 get_queryset 方法意味着以下内容:1 是的,未经身份验证的用户可以发送 GET 请求来检索用户列表,但它会为空 因为return User.objects.filter(id = self.request.user.id) 确保只返回有关经过身份验证的用户的信息。 2 这同样适用于其他方法,如果经过身份验证的用户尝试删除另一个用户对象,则会返回详细信息:未找到(因为它尝试访问的用户不在查询集中)。 3经过身份验证的用户可以为他们的用户对象做任何他们想做的事情。 确实,经过一番思考,这似乎是正确的方法。感谢您的帮助【参考方案2】:

您可以利用 Django REST Framework 定义自定义权限的能力。您可以在自定义类中同时指定 has_permissionhas_object_permission。除了发布到创建端点之外,这将为您提供向匿名用户抛出 403 的预期行为。它可能看起来像:

class IsAnonCreate(permissions.BasePermission):
    def has_permission(self, request, view):
        if request.method == "POST" and not request.user.is_authenticated():
            return True
        elif not request.user.is_authenticated() and request.method != "POST":
            return False
        elif request.method in permissions.SAFE_METHODS:
            return True

        return False

    def has_object_permission(self, request, view, obj):
        if not request.user.is_authenticated():
            return False
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.username == request.user.username

如果需要,您可以为经过身份验证的用户添加一些自定义处理。

那么您需要做的就是将权限类添加到您的ModelViewSet

class UserViewSet(viewsets.ModelViewSet):

    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAnonCreate, )

【讨论】:

【参考方案3】:

这是基于@argaen 的回答,它对我有用:

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    permission_classes = (AllowAny,)
    authentication_classes = (NoAuthentication,)
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('id', 'email', 'name')

    def get_queryset(self):
        user = TokenAuthentication().authenticate(self.request)
        if user is not None:
            user = user[0]
            if user.is_superuser:
                return get_user_model().objects.all()
            else:
                return get_user_model().objects.filter(id=user.id)

        return get_user_model().objects.none() 

【讨论】:

Django DRF - 视图集中的补丁请求对象?

】DjangoDRF-视图集中的补丁请求对象?【英文标题】:DjangoDRF-Patchrequestobjectinviewset?【发布时间】:2021-07-2615:40:51【问题描述】:我们正在使用oauth2并在我们的测试中执行force_login()模拟身份验证。然而,在我们的模型视图集中,... 查看详情

Google BigQuery:授予服务帐户权限以仅在某些特定数据集中创建作业

...了我的所有数据。在这个项目中,我创建了多个包含不同视图的数据集。现在我 查看详情

如何通过在焦点集中时将其移动到键盘顶部/视图中心来突出显示滚动视图中的焦点 UITextField

】如何通过在焦点集中时将其移动到键盘顶部/视图中心来突出显示滚动视图中的焦点UITextField【英文标题】:HowtohighlightthefocussedUITextFieldinascrollviewbymovingittothetopofthekeyboard/centeroftheviewwhenitwasfocussed【发布时间】:2012-10-2511:21:47【... 查看详情

如何在非通用视图/视图集中使用分页?

】如何在非通用视图/视图集中使用分页?【英文标题】:HowtousePaginationinaNon-GenericView/Viewset?【发布时间】:2018-01-2201:31:53【问题描述】:序幕:我在不止一篇帖子中看到过这个问题:DjangoRestFramework-APIViewPaginationPaginationnotworkingin... 查看详情

将视图的顶部和底部约束到相同的准则以集中它,它应该工作吗?

】将视图的顶部和底部约束到相同的准则以集中它,它应该工作吗?【英文标题】:Constrainingtopandbottomofaviewtothesameguidelinetocentralizeit,isitsupposedtowork?【发布时间】:2021-09-2419:46:17【问题描述】:我正在使用指南在某个点在两个视... 查看详情

视图不显示和自动布局集中

】视图不显示和自动布局集中【英文标题】:Viewnotdisplayingandcentralisingwithautolayout【发布时间】:2020-04-2110:02:49【问题描述】:我想以编程方式在我的视图控制器中添加一个视图并集中它。我将视图作为子视图添加到父视图并启... 查看详情

(反应原生)如何使用地理定位将地图视图集中在用户身上

】(反应原生)如何使用地理定位将地图视图集中在用户身上【英文标题】:(reactnative)HowtocentermapviewonuserusingGeolocation【发布时间】:2021-09-0711:15:41【问题描述】:如何使用Geolocation.getCurrenPosition()以便返回用户的纬度和经度【问... 查看详情

是否执行了视图列集中的所有函数,即使它们没有在查询中显式引用?

】是否执行了视图列集中的所有函数,即使它们没有在查询中显式引用?【英文标题】:Areallfunctionsinaview\'scolumnsetexecuted,eveniftheyaren\'texplicitlyreferencedinaquery?【发布时间】:2020-03-0516:25:11【问题描述】:假设我有一个视图定义,... 查看详情

以编程方式在 BigQuery 的数据集中创建表

】以编程方式在BigQuery的数据集中创建表【英文标题】:CreatingatablewithinadatasetinBigQueryprogrammatically【发布时间】:2017-08-0520:14:52【问题描述】:是否可以使用Java中的API在BigQuery的数据集中创建表?我知道这是可能的bqmk--schema<fil... 查看详情

如何防止 QWebEngineView 将注意力集中在 setHtml(...) 和 load(...) 调用上?

...我用QTreeView和QWebEngineView创建了简单的Qt窗口布局:在树视图中选择了一些项目后,Web引擎视图 查看详情

在 Django Rest Framework 中生成 OpenAPI Schema:更新视图集中的 URL 关键字

】在DjangoRestFramework中生成OpenAPISchema:更新视图集中的URL关键字【英文标题】:GeneratingOpenAPISchemainDjangoRestFramework:URLKeywordinUpdateViewSet【发布时间】:2021-01-1309:12:05【问题描述】:我正在尝试做一些应该非常直截了当的事情,但我... 查看详情

如何在 Django 查询集中创建联合

】如何在Django查询集中创建联合【英文标题】:HowtocreateUnioninDjangoqueryset【发布时间】:2014-05-3109:32:44【问题描述】:我在项目中使用DjangoRESTFramework,我想创建两个不同的模型。我的模型classA(models.Model):name=models.CharField(max_length=... 查看详情

在 Spark 数据集中创建具有运行总计的列

】在Spark数据集中创建具有运行总计的列【英文标题】:createcolumnwitharunningtotalinaSparkDataset【发布时间】:2017-10-0500:16:12【问题描述】:假设我们有一个包含两列的Spark数据集,比如索引和值,按第一列(索引)排序。((1,100),(2,110... 查看详情

在H2数据库的嵌套集中创建存储过程添加节点

】在H2数据库的嵌套集中创建存储过程添加节点【英文标题】:createstoredprocedureaddingnodeinnestedsetinH2database【发布时间】:2010-06-2315:07:35【问题描述】:我有一个用于为嵌套集添加节点的sql,这是我的sqlSELECT@myRight:=rgtFROMnested_categor... 查看详情

视图集中视图的 Django Rest Framework 自定义模式

】视图集中视图的DjangoRestFramework自定义模式【英文标题】:DjangoRestFrameworkcustomschemaforviewinviewset【发布时间】:2018-10-1818:51:39【问题描述】:我有一个使用Django和DjangoRESTFramework构建的API。我有一个模型,它返回一些与典型Django... 查看详情

像 lyft 应用一样集中放置图像视图

】像lyft应用一样集中放置图像视图【英文标题】:Centrallyplacingimageviewlikelyftapp【发布时间】:2018-02-1210:21:36【问题描述】:我尝试开发类似Lyftapp的页面为这种类型的视图使用了集合视图,但没有得到图像中的预期结果。需要一... 查看详情

链接表 OLE 对象在记录集中显示为空,而在查询视图中显示为 OLE 对象

】链接表OLE对象在记录集中显示为空,而在查询视图中显示为OLE对象【英文标题】:LinkedtableOLEObjectshowsasnullinarecordsetwhileitisdisplayedonqueryviewasOLEObject【发布时间】:2017-08-1418:47:53【问题描述】:我有以下Oracle表通过ODBC连接到Access... 查看详情

powershell编辑单个网站集中的所有视图(代码片段)

查看详情