如何在URL不携带<pk>时实现API删除?DRF浏览器无响应问题
问题原因及解决办法
DRF默认的Browsable API(自带网页调试界面)是为带主键的单资源详情接口设计的,它默认认为DELETE请求通过URL中的pk参数定位资源,不会自动给集合接口(比如api/barrel)的DELETE请求生成带请求体的输入表单。你点击删除按钮后,请求没有携带code字段,后端处理失败,而界面未给出明确反馈,所以看起来没反应。
下面提供两种可行的解决方法:
方法一:用序列化器让Browsable API自动生成表单
- 先创建一个仅用于删除验证的序列化器:
# serializers.py from rest_framework import serializers class BarrelDeleteSerializer(serializers.Serializer): code = serializers.CharField(required=True, help_text='需要删除的桶编号')
- 修改你的
BarrelAPIView,在DELETE方法中用这个序列化器验证请求体,同时让Browsable API识别该序列化器:
# views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import Barrel from .serializers import BarrelSerializer, BarrelDeleteSerializer class BarrelAPIView(APIView): def get(self, request): barrels = Barrel.objects.all() serializer = BarrelSerializer(barrels, many=True) return Response(serializer.data) def post(self, request): serializer = BarrelSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request): # 用删除专用序列化器验证请求体 serializer = BarrelDeleteSerializer(data=request.data) if not serializer.is_valid(): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) code = serializer.validated_data['code'] try: barrel = Barrel.objects.get(code=code) barrel.delete() return Response({'message': '删除成功'}, status=status.HTTP_204_NO_CONTENT) except Barrel.DoesNotExist: return Response({'error': '不存在该编号的桶'}, status=status.HTTP_404_NOT_FOUND) # 让Browsable API知道DELETE请求用哪个序列化器 def get_serializer(self, *args, **kwargs): if self.request.method == 'DELETE': return BarrelDeleteSerializer(*args, **kwargs) return super().get_serializer(*args, **kwargs)
修改完成后,在Browsable API中切换到DELETE方法时,界面会自动生成code字段的输入框,输入后提交就能正常触发删除逻辑。
方法二:自定义Browsable API模板添加表单
如果不想用序列化器,也可以直接修改界面模板:
- 在你的Django应用下创建模板目录
templates/rest_framework/,新建api.html文件:
{% extends "rest_framework/base.html" %} {% block content %} {{ block.super }} <!-- 为DELETE请求添加自定义表单 --> {% if request.method == 'DELETE' %} <div class="card mt-4"> <div class="card-header"> <h5>删除桶(通过编号)</h5> </div> <div class="card-body"> <form action="" method="post"> {% csrf_token %} <!-- 模拟DELETE请求 --> <input type="hidden" name="_method" value="DELETE"> <div class="form-group mb-3"> <label for="code" class="form-label">桶编号</label> <input type="text" name="code" id="code" class="form-control" required> </div> <button type="submit" class="btn btn-danger">执行删除</button> </form> </div> </div> {% endif %} {% endblock %}
- 在项目的
settings.py中配置DRF使用自定义模板:
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ], # 指定自定义模板路径 'TEMPLATE_DIRS': ['your_app/templates'], }
之后打开Browsable API切换到DELETE方法,就能看到自定义的删除表单,输入code后提交即可。
内容的提问来源于stack exchange,提问作者Wei Jian Tan
相关产品推荐
相关产品推荐

