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

DRF中设置django_filters双字段必填条件并自定义空查询错误提示

解决DRF中django_filters的强制双参数过滤及空结果自定义响应问题

问题分析

当前代码允许单独传入ref_code触发过滤,不符合“必须同时输入ref_code和expecting_time才能查询”的要求;同时空结果的判断逻辑有误(queryset永远不会为None),无法正确返回自定义提示。以下是针对性的修改方案:

1. 修改FilterSet,添加参数校验

在filters.py中为AppointmentFilter添加全局校验逻辑,根据需求选择以下两种方案之一:

方案A:允许不传参数(返回全部数据),但禁止只传其中一个

import django_filters
from django_filters import ValidationError
from myappointment.models import AppointmentData

class AppointmentFilter(django_filters.FilterSet):
    
    class Meta:
        model = AppointmentData
        fields =['ref_code', 'expecting_time']

    def clean(self):
        cleaned_data = super().clean()
        ref_code = cleaned_data.get('ref_code')
        expecting_time = cleaned_data.get('expecting_time')
        
        # 仅当其中一个参数存在时,校验另一个是否也存在
        has_ref = ref_code is not None
        has_time = expecting_time is not None
        if has_ref != has_time:
            raise ValidationError("必须同时输入ref_code和expecting_time两个参数,或都不输入")
        return cleaned_data

方案B:强制要求必须同时传入两个参数(不传或只传一个都报错)

import django_filters
from django_filters import ValidationError
from myappointment.models import AppointmentData

class AppointmentFilter(django_filters.FilterSet):
    
    class Meta:
        model = AppointmentData
        fields =['ref_code', 'expecting_time']

    def clean(self):
        cleaned_data = super().clean()
        ref_code = cleaned_data.get('ref_code')
        expecting_time = cleaned_data.get('expecting_time')
        
        if not (ref_code is not None and expecting_time is not None):
            raise ValidationError("必须同时提供ref_code和expecting_time参数才能进行查询")
        return cleaned_data

2. 修改API视图,修复空结果判断及响应逻辑

在api.py中调整过滤后的结果判断,同时处理过滤校验失败的情况:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from myappointment.models import AppointmentData
from myappointment.filters import AppointmentFilter
from myappointment.serializers import AppointmentDataSerializer

@api_view(['GET'])
def AllAppointmentData(request):
    queryset = AppointmentData.objects.all()
    filterset = AppointmentFilter(request.GET, queryset=queryset)

    if filterset.is_valid():
        queryset = filterset.qs
        # 检查查询结果是否为空
        if queryset.exists():
            serializer = AppointmentDataSerializer(queryset, many=True)
            return Response(serializer.data)
        else:
            # 返回自定义空结果提示
            return Response(
                {"message": "未找到匹配的预约数据"},
                status=status.HTTP_200_OK
            )
    else:
        # 返回参数校验错误信息
        return Response(filterset.errors, status=status.HTTP_400_BAD_REQUEST)

关键修改说明

  • 参数校验:通过FilterSet的clean方法实现全局参数校验,确保符合“双参数同时触发查询”的要求。
  • 空结果判断:用queryset.exists()替代原有的queryset is not None,因为空的QuerySet仍然是有效的对象,不会为None。
  • 响应规范:空结果返回200状态码(请求成功但无数据),参数错误返回400状态码(请求不符合要求),符合RESTful规范。

内容的提问来源于stack exchange,提问作者Couone Technology

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:17:39