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

使用DRF Serializer填充Django模型字段时出现非空错误排查

DRF序列化时出现"This field may not be null"错误的排查与解决

尝试通过DRF Serializer将数据填充到Django模型的DecimalField和CharField字段时,触发了奇怪的"This field may not be null"错误,以下是相关代码及报错信息:

模型定义

class Product(BaseModel):
    product = models.CharField(max_length=255)
    recommended_action = models.CharField(max_length=255)
    recommended_action_value = models.DecimalField(max_digits=12, decimal_places=8)
    recommended_price = models.DecimalField(max_digits=12, decimal_places=8)
    rrp = models.DecimalField(max_digits=12, decimal_places=8)
    iam_price = models.DecimalField(max_digits=12, decimal_places=8)
    iam_index = models.DecimalField(max_digits=12, decimal_places=8)
    factor = models.DecimalField(max_digits=12, decimal_places=8)
    avg_in_stock = models.DecimalField(
        null=True, blank=True, max_digits=12, decimal_places=8
    )

序列化器定义

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product
        fields = "__all__"

视图代码

@api_view(['POST'])
def migrate_data(request, *args, **kwargs):
    if request.method == "POST":
        data = json.loads(request.body)
        product_serialized_data = serializers.ProductSerializer(
            data=data,
            many=True,
            context={"request": request},
        )
        if not product_serialized_data.is_valid():
            print(product_serialized_data.errors)
    product_serialized_data.save()
    return Response(data={"detail": "Success"})

请求数据

{
    "product": "DE_Ford_2095160",
    "recommended_action": "increase",
    "recommended_action_value": 0.0315553,
    "recommended_price": 14.5862,
    "rrp": 14.14,
    "iam_price": 6.56898,
    "iam_index": 0.464567,
    "factor": 2.15254,
    "avg_in_stock": 1
}

报错信息

[
    {
        'recommended_action': [ErrorDetail(string='This field may not be null.', code='null')],
        'recommended_action_value': [ErrorDetail(string='This field may not be null.', code='null')],
        'recommended_price': [ErrorDetail(string='This field may not be null.', code='null')],
        'rrp': [ErrorDetail(string='This field may not be null.', code='null')],
        'iam_index': [ErrorDetail(string='This field may not be null.', code='null')],
        'factor': [ErrorDetail(string='This field may not be null.', code='null')]
    }
]

问题原因及修复方案

1. many=True 与请求数据格式不匹配

序列化器中设置了many=True,表示要处理数组格式的批量数据,但实际请求发送的是单个对象。DRF会错误地将单个对象的每个键解析为数组元素,导致所有字段被识别为null。

修复:

  • 如果是单条数据,直接移除many=True参数;
  • 如果需要批量处理,请求数据需改为数组格式,示例:
    [
        {
            "product": "DE_Ford_2095160",
            // 其他字段...
        }
    ]
    

2. 不必要的json.loads(request.body)

DRF的request.data已经自动完成了请求体的解析工作,不需要手动调用json.loads。手动解析可能因请求头(如Content-Type)处理逻辑冲突导致数据异常,直接使用request.data即可。

3. 视图逻辑漏洞

  • product_serialized_data.save()写在了if request.method == "POST"代码块外部,非POST请求会直接触发变量未定义错误;
  • 即使验证不通过,代码依然执行save(),会导致无效数据尝试入库。

修复后的视图代码:

from rest_framework import status

@api_view(['POST'])
def migrate_data(request, *args, **kwargs):
    product_serialized_data = serializers.ProductSerializer(
        data=request.data,
        # 根据实际需求决定是否保留many=True
        # many=True,
        context={"request": request},
    )
    if product_serialized_data.is_valid():
        product_serialized_data.save()
        return Response(data={"detail": "Success"})
    # 验证失败时返回错误信息
    return Response(product_serialized_data.errors, status=status.HTTP_400_BAD_REQUEST)

4. 可选:Decimal字段精度保障

如果请求中传递的是浮点数,存入DecimalField可能存在精度丢失风险,可在序列化器中显式指定字段类型,确保转换逻辑正确:

class ProductSerializer(serializers.ModelSerializer):
    recommended_action_value = serializers.DecimalField(max_digits=12, decimal_places=8)
    recommended_price = serializers.DecimalField(max_digits=12, decimal_places=8)
    # 其他Decimal字段同理
    class Meta:
        model = models.Product
        fields = "__all__"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:01:00