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

使用Django Rest Framework的ModelSerializer仅序列化非空字段的方法

实现DRF ModelSerializer仅序列化非空字段的方案

原有修改__init__方案的问题说明

  • 序列化器的__init__方法仅在实例化时执行1次:如果传入的是查询集(many=True场景),序列化器的instance属性是整个查询集,而非单个模型实例,不会为每个实例单独初始化序列化器
  • 在__init__中删除字段会全局影响所有实例的序列化规则,无法针对单个实例的字段值动态调整,完全不符合需求

正确实现方案:重写to_representation方法

to_representation方法会在每个实例序列化时单独调用,是处理单个实例输出的最佳入口,可以完全复用原有ModelSerializer的字段配置,不需要单独定义每个字段。

基础通用版(仅过滤所有假值)

class NonEmptyFieldsModelSerializer(serializers.ModelSerializer):
    """仅序列化存在真值的字段的ModelSerializer基类"""
    def to_representation(self, instance):
        # 先获取默认的序列化结果
        ret = super().to_representation(instance)
        # 过滤掉所有值为假的字段(包括None、空字符串、空列表、0等)
        return {key: value for key, value in ret.items() if value}

适配0值十进制过滤的优化版

如果需要额外过滤值为0的十进制数(DRF默认转成字符串避免精度损失),可以使用调整后的版本,注意提前引入依赖的copy和re模块:

import copy
import re

class NonEmptySerializer(serializers.ModelSerializer):
    def to_representation(self, instance):
        ret = super().to_representation(instance)
        non_null_ret = copy.deepcopy(ret)
        for key in ret.keys():
            if not ret[key]:
                non_null_ret.pop(key)
            elif isinstance(ret[key], str) and re.fullmatch('[0.]+', ret[key]):
                # 匹配所有仅由0和.组成的字符串,即值为0的十进制转码结果
                non_null_ret.pop(key)
        return non_null_ret

使用方法

只需要让原有业务序列化器继承上述基类即可,其他代码不需要任何改动:

class OutfitSerializer(NonEmptySerializer):
  class Meta:
    model = Outfit
    fields = '__all__'

视图代码完全保持原有逻辑即可,自动适配单个实例和列表查询的场景。

可选调整说明

如果需要保留特定假值(比如布尔类型的False、合法数值0等),可以自行修改判断逻辑,例如仅过滤None和空字符串:

def to_representation(self, instance):
    ret = super().to_representation(instance)
    return {
        key: value for key, value in ret.items() 
        if value is not None and value != ""
    }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:24:06