Django序列化器
什么是序列化器(Serializer)?
序列化器是 DRF 中用于:
| 功能 | 描述 |
|---|---|
| 序列化 | 将模型对象转换为 JSON,返回给前端 |
| 反序列化 | 将前端传来的 JSON 数据转换为模型对象 |
| 校验 | 自动校验字段类型、必填项、格式等 |
| 字段控制 | 控制哪些字段可读、可写、只读、隐藏等 |
一、序列化流程图解(对象 → JSON)
模型对象 / QuerySet↓
初始化序列化器(传入 instance)↓
调用 .data → 触发 to_representation()↓
遍历字段:├─ 普通字段 → 字段.to_representation(obj.field)├─ SerializerMethodField → get_<field>(obj)├─ 嵌套序列化器 → 子序列化器.to_representation()└─ source 映射字段 → 取值后序列化↓
返回 JSON 数据(OrderedDict)
✅ 可扩展点:
-
重写
to_representation(self, instance):自定义输出结构 -
使用
SerializerMethodField:动态字段、格式化展示 -
嵌套序列化器:展示关联对象详情(如角色、权限)
二、反序列化流程图解(JSON → 模型)
前端提交 JSON 数据↓
初始化序列化器(传入 data + context)↓
调用 .is_valid()↓
字段级校验:├─ 字段类型转换(CharField, IntegerField 等)├─ validate_<field>(value)└─ validators(如 UniqueValidator、自定义校验器)↓
对象级校验:└─ validate(self, attrs)↓
调用 .save()├─ create(validated_data)(用于 POST)└─ update(instance, validated_data)(用于 PUT/PATCH)↓
写入数据库,返回模型对象
✅ 可扩展点:
-
validate_<field>(self, value):字段级校验 -
validate(self, attrs):对象级联合校验 -
create()/update():处理嵌套写入、逻辑外键、多对多中间表等 -
context['request']:用于获取当前用户、租户、IP 等上下文信息
一、基础使用:ModelSerializer
from rest_framework import serializers
from .models import Userclass UserSerializer(serializers.ModelSerializer):class Meta:model = Userfields = ['id', 'username', 'email', 'status']
用法示例:
# 序列化(对象 → JSON)
user = User.objects.get(id=1)
serializer = UserSerializer(user)
print(serializer.data)# 反序列化(JSON → 对象)
data = {'username': 'tom', 'email': 'tom@example.com', 'status': 1}
serializer = UserSerializer(data=data)
if serializer.is_valid():serializer.save()
二、自定义字段
字段属性控制
| 属性 | 描述 |
|---|---|
read_only=True | 只读字段,前端不能提交 |
write_only=True | 仅写字段,序列化时不输出 |
required=True | 必填字段 |
default=value | 默认值,可为函数如 timezone.now |
allow_null=True | 允许为 null |
添加只读字段、隐藏字段、默认值
class UserSerializer(serializers.ModelSerializer):status = serializers.IntegerField(default=1)creator_id = serializers.IntegerField(write_only=True)create_time = serializers.DateTimeField(read_only=True)class Meta:model = Userfields = '__all__'
自定义字段的几种方式
1. SerializerMethodField(只读字段)
用于展示模型中不存在的字段,或需要计算/拼接的字段:
class UserSerializer(serializers.ModelSerializer):display_name = serializers.SerializerMethodField()def get_display_name(self, obj):return obj.real_name or obj.usernameclass Meta:model = Userfields = ['id', 'username', 'real_name', 'display_name']
适合格式化输出、拼接字段、反查字段(如角色列表、部门名称)
2. source 映射字段
用于将序列化字段映射到模型中的其他字段或属性:
real_name = serializers.CharField(source='profile.real_name')
适合跨模型字段、属性方法、嵌套字段简化
3. 自定义字段类型
你可以直接使用 CharField, IntegerField, BooleanField 等,并设置属性:
status = serializers.IntegerField(default=1, required=False, help_text='状态(0禁用,1启用)')
可控制默认值、是否必填、提示信息等
| 能力 | 技术点 | 企业价值 |
|---|---|---|
| 自定义字段 | SerializerMethodField, source | 提升输出语义、格式化展示 |
三、校验逻辑详解
1. 字段级校验:validate_<field_name>
用于校验单个字段的值:
def validate_username(self, value):if 'admin' in value:raise serializers.ValidationError("用户名不能包含 'admin'")return value
适合格式限制、敏感词过滤、唯一性校验等
2. 对象级校验:validate(self, attrs)
用于多个字段之间的联合校验:
def validate(self, attrs):if attrs['status'] == 0 and not attrs.get('email'):raise serializers.ValidationError("禁用用户必须填写邮箱")return attrs
适合状态联动、条件判断、业务规则校验
3. 自定义校验器类(推荐企业项目使用)
from rest_framework.validators import ValidationErrordef validate_phone(value):if not value.startswith('1'):raise ValidationError("手机号必须以 1 开头")
然后在字段中使用:
phone = serializers.CharField(validators=[validate_phone])
可复用、集中管理、便于测试
4. 字段行为控制:extra_kwargs(隐性校验器)
extra_kwargs 是 ModelSerializer.Meta 中的配置项,用于控制字段的行为,从而影响校验流程:
class UserSerializer(serializers.ModelSerializer):class Meta:model = Userfields = ['username', 'email', 'password']extra_kwargs = {'password': {'write_only': True},'email': {'required': False,'allow_null': True,'error_messages': {'required': '邮箱不能为空','invalid': '邮箱格式不正确'}}}
| 配置项 | 说明 |
|---|---|
required | 是否为必填字段(默认 True) |
allow_null | 是否允许为 null |
default | 设置默认值 |
read_only | 设置为只读字段,前端无法提交 |
write_only | 设置为只写字段,响应中不返回 |
error_messages | 自定义错误提示,支持国际化 |
适合快速控制字段行为,避免显式声明字段,提升序列化器的简洁性和可维护性。
能力对照表(含 extra_kwargs)
| 能力 | 技术点 | 企业价值 |
|---|---|---|
| 字段级校验 | validate_<field>() | 控制字段合法性 |
| 对象级校验 | validate(self, attrs) | 实现业务规则 |
| 校验器复用 | 自定义函数或类 | 提升可维护性、集中管理 |
| 字段行为控制 | extra_kwargs | 控制字段是否必填、只读、默认值、提示 |
多种校验方式共同使用时的执行顺序
当你调用 .is_valid() 时,DRF 会按以下顺序执行校验逻辑:
1. extra_kwargs → 预处理字段行为(如 required, default, allow_null)
2. 字段类型转换(CharField, IntegerField 等)
3. 字段 validators(如 UniqueValidator、自定义校验器函数)
4. 字段级校验:validate_<field_name>()
5. 对象级校验:validate(self, attrs)
✅ 注意:如果前面某一层校验失败,后续校验将不会执行。
四、嵌套序列化与多对多处理
一、嵌套序列化器的用途和类型
嵌套序列化器是指在一个序列化器中嵌入另一个序列化器,用于处理关联模型字段。
用途场景
| 类型 | 示例字段 | 描述 |
|---|---|---|
| 一对多 | User → Department | 用户所属部门 |
| 多对多 | User → Roles | 用户拥有多个角色 |
| 反查字段 | Role → Users | 角色下的用户列表 |
| 逻辑外键反查 | Permission → Menu | 权限关联菜单 |
二、只读嵌套序列化器(展示用)
适用于展示关联对象详情,但不支持写入:
class RoleSerializer(serializers.ModelSerializer):class Meta:model = Rolefields = ['id', 'name']class UserSerializer(serializers.ModelSerializer):roles = serializers.SerializerMethodField()def get_roles(self, obj):role_ids = UserRole.objects.filter(user_id=obj.id).values_list('role_id', flat=True)roles = Role.objects.filter(id__in=role_ids)return RoleSerializer(roles, many=True).dataclass Meta:model = Userfields = ['id', 'username', 'roles']
适合逻辑外键结构,手动反查并嵌套序列化器输出
三、可写嵌套序列化器(创建/更新用)
适用于前端提交嵌套结构时写入关联关系:
class RoleInputSerializer(serializers.ModelSerializer):class Meta:model = Rolefields = ['id']class UserCreateSerializer(serializers.ModelSerializer):roles = RoleInputSerializer(many=True)class Meta:model = Userfields = ['username', 'email', 'roles']def create(self, validated_data):roles_data = validated_data.pop('roles')user = User.objects.create(**validated_data)for role in roles_data:UserRole.objects.create(user_id=user.id, role_id=role['id'])return user
适合多对多逻辑外键结构,手动处理中间表写入
四、自动多对多处理(仅适用于 ManyToManyField)
如果你使用 Django 原生的 ManyToManyField,DRF 可以自动处理嵌套写入:
class User(models.Model):roles = models.ManyToManyField(Role, through='UserRole')class UserSerializer(serializers.ModelSerializer):class Meta:model = Userfields = ['id', 'username', 'roles']
⚠️ 你当前使用的是逻辑外键结构(
UserRole中间表),所以需要手动处理嵌套写入
五、企业项目中的最佳实践
| 场景 | 推荐做法 |
|---|---|
| ✅ 展示嵌套字段 | 使用 SerializerMethodField + 子序列化器封装 |
| ✅ 写入嵌套字段 | 使用输入序列化器 + 重写 create() / update() |
| ✅ 多对多逻辑外键 | 手动维护中间表(如 UserRole, RolePermission) |
| ✅ 字段权限控制 | 使用 read_only, write_only, required 控制嵌套字段行为 |
| ✅ 分离输入输出序列化器 | UserCreateSerializer, UserDetailSerializer 分开定义,职责清晰 |
总结:序列化器的核心价值
| 能力 | 说明 |
|---|---|
| 数据转换 | 模型对象 ↔ JSON |
| 数据校验 | 自动校验字段类型、格式、必填项 |
| 字段控制 | 控制哪些字段可读、可写、只读、隐藏等 |
| 嵌套结构 | 支持嵌套模型、反查字段、自定义字段 |
| 企业级扩展 | 支持权限控制、字段映射、动态字段、字段级别权限等 |
