REST framework入坑(5)-模型类序列化器
如果想为Django存在的模型类快速创建序列化器,可以使用DRF框架封装好的
ModelSerializer
模型类序列化器来帮助我们快速创建一个Serializer类
- 基于模型类的字段条件创建约束
- 自动生成序列化器(serializer)
- 内部已经封装了
create
与update
方法,序列化器对象在调用save()方法时,会自动对数据库进行操作
1. 基础定义¶
# 继承自serializers.ModelSerializer
class StudentInfoSerializer(serializers.ModelSerializer)
class Meta:
model = StudentInfo # 指定要依据的模型类
fields = '__all__' # 设置全部字段自动生成
2. 自定义过滤字段¶
- 使用fields来明确字段, 可以写明具体哪些字段
# 继承自serializers.ModelSerializer
class StudentInfoSerializer(serializers.ModelSerializer)
class Meta:
model = StudentInfo # 指定要依据的模型类
fields = ['id', 'name'] # 列表中设置指定要生成的字段
- 使用exclude可以明确排除掉哪些字段
# 继承自serializers.ModelSerializer
class StudentInfoSerializer(serializers.ModelSerializer)
class Meta:
model = StudentInfo # 指定要依据的模型类
exclude = ['info'] # 指定哪些字段不需要自动生成
- 可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段
# 继承自serializers.ModelSerializer
class StudentInfoSerializer(serializers.ModelSerializer)
class Meta:
model = StudentInfo # 指定要依据的模型类
fields = '__all__' # 自定生成全部字段
ead_only_fields = ['id', 'name'] # 指定列表中的字段仅用于序列化操作
3. 添加额外约束¶
extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
# 继承自serializers.ModelSerializer
class StudentInfoSerializer(serializers.ModelSerializer)
class Meta:
model = StudentInfo # 指定要依据的模型类
fields = '__all__' # 设置全部字段自动生成
extra_kwargs = {
name: { # 给name字段设置额外的约束
'min_value': 0, # 设置最小的长度
'required': True # 设置是否必传
}
info: { # 同上
'min_value': 0,
'required': True
}
}
4. 使用SerializerMethodField 优化¶
- 数据用例
# 班级模型类
class ClassInfo(models.Model):
name = models.CharField(max_length=20, verbose_name='班级名称')
Info = models.CharField(max_length=20, verbose_name='班级信息')
class Meta:
db_table = 'class'
def __str__(self):
return self.name
# 学生模型类
class StudentInfo(models.Model):
name = models.CharField(max_length=20, verbose_name='姓名')
clsinfo = models.ForeignKey(ClassInfo, related_name='cls_stu)
class Meta:
db_table = 'student'
def __str__(self):
return self.name
- 那么在 Django REST framework 我们通常按下面的方式定义 Serializer 类. 在 ClassInfo 类中增加一个属性 cls_stu(student外键到class的别名) 来保存当前 class 对象所有的学生集合. 但是此时有个问题如果此 Class 对象所拥有的 Student 比较多, 此时就会影响性能. 比如:
# 班级序列化器
class ClassSerializer(serializers.ModelSerializer):
cls_stu = serializers.PrimaryKeyRelatedField(many=True, required=False, read_only=True)
class Meta:
model = Article
fields = ('id', 'name', 'info', 'cls_stu')
# 学生序列化器
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'name', 'clsinfo')
- 但是这样会出现一个问题: 这样序列化 Class 对象的时候会把 所有与 Class 对象关联的 student 对象的也序列化起来,就算是我们用 IntegerField 或者 StringRelatedField 那也会序列化很多用户的信息
- 其实在很多时候我们并不需要在查询 Class 对象的时候查询所拥有的 Student 对象,很多时候我们只是需要一个 Class 所拥有 Student 对象的总数就可以了,如果有需要再去查询 Student 列表详细。此时我们就可以使用 Django REST framework 提供的 SerializerMethodField 来实现这个目的
# 班级序列化器
class ClassSerializer(serializers.ModelSerializer):
get_cls_stu_count = serializers.SerializerMethodField()
class Meta:
model = Article
fields = ('id', 'name', 'info', 'get_cls_stu_count')
def get_cls_stu_count(self, obj):
return obj.cls_stu.all().count()
# 学生序列化器
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'name', 'clsinfo')
- 首先在 ClassSerializer 中去除 cls_stu 属性
- 然后在 ClassSerializer 中增加一个属性 get_cls_stu_count, 并把这个属性添加到 Meta 的 fields 列表里
- 添加一个 get_cls_stu_count 方法,这个方法的命名规则就是在上面声明的属性前面加上个 'get_' 前缀,并接受一个 obj 参数,这个 obj 参数就是当前的 ClassInfo 对象实例。