相关文档

  • DRF - Django Rest Framework
  • Django - Django 框架

204 状态码的一个邪门坑

问题现象

今天调删除接口,踩了一个非常邪门的坑。

后端用的 Django ModelViewSet,删除接口写得好好的,用 Postman 测试也能看到返回:

{
  "data": null,
  "result": true,
  "code": 0,
  "message": "OK"
}

结果前端 axios 怎么拿都拿不到响应体,如果前端判断删除成功是响应体中的某个参数的话,就会导致实际删除成功,但是前端显示删除失败

(我拿 post 调接口的写的接口文档给前端,导致前端用响应体判断删除是否成功。)

问题代码

from rest_framework import viewsets
from rest_framework.renderers import JSONRenderer
from .serializers import YourSerializer
 
class YourViewSet(viewsets.ModelViewSet):
    serializer_class = YourSerializer
    renderer_classes = [JSONRenderer]  # 就是这行导致的

ModelViewSet 的 destroy 方法默认返回 204 No Content。

根本原因

客户端对 204 响应体的处理
Postman不遵循 HTTP 规范,能显示响应体
浏览器 fetch/axios严格遵循 HTTP 规范,丢弃 204 响应体

简单说:

  • Postman:看到了返回,以为自己写对了
  • 前端:根本拿不到,傻傻不知道

解决方案

方案一:重写 destroy,返回 200

from rest_framework import status
from rest_framework.response import Response
 
class YourViewSet(viewsets.ModelViewSet):
    serializer_class = YourSerializer
 
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(
            {"message": "删除成功", "result": True},
            status=status.HTTP_200_OK
        )

方案二:用 @action 包装删除

from rest_framework.decorators import action
 
class YourViewSet(viewsets.ModelViewSet):
    serializer_class = YourSerializer
    renderer_classes = [JSONRenderer]
 
    @action(detail=True, methods=['delete'])
    def delete(self, request, pk=None):
        instance = self.get_object()
        instance.delete()
        return Response(
            {"message": "删除成功", "result": True},
            status=status.HTTP_200_OK
        )

教训

  1. Postman 测试通过不代表前端能用 — Postman 不按 HTTP 规范来
  2. 204 状态码按规范就是不能有响应体 — 浏览器会丢弃

2026-03-10 踩坑记录

相关文档

  • DRF - Django Rest Framework
  • Django - Django 框架