DjangoRestFramework:我可以用两个不同的方法创建一个viewset吗?它们具有相同的url_路径,但请求方法不同?

2024-04-23 23:45:00 发布

您现在位置:Python中文网/ 问答频道 /正文

这是视图集

class MobileDeviceViewset(ModelViewSet):
    @action(
        methods=['post', 'put', 'patch'],
        url_path='token',
        detail=True,
    )
    def update_token(self, request, *args, **kwargs) -> Response:
        ...

    @action(
        methods=['get'],
        url_path='token',
        detail=True,
    )
    def get_token(self, request, *args, **kwargs) -> Response:
        ...

所以我想在这里做的是有一个端点/token/,应用程序将向它发送一个GET请求来检查是否有令牌,如果有则获取它。我还想使用相同的/token/端点向发送更新的令牌。当前发生的是,我得到一个错误,告诉我POST/PATCH/PUT方法不允许在该端点上使用,因此它似乎只识别get_token方法。这里的token对象实际上是一个称为MobileDeviceUser的manytomy through模型,所以我不只是试图更新MobileDevice对象上的字段。在


Tags: pathselftokentrueurlgetresponserequest
1条回答
网友
1楼 · 发布于 2024-04-23 23:45:00

既然您的url_path和{}在这两种情况下都是相同的,为什么要在视图中使用两个单独的方法??
无论如何,我会推荐这种方式,

class MobileDeviceViewset(ModelViewSet):
    # your code

    @action(methods=['get', 'post', 'put', 'patch'], url_path='token', detail=True, )
    def my_action(self, request, *args, **kwargs):
        if request.method == 'GET':
            return self.get_token(request, *args, **kwargs)
        else:
            return self.update_token(request, *args, **kwargs)

    def update_token(self, request, *args, **kwargs):
        return Response("update token response {}".format(request.method))

    def get_token(self, request, *args, **kwargs):
        return Response("update token response {}".format(request.method))

然后你必须在你的URL配置中做一些改变

^{pr2}$

因此,您的URL将类似于,..../mysample/3/token/

注意
该溶液在Python 3.6Django==2.1和{}下进行测试


更新

为什么Method Not Allowed错误?在

当一个请求到达Django时,它会搜索URL configs中的模式,并在匹配时将请求发送到相应的视图。
在您的例子中,您定义了两个具有相同URL(如下所示)的视图(是的,不过是actions)。在

actions = {
    "post": "update_token",
    "put": "update_token",
    "patch": "update_token"
}

urlpatterns = [
                  path('mysample/<pk>/token/', MobileDeviceViewset.as_view(actions={"get": "get_token"})),
                  path('mysample/<pk>/token/', MobileDeviceViewset.as_view(actions=actions))

              ] + router.urls


在这种情况下,会出现一个请求(让它成为一个HTTPPOST),并且URL调度器重定向到满足URL路径的第一个视图。因此,POST请求进入get_token方法,但是,它只允许GET方法


可能的解决办法是什么?在

方法1:
正如我在上面所描述的,使用一个常见的操作并区分HTTP方法并调用适当的方法
方法2:
对两个操作使用不同的URL路径,如

actions = {
    "post": "my_action",
    "put": "my_action",
    "patch": "my_action"
}
urlpatterns = [
                  path('mysample/<pk>/get-token/', MobileDeviceViewset.as_view(actions={"get": "get_token"})),
                  path('mysample/<pk>/update-token/', MobileDeviceViewset.as_view(actions=actions))

              ] + router.urls

相关问题 更多 >