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

Django REST自定义字段校验函数无法返回400响应的修复方案

解决Django REST中自定义校验函数无法返回400响应的问题

你遇到的问题很典型——你的check_field函数确实生成了错误响应,但你只是调用了它,却没有把函数返回的响应作为视图的返回值返回,所以视图会继续执行后面的代码,不会中断请求流程。

问题根源

当你调用check_field(phone)时,函数内部判断字段为空后会返回一个JsonResponse对象,但这个返回值并没有被你的pay视图接收并返回给客户端。视图会忽略这个返回值,继续执行后续的校验逻辑,自然达不到提前返回错误的效果。

修复方案一:完善函数调用逻辑

首先,我们需要修改check_field函数,让它能接收字段名称(不然字段为空时会显示None field is empty,这不太友好),然后在视图中接收函数的返回值,若存在则直接返回:

  1. 修改check_field函数:
def check_field(field_value, field_name):
    if not field_value:
        logger.info('its work')
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': '{} field is empty'.format(field_name)
            },
        })
  1. 在视图中调用并处理返回值:
def pay(request):
    body = request.body.decode('utf-8')
    if not body:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': 'empty query'
            },
        })
    body = json.loads(body)
    phone = body.get('phone')
    amount = body.get('amount')
    merch_name = body.get('merchant_name')

    # 逐个检查字段,若函数返回响应则直接返回给客户端
    error_response = check_field(phone, 'phone')
    if error_response:
        return error_response
    
    error_response = check_field(amount, 'amount')
    if error_response:
        return error_response
    
    error_response = check_field(merch_name, 'merchant_name')
    if error_response:
        return error_response

    # 后续支付逻辑继续执行...

修复方案二:用异常处理简化代码

如果觉得逐个判断返回值太繁琐,可以用自定义异常来实现更简洁的逻辑:

  1. 定义自定义异常类:
class RequiredFieldEmpty(Exception):
    def __init__(self, field_name):
        self.field_name = field_name
  1. 修改check_field函数抛出异常:
def check_field(field_value, field_name):
    if not field_value:
        logger.info('its work')
        raise RequiredFieldEmpty(field_name)
  1. 在视图中捕获异常并返回响应:
def pay(request):
    body = request.body.decode('utf-8')
    if not body:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': 'empty query'
            },
        })
    body = json.loads(body)
    phone = body.get('phone')
    amount = body.get('amount')
    merch_name = body.get('merchant_name')

    try:
        check_field(phone, 'phone')
        check_field(amount, 'amount')
        check_field(merch_name, 'merchant_name')
    except RequiredFieldEmpty as e:
        return JsonResponse({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': '{} field is empty'.format(e.field_name)
            },
        })

    # 后续支付逻辑继续执行...

更规范的优化建议:使用DRF序列化器

既然你在用Django REST Framework,其实最规范的做法是用序列化器来处理字段校验,它不仅能帮你处理必填项检查,还能支持字段类型、格式等更多校验场景,代码也更简洁:

from rest_framework import serializers
from rest_framework.response import Response
from rest_framework.decorators import api_view

# 定义序列化器,指定必填字段和自定义错误信息
class PaymentSerializer(serializers.Serializer):
    phone = serializers.CharField(required=True, error_messages={'required': 'phone field is empty'})
    amount = serializers.CharField(required=True, error_messages={'required': 'amount field is empty'})
    merchant_name = serializers.CharField(required=True, error_messages={'required': 'merchant_name field is empty'})

@api_view(['POST'])
def pay(request):
    # 用请求数据初始化序列化器
    serializer = PaymentSerializer(data=request.data)
    
    # 执行校验,不通过则返回错误响应
    if not serializer.is_valid():
        # 提取第一个错误信息返回(也可以返回所有错误)
        first_error = next(iter(serializer.errors.values()))[0]
        return Response({
            'status': 'failed',
            'errors': {
                'code': 400,
                'message': first_error
            }
        }, status=400)
    
    # 校验通过后,直接获取清理后的合法数据
    validated_data = serializer.validated_data
    phone = validated_data['phone']
    amount = validated_data['amount']
    merch_name = validated_data['merchant_name']

    # 后续支付逻辑继续执行...

这种方式完全避免了重复的校验代码,而且符合DRF的最佳实践,维护起来更方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:45:14