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

使用@action装饰器时DRF出现DELETE方法不允许的问题

Problem Analysis

You’re facing a routing conflict because Django processes URL patterns in sequential order. Your two identical URL paths mean the first one always gets matched: when GET is first, DELETE requests hit a path only configured for GET (hence the "Method not allowed" error), and swapping order reverses which method works.

Solution

Combine both method mappings into a single URL path, and adjust your viewset for better alignment with DRF conventions.

Step 1: Fix URL Configuration

Replace the two separate path entries with one that maps both HTTP methods to their respective actions:

path('reporting/reports/<str:report_id>', ReportView.as_view({
    "get": "get_report",
    "delete": "delete_reports"
}), name="report_actions"),

Since your actions target a specific report by report_id, use detail=True in the @action decorator to signal a single-instance action. If report_id isn’t your model’s primary key, set lookup_field to match:

from rest_framework import viewsets

class ReportView(viewsets.ViewSet):
    lookup_field = "report_id"  # Match your model's identifier field

    @action(methods=["GET"], detail=True)
    def get_report(self, request, report_id=None):
        # Your GET logic here
        pass

    @action(methods=["DELETE"], detail=True)
    def delete_reports(self, request, report_id=None):
        # Your DELETE logic here
        pass

Alternative: Use Built-in ViewSet Methods

If your actions are just retrieving and deleting reports, skip custom actions and override DRF’s default methods:

class ReportView(viewsets.ModelViewSet):
    queryset = Report.objects.all()
    serializer_class = ReportSerializer
    lookup_field = "report_id"

    def retrieve(self, request, report_id=None):
        # Custom GET logic (or use super() for default behavior)
        return super().retrieve(request, report_id)

    def destroy(self, request, report_id=None):
        # Custom DELETE logic (or use super() for default behavior)
        return super().destroy(request, report_id)

Then simplify your URL path to map directly to these built-in methods:

path('reporting/reports/<str:report_id>', ReportView.as_view({
    "get": "retrieve",
    "delete": "destroy"
}), name="report_actions"),
Why This Works

Combining method mappings into one URL path lets Django route both GET and DELETE requests to their correct handlers without conflict. Using detail=True ensures your code follows DRF’s design patterns, making it more maintainable.

内容的提问来源于stack exchange,提问作者Pratik Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:02:55