You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中用独立APIView类实现同一路由CRUD遇405错误如何解决?

解决Django同路由绑定多独立视图的问题

你遇到的405错误确实是Django路由匹配顺序导致的:当请求some_resource/时,会优先匹配第一个path对应的SomeResourceListView,而这个视图只实现了GET方法,自然处理不了POST请求。

要在保持视图类独立的前提下,让同一路径绑定多个视图,有两种可行方案:

方案一:利用path的methods参数(Django 2.2+支持)

直接在路由配置中指定每个path对应的HTTP方法,Django会根据请求的方法匹配对应的视图。修改后的urls.py如下:

from django.urls import path
from .views import (
    SomeResourceListView,
    SomeResourceCreateView,
    SomeResourceRetrieveView
)

url_patterns = [
    # 处理GET请求的列表接口
    path(
        "some_resource/",
        SomeResourceListView.as_view(),
        name="some-resource-list",
        methods=["GET"]
    ),
    # 处理POST请求的创建接口
    path(
        "some_resource/",
        SomeResourceCreateView.as_view(),
        name="some-resource-create",
        methods=["POST"]
    ),
    # 处理GET请求的详情接口
    path(
        "some_resource/<int:pk>",
        SomeResourceRetrieveView.as_view(),
        name="some-resource-retrieve",
        methods=["GET"]
    ),
]

方案二:在as_view()中指定http_method_names

通过给视图的as_view()方法传递http_method_names参数,限制该视图实例只处理指定的HTTP方法,这样即使路由路径相同,Django也会根据方法匹配正确的视图:

from django.urls import path
from .views import (
    SomeResourceListView,
    SomeResourceCreateView,
    SomeResourceRetrieveView
)

url_patterns = [
    path(
        "some_resource/",
        SomeResourceListView.as_view(http_method_names=["get"]),
        name="some-resource-list"
    ),
    path(
        "some_resource/",
        SomeResourceCreateView.as_view(http_method_names=["post"]),
        name="some-resource-create"
    ),
    path("some_resource/<int:pk>", SomeResourceRetrieveView.as_view(), name="some-resource-retrieve"),
]

扩展:实现完整CRUD的路由配置

如果后续要添加update(PUT/PATCH)和delete(DELETE)操作,同样可以用上述方法绑定到some_resource/<int:pk>路径:

假设已创建对应的视图类:

class SomeResourceUpdateView(APIView):
    def put(self, request, pk, *args, **kwargs):
        # 全量更新逻辑
        ...
    def patch(self, request, pk, *args, **kwargs):
        # 部分更新逻辑
        ...

class SomeResourceDeleteView(APIView):
    def delete(self, request, pk, *args, **kwargs):
        # 删除逻辑
        ...

对应的路由配置:

url_patterns = [
    # 列表与创建
    path("some_resource/", SomeResourceListView.as_view(), name="some-resource-list", methods=["GET"]),
    path("some_resource/", SomeResourceCreateView.as_view(), name="some-resource-create", methods=["POST"]),
    # 详情、更新、删除
    path("some_resource/<int:pk>", SomeResourceRetrieveView.as_view(), name="some-resource-retrieve", methods=["GET"]),
    path("some_resource/<int:pk>", SomeResourceUpdateView.as_view(), name="some-resource-update", methods=["PUT", "PATCH"]),
    path("some_resource/<int:pk>", SomeResourceDeleteView.as_view(), name="some-resource-delete", methods=["DELETE"]),
]

这两种方案都能严格保持每个视图类的单一职责,同时实现同路由多方法的绑定需求。

内容的提问来源于stack exchange,提问作者Martin Faucheux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:45:25