跳至内容

序列化器

序列化器(Serializer)是 DRF 的核心组件,承担两个方向的数据转换:将模型对象转为 JSON(序列化),以及将客户端提交的 JSON 校验并还原为模型对象(反序列化)。DRF 提供了两种序列化器:手动声明字段的 Serializer 和自动映射模型的 ModelSerializer

Serializer 基础

定义序列化器

所有序列化器都继承自 rest_framework.serializers.Serializer。字段声明与 Django Form 类似,每个字段对应一种数据类型:

from rest_framework import serializers

class StudentSerializer(serializers.Serializer):
    id          = serializers.IntegerField(read_only=True)
    name        = serializers.CharField(max_length=100)
    age         = serializers.IntegerField(min_value=0, max_value=150)
    sex         = serializers.BooleanField(default=True)
    description = serializers.CharField(required=False, allow_blank=True)
序列化器与数据库模型解耦,可以为任意 Python 对象(包括非 ORM 数据)定义序列化器。

常用字段类型

字段类型说明
CharField字符串,支持 max_lengthmin_length
IntegerField整数,支持 max_valuemin_value
FloatField浮点数
DecimalField定点数,需指定 max_digitsdecimal_places
BooleanField布尔值
DateField日期(YYYY-MM-DD
DateTimeField日期时间
EmailField邮箱,自动格式校验
URLFieldURL,自动格式校验
UUIDFieldUUID
ChoiceField枚举,需传入 choices
ListField列表,需指定子字段 child
DictField字典,需指定子字段 child
SerializerMethodField只读计算字段,通过 get_<field_name> 方法返回值

字段通用参数

参数默认值说明
read_onlyFalse仅用于序列化输出,反序列化时忽略
write_onlyFalse仅用于反序列化输入,序列化输出时隐藏
requiredTrue反序列化时是否必须提供
default未提供时的默认值
allow_nullFalse是否允许传入 null/None
allow_blankFalse是否允许空字符串(仅 CharField)
validators[]额外验证函数列表
error_messages自定义错误信息字典
label可视化界面中显示的字段名
help_text可视化界面中显示的帮助提示

序列化(模型 → JSON)

序列化单个对象

from students.models import Student
from .serializers import StudentSerializer

student = Student.objects.get(pk=1)
serializer = StudentSerializer(instance=student)
print(serializer.data)
# {'id': 1, 'name': '张三', 'age': 20, 'sex': True, 'description': '...'}

在视图中返回:

from django.views import View
from django.http import JsonResponse
from students.models import Student
from .serializers import StudentSerializer

class StudentView(View):
    def get(self, request, pk):
        student = Student.objects.get(pk=pk)
        serializer = StudentSerializer(instance=student)
        return JsonResponse(serializer.data)

序列化多个对象

当数据源是 QuerySet 时,传入 many=True

students = Student.objects.all()
serializer = StudentSerializer(instance=students, many=True)
# serializer.data 是一个列表
return JsonResponse(serializer.data, safe=False)

SerializerMethodField 示例

用于在输出中附加计算字段:

class StudentSerializer(serializers.Serializer):
    id   = serializers.IntegerField(read_only=True)
    name = serializers.CharField()
    age  = serializers.IntegerField()
    # 计算字段:根据 age 判断是否成年
    is_adult = serializers.SerializerMethodField()

    def get_is_adult(self, obj):
        return obj.age >= 18

反序列化(JSON → 模型)

数据验证

反序列化流程:接收客户端数据 → 实例化序列化器(传入 data)→ 调用 is_valid() → 获取 validated_data

data = {
    "name": "李四",
    "age": 22,
    "sex": True,
    "description": "测试用户",
}
serializer = StudentSerializer(data=data)

if serializer.is_valid():
    print(serializer.validated_data)  # OrderedDict,包含校验通过的数据
else:
    print(serializer.errors)          # 包含字段错误的字典

验证失败时直接抛出 HTTP 400:

serializer.is_valid(raise_exception=True)

自定义验证(钩子)

DRF 提供三种扩展验证的方式,优先级从高到低依次执行:

1. 字段级钩子 validate_<field_name>

class StudentSerializer(serializers.Serializer):
    name = serializers.CharField()

    def validate_name(self, value):
        if value == "admin":
            raise serializers.ValidationError("用户名不能是 admin")
        return value  # 必须返回校验后的值

2. 全局钩子 validate

用于跨字段联合验证:

def validate(self, data):
    if data.get("age", 0) < 18 and data.get("sex") is False:
        raise serializers.ValidationError("未成年女性不允许注册")
    return data  # 必须返回 data

3. validators 函数

在字段上附加独立的验证函数,便于复用:

def check_age(value):
    if value == 0:
        raise serializers.ValidationError("年龄不能为 0")
    return value

class StudentSerializer(serializers.Serializer):
    age = serializers.IntegerField(validators=[check_age])

保存数据(create / update)

调用 serializer.save() 时,DRF 根据是否传入 instance 自动分发到 create()update() 方法,需要在序列化器中实现这两个方法:

class StudentSerializer(serializers.Serializer):
    id          = serializers.IntegerField(read_only=True)
    name        = serializers.CharField(required=True, max_length=100)
    age         = serializers.IntegerField(min_value=0, max_value=150)
    sex         = serializers.BooleanField(default=True)
    description = serializers.CharField(required=False, allow_blank=True)

    def create(self, validated_data):
        return Student.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.name        = validated_data.get("name", instance.name)
        instance.age         = validated_data.get("age", instance.age)
        instance.sex         = validated_data.get("sex", instance.sex)
        instance.description = validated_data.get("description", instance.description)
        instance.save()
        return instance

在视图中使用:

# 创建(不传 instance)
serializer = StudentSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
student = serializer.save()   # 调用 create()

# 更新(传入 instance)
student = Student.objects.get(pk=pk)
serializer = StudentSerializer(instance=student, data=request.data)
serializer.is_valid(raise_exception=True)
student = serializer.save()   # 调用 update()

# 部分更新(PATCH)
serializer = StudentSerializer(instance=student, data=request.data, partial=True)

save() 还可以传入额外数据,会合并到 validated_data 中:

serializer.save(created_by=request.user)

ModelSerializer

ModelSerializer 继承自 Serializer,根据模型类自动生成字段,并内置 create()update() 实现,极大减少样板代码。

基本定义

from rest_framework import serializers
from .models import Student

class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model  = Student
        fields = "__all__"   # 包含所有模型字段

Meta 配置项

class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model  = Student

        # 方式一:列出需要的字段
        fields = ["id", "name", "age", "sex", "description"]

        # 方式二:排除指定字段(与 fields 互斥,不能同时使用)
        # exclude = ["description"]

        # 只读字段列表(等效于对每个字段设置 read_only=True)
        read_only_fields = ("id",)

        # 为字段添加/覆盖选项参数
        extra_kwargs = {
            "sex":         {"write_only": True},
            "description": {"required": False, "allow_blank": True},
        }

扩展额外字段

ModelSerializer 同样支持声明额外字段(声明后必须在 fields 中列出):

class StudentModelSerializer(serializers.ModelSerializer):
    full_label = serializers.SerializerMethodField()

    class Meta:
        model  = Student
        fields = ["id", "name", "age", "sex", "full_label"]

    def get_full_label(self, obj):
        return f"{obj.name}{obj.class_null}班)"

传递额外上下文

有时需要在序列化器内访问 request、当前用户等信息。在视图中通过 context 传入,序列化器内通过 self.context 获取:

# 视图层
serializer = StudentModelSerializer(
    instance=student,
    context={"request": request, "project_id": 42}
)

# 序列化器内
class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model  = Student
        fields = "__all__"

    def validate(self, data):
        request = self.context.get("request")
        if not request.user.is_staff:
            raise serializers.ValidationError("无权限操作")
        return data
使用 GenericAPIView 及其子类时,get_serializer() 方法会自动将 requestviewformat 注入 context,无需手动传入。

Serializer vs ModelSerializer

对比项SerializerModelSerializer
字段声明手动逐个声明从模型自动生成
create/update需自行实现内置默认实现
适用场景非模型数据、高度定制化接口标准 CRUD,与模型字段高度吻合
代码量较多少,快速开发

大多数标准 CRUD 接口选择 ModelSerializer;当序列化的数据来自多个模型或需要复杂字段计算时,选择 Serializer

最后更新于