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
相关产品推荐
相关产品推荐

