序列化器
序列化器(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)常用字段类型
| 字段类型 | 说明 |
|---|---|
CharField | 字符串,支持 max_length、min_length |
IntegerField | 整数,支持 max_value、min_value |
FloatField | 浮点数 |
DecimalField | 定点数,需指定 max_digits、decimal_places |
BooleanField | 布尔值 |
DateField | 日期(YYYY-MM-DD) |
DateTimeField | 日期时间 |
EmailField | 邮箱,自动格式校验 |
URLField | URL,自动格式校验 |
UUIDField | UUID |
ChoiceField | 枚举,需传入 choices |
ListField | 列表,需指定子字段 child |
DictField | 字典,需指定子字段 child |
SerializerMethodField | 只读计算字段,通过 get_<field_name> 方法返回值 |
字段通用参数
| 参数 | 默认值 | 说明 |
|---|---|---|
read_only | False | 仅用于序列化输出,反序列化时忽略 |
write_only | False | 仅用于反序列化输入,序列化输出时隐藏 |
required | True | 反序列化时是否必须提供 |
default | — | 未提供时的默认值 |
allow_null | False | 是否允许传入 null/None |
allow_blank | False | 是否允许空字符串(仅 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 # 必须返回 data3. 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 dataGenericAPIView 及其子类时,get_serializer() 方法会自动将 request、view、format 注入 context,无需手动传入。Serializer vs ModelSerializer
| 对比项 | Serializer | ModelSerializer |
|---|---|---|
| 字段声明 | 手动逐个声明 | 从模型自动生成 |
create/update | 需自行实现 | 内置默认实现 |
| 适用场景 | 非模型数据、高度定制化接口 | 标准 CRUD,与模型字段高度吻合 |
| 代码量 | 较多 | 少,快速开发 |
大多数标准 CRUD 接口选择 ModelSerializer;当序列化的数据来自多个模型或需要复杂字段计算时,选择 Serializer。