从入门到"精通"Django REST Framework-(三)
一. 什么是 ModelSerializer?
ModelSerializer 是 Django REST Framework(DRF)提供的一个序列化器,它用于简化与 Django 模型的交互。ModelSerializer 通过自动读取 Django 模型的字段,生成对应的序列化字段,从而简化了手动编写字段的工作。它继承自 serializers.Serializer,但不同的是,它专门用于处理与 Django ORM 模型的数据交互。
二. 为什么要使用 ModelSerializer
- 简化代码:
ModelSerializer通过自动从 Django 模型生成字段,避免了手动逐一定义每个字段的重复代码。它大大简化了序列化器的编写工作。 - 自动化操作:
ModelSerializer提供了默认的create()和update()方法,这些方法会自动根据模型的数据进行创建和更新。这意味着你不需要手动编写这些方法,减少了出错的概率。 - 与 Django ORM 紧密集成:
ModelSerializer与 Django 的 ORM 数据模型集成非常紧密,能够直接操作 Django 数据库模型,并且支持字段验证和嵌套序列化。自动继承 Model 的字段约束(如 max_length, null, unique 等)。 - 提高开发效率: 使用
ModelSerializer,开发人员无需手动定义字段和验证器,也无需重写create()和update()方法,适合标准的 CRUD 操作,提升开发效率。
三. 基础用法
ModelSerializer 是为 Django 模型专门设计的序列化器,下面是基础的使用方法。
1. 定义 Django 模型
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
isbn_number = models.CharField(max_length=13)
2. 创建 ModelSerializer
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book # 指定模型
fields = '__all__' # 包含所有字段
3. 使用ModelSerializer来序列化数据
# 进行数据的序列化
book = Book.objects.first()
serializer = BookSerializer(book)
print(serializer.data) # 输出序列化后的数据
四. 核心配置 Meta 类详解
ModelSerializer 中最重要的部分是 Meta 类,以下是 Meta 类常见字段及其用法。
1. model
- 作用:指定要与序列化器关联的 Django 模型。
- 示例
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
2. fields
- 作用:指定需要序列化的字段,可以是一个字段列表,或者
'__all__',表示包含所有字段。 - 示例
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'author'] # 只序列化 title 和 author 字段
3. exclude
- 作用:排除不需要序列化的字段,不能与
fields一起使用。 - 示例
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
exclude = ['isbn_number'] # 排除 isbn_number 字段
4. read_only_fields
- 作用:指定只读字段,这些字段不能被更新或创建。
- 示例
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
read_only_fields = ['isbn_number', 'published_date']
5. write_only_fields
- 作用:指定只写字段,不能通过序列化器读取这些字段。
- 示例
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
write_only_fields = ['password'] # 仅用于写入
6. depth
- 作用:指定嵌套序列化的深度。如果模型之间存在外键关系,可以设置
depth来控制递归序列化的深度。 - 示例
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
depth = 1 # 递归序列化嵌套对象(如外键)
7. validators
- 作用:为模型或字段指定验证器,进行自定义验证。
- 示例
def validate_title(value):
if 'banned' in value:
raise serializers.ValidationError("Title contains banned words.")
return value
class BookSerializer(serializers.ModelSerializer):
title = serializers.CharField(validators=[validate_title])
class Meta:
model = Book
fields = ['title', 'author']
五. 高级技巧
嵌套序列化
对于有外键关系的模型,可以使用嵌套序列化器进行序列化。例如,如果 Book 模型有一个指向 Author 模型的外键,可以在 BookSerializer 中嵌套 AuthorSerializer。
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['name']
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer()
class Meta:
model = Book
fields = ['title', 'author']
自定义 create() 和 update() 方法
如果需要自定义创建和更新逻辑,可以重写 create() 和 update() 方法。
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
def create(self, validated_data):
# 自定义创建逻辑
return Book.objects.create(**validated_data)
def update(self, instance, validated_data):
# 自定义更新逻辑
instance.title = validated_data.get('title', instance.title)
instance.save()
return instance
批量更新
如果需要批量更新数据,可以通过序列化器的 update() 方法配合 many=True 来实现。
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
# 更新逻辑
六. 常见问题
如何处理外键和多对多关系的序列化?
使用嵌套的 ModelSerializer 来处理外键关系(ForeignKey),可以通过 depth 或者手动嵌套序列化器来实现多对多关系。
如何排除模型中的某些字段?
使用 exclude 来排除不需要序列化的字段。
如何验证一个字段?
通过定义 validate_<field_name> 方法来为字段添加自定义验证逻辑。
如何让字段只读?
使用 read_only_fields 在 Meta 类中标记字段为只读。
七. 生产技巧
1.性能优化
- 对于大数据量的序列化,尽量避免使用深度过大的嵌套序列化,可以使用
depth控制递归深度,或者使用自定义嵌套序列化器来减少不必要的嵌套。 - 使用
select_related和prefetch_related预加载外键和多对多关系,避免 N+1 查询问题。
2.使用 ModelSerializer 优化 API 性能:
- 在处理批量数据时,尽量批量创建或更新数据(例如使用
bulk_create和bulk_update)。 - 对于常用字段,可以通过缓存优化性能。
批量创建数据
from rest_framework import serializers
from django.db import transaction
class ProductBulkSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['name', 'price', 'category']
@transaction.atomic
def create(self, validated_data):
# 原生批量创建(跳过 ModelSerializer 的单个创建逻辑)
objs = [Product(**item) for item in validated_data]
return Product.objects.bulk_create(objs)
# 使用方式
data = [{'name': 'A', 'price':10}, {'name':'B', 'price':20}]
serializer = ProductBulkSerializer(data=data, many=True)
serializer.is_valid(raise_exception=True)
serializer.save()
批量更新数据
class ProductBulkUpdateSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=True)
class Meta:
model = Product
fields = ['id', 'price', 'stock']
def update(self, instance, validated_data):
# 原生批量更新(需配合视图逻辑)
update_objs = []
for item in validated_data:
obj = Product.objects.get(id=item['id'])
obj.price = item['price']
update_objs.append(obj)
Product.objects.bulk_update(update_objs, ['price'])
return update_objs
3.动态修改字段required属性
- POST请求:需要提供所有字段的值
- PATCH请求:动态修改字段属性,允许只更新需要修改的字段
from rest_framework import serializers
class DynamicRequiredFieldsMixin:
def get_fields(self):
fields = super().get_fields()
request = self.context.get('request', None)
# 仅当请求方法为 PATCH 时调整必填性
if request and request.method in ['PATCH']:
for field_name, field in fields.items():
field.required = False # 所有字段变为可选
field.allow_null = True # 允许传入 null(可选)
return fields
# 使用示例
class ProductSerializer(DynamicRequiredFieldsMixin, serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
关键原理剖析
- Hook 机制
- 通过重写
get_fields()方法,在序列化器初始化时动态修改字段属性 - 执行顺序:
get_fields()→ 字段实例化 → 验证逻辑
- 通过重写
- 请求上下文获取
- 从
self.context['request']获取当前请求对象 - 需确保视图将
request传递到序列化器上下文中(通常自动处理)
- 从
- 字段属性动态修改
| 属性 | 作用 | 示例值 |
|---|---|---|
| required | 控制字段是否必须传入 | False |
| allow_null | 允许接收 null 值(需数据库允许) |
True |
每天进步一点点

浙公网安备 33010602011771号