首页 > 解决方案 > REST 上的奇怪行为:更新/补丁视图不允许 get 方法并在通过请求调用时返回 405

问题描述

以前也有人问过类似的问题,但我似乎无法用答案解决我的问题。

我正在尝试部分更新一个对象,并且我覆盖了partial_update methodREST 的泛型UpdateAPIView,但是当我通过调用这个视图时,requests我得到了一个405:get method not allowed-response。

非常奇怪的是,我的代码工作了大约 2 周,现在突然间我收到了这个错误。我正用头撞墙,似乎无法弄清楚这一点。

在我看来,我正在这样做:

class BuildingUpdateAPI(UpdateAPIView):
    serializer_class = BuildingSerializer

    def partial_update(self, request, *args, **kwargs):
        """Patches building specified in URL with data in request."""

        network = Network.objects.get(name=self.kwargs["name_network"])
        building = network.buildings.get(name=self.kwargs["name_building"])

        serializer = BuildingSerializer(building, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(status=200, data=serializer.data)
        msg = (
            "Error message"
        )
        return JsonResponse(status=400, data=msg, safe=False)

我的序列化器很简单,它只定义字段(但如果有帮助,我可以提供)。

在其他答案中,据说 REST 寻找 aget-method却找不到它。但我不是通过 get 调用它,而是通过patch

ep = "http://localhost:8000/path/to/update/"
data = {
   "update_field": "123"
}
r = requests.request("patch", url=ep, data=data, headers=get_headers())

其他答案说我调用了错误的 URL,但我很确定它是正确的 URL。再说一次,这以前有效,现在无效。或者我不能Network.objects.get在更新方法中调用吗?但那我怎么可能做任何事……

让这件事变得更加荒谬:我可以使用 REST 接口进行更新。但是通过请求发送补丁请求会给我这个错误(但我需要用请求来做)

我真的没有选择,非常感谢任何帮助。提前致谢。如果我可以提供更多代码或信息,只需 lmk。

谢谢。

更新:通过邮递员尝试这个也会给出同样的错误,所以我猜这不是请求的问题。

网址.py:

urlpatterns = [
    path(
        "api/v1/networks/<int:pk>/",
        NetworkDetailAPIById.as_view(),
        name="networks-detail-api-id",
    ),
    path(
        "api/v1/networks/<str:name>/",
        NetworkDetailAPIByName.as_view(),
        name="networks-detail-api-name",
    ),
    path(
        "api/v1/networks/update/<int:pk>/",
        NetworkUpdateAPI.as_view(),
        name="networks-update-api",
    ),
    path(
        "api/v1/networks/buildings/new/",
        NetworkBuildingCreateAPI.as_view(),
        name="networks-buildings-create-api",
    ),
    path(
        "api/v1/networks/project/<str:project_name>",
        NetworkProjectListAPI.as_view(),
        name="networks-project-list-api",
    ),
    path(
        "api/v1/buildings/<int:id>/",
        BuildingRetrieveAPI.as_view(),
        name="buildings-detail-api",
    ),
    path(
        "api/v1/buildings/delete/<int:id>",
        BuildingDeleteAPI.as_view(),
        name="buildings-delete-api",
    ),
    path(
        "api/v1/buildings/update/<str:name_network>/<str:name_building>",
        BuildingUpdateAPI.as_view(),
        name="buildings-update-api",
    ),
    path(
        "api/v1/network/buildings/<str:name_network>/",
        BuildingByNetworkListAPI.as_view(),
        name="network-buildings-list-api",
    ),
    path(
        "api/v1/time-series/",
        TimeSeriesAPI.as_view(),
        name="time-series-list-create-api",
    ),
    path(
        "api/v1/time-series/network/building/type-data/<str:name_network>/<str:name_building>/<str:type_data>/",
        TimeSeriesBuildingInNetworkAPI.as_view(),
        name="time-series-building-data-type-detail-api",
    ),
    path(
        "api/v1/time-series/project/type-data/step/<str:project>/"
        "<str:type_data>/<str:time_step>/",
        TimeStampBuildingsAPI.as_view(),
        name="timestamp-detail-api",
    ),

    path("api/v1/bldg/<str:name_network>/<str:name_building>/", SampleCreate.as_view(), name="sample")
]

添加时出错get


500
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="robots" content="NONE,NOARCHIVE">
  <title>AssertionError
          at /de/api/v1/bldg/TestDevNetworkBuilding4/Demand_1/</title>
  <style type="text/css">
    html * { padding:0; margin:0; }


..... plus a bunch of html 

标签: djangodjango-rest-frameworkdjango-viewsdjango-serializer

解决方案


您的路径缺少端口组件:

ep = "http:localhost:/path/to/update/"

应该是这样的:

ep = "http:localhost:5000/path/to/update/"

更新:

尝试patch在类中添加一个方法:

def patch(self, request, *args, **kwargs):
    kwargs['partial'] = True
    return self.partial_update(request, *args, **kwargs)

然后,更改为:

r = requests.request("PATCH", url=ep, data=data, headers=get_headers())

或尝试:

r = requests.patch(url=ep, data=data, headers=get_headers())

更新 2:

故障排除后:

/de/api/v1/bldg/TestDevNetworkBuilding4/Demand_1这是一个与您的SampleCreate.as_view()URL 模式匹配的断言错误。该网址正在path("api/v1/bldg/<str:name_network>/<str:name_building>/"匹配。

可能的原因:您在 url 中混淆了 bldg 和 building,或者添加了另一个 url 参数,例如 language deen等。


推荐阅读