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

如何在DRF中发送DELETE请求体并实现带过滤的批量删除

解决DRF中批量删除仅允许过滤后查询集的问题

嘿,我来帮你搞定这个批量删除的需求!既然你已经在用django-rest-framework-bulk的BulkModelViewSet,那咱们只需要在视图里加一层校验逻辑,确保只有过滤后的数据集才能被批量删除,不能直接删全表。

第一步:确保依赖正确安装配置

首先确认你已经装了库,并且加到了项目配置里:

pip install django-rest-framework-bulk

然后在settings.py的INSTALLED_APPS中添加:

INSTALLED_APPS = [
    # ... 其他应用
    'rest_framework_bulk',
]

第二步:自定义BulkModelViewSet,添加校验逻辑

核心思路是重写bulk_destroy方法,先拿到过滤后的查询集,再判断是否是全量数据,拒绝无过滤的批量删除。这里分两种常见场景处理:

场景1:通过URL参数过滤后删除(比如按team过滤)

这种情况下,前端不需要传请求体,只需要通过URL参数过滤,然后发送DELETE请求:

from rest_framework_bulk import BulkModelViewSet
from rest_framework.response import Response
from rest_framework import status
from rest_framework.filters import DjangoFilterBackend, SearchFilter
from .models import Hero  # 换成你的模型
from .serializers import HeroSerializer  # 换成你的序列化器

class HeroBulkViewSet(BulkModelViewSet):
    queryset = Hero.objects.all()
    serializer_class = HeroSerializer
    # 配置过滤后端,允许按字段过滤或搜索
    filter_backends = [DjangoFilterBackend, SearchFilter]
    filterset_fields = ['team']  # 允许按team过滤
    search_fields = ['first_name', 'second_name']  # 支持模糊搜索

    def bulk_destroy(self, request, *args, **kwargs):
        # 获取经过URL参数过滤后的查询集
        filtered_queryset = self.filter_queryset(self.get_queryset())

        # 校验:如果过滤后的查询集等于全量数据,说明没有加过滤条件,拒绝删除
        if filtered_queryset.count() == Hero.objects.count():
            return Response(
                {"detail": "批量删除仅支持过滤后的数据集,禁止删除全部数据!"},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # 执行批量删除
        self.perform_bulk_destroy(filtered_queryset)
        return Response(status=status.HTTP_204_NO_CONTENT)

场景2:通过DELETE请求体传ID列表删除(同时支持URL过滤)

如果你的需求是前端通过请求体传要删除的ID数组(比如你提供的JSON格式),那可以调整逻辑,同时校验请求体的ID和URL过滤条件:

def bulk_destroy(self, request, *args, **kwargs):
    # 从请求体中提取要删除的ID列表
    delete_ids = [item.get('id') for item in request.data]
    if not delete_ids:
        return Response(
            {"detail": "请提供要删除的记录ID列表!"},
            status=status.HTTP_400_BAD_REQUEST
        )
    
    # 先应用URL过滤条件,再筛选出请求体中的ID
    filtered_queryset = self.filter_queryset(self.get_queryset()).filter(id__in=delete_ids)

    # 校验:如果要删除的是全量数据,拒绝操作
    if filtered_queryset.count() == Hero.objects.count():
        return Response(
            {"detail": "批量删除仅支持过滤后的数据集,禁止删除全部数据!"},
            status=status.HTTP_403_FORBIDDEN
        )
    
    self.perform_bulk_destroy(filtered_queryset)
    return Response(status=status.HTTP_204_NO_CONTENT)

第三步:序列化器配置

确保你的序列化器包含id字段,这样前端能正确传参:

from rest_framework import serializers
from .models import Hero

class HeroSerializer(serializers.ModelSerializer):
    class Meta:
        model = Hero
        fields = ['id', 'first_name', 'second_name', 'team']

测试示例

比如前端可以这样请求:

  • 按team过滤后删除:发送DELETE /heroes/?team=avengers
  • 传ID列表删除:发送DELETE /heroes/,请求体为[{"id": "1"}, {"id": "2"}]

如果用户尝试直接删除全量数据(比如不带任何过滤参数,或者请求体包含所有ID),会返回403禁止访问。

内容的提问来源于stack exchange,提问作者Vasu Gaur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:17:35