关于常规的Serializer使用方法,可以参考 常规的Serializer讲解
如果我们需要使用的序列化器,是对应Django的模型类,那么,DRF已经为我们提供了ModelSerializer模型类序列化器,可以满足我们的需求,快速创建一个Serializer类。
ModelSerializer和普通Serializer的区别:
①:基于模型类自动生成一系列字段;
②:基于模型类自动为Serializer生成validators,比如unique_together;
③:包含默认的create()和update()的实现。
现在,我们就从实际的操作中来看一下ModelSerializer,应该如何使用。
本文代码实现前提:我已经在子应用的models.py文件中定义了几个模型类
# 定义图书模型类BookInfo
class BookInfo(models.Model):
btitle = models.CharField(max_length=20, verbose_name='名称')
bpub_date = models.DateField(verbose_name='发布日期')
bread = models.IntegerField(default=0, verbose_name='阅读量')
bcomment = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
image = models.ImageField(upload_to='booktest', verbose_name='图片', null=True)
def __str__(self):
"""定义每个数据对象的显示信息"""
return self.btitle
#定义英雄模型类HeroInfo
class HeroInfo(models.Model):
GENDER_CHOICES = (
(0, 'male'),
(1, 'female')
)
hname = models.CharField(max_length=20, verbose_name='名称')
hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息')
hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
def __str__(self):
return self.hname
一·定义
我们现在对于BookInfo,创建一个序列化器
class BookInfoModelSerializer(serializers.ModelSerializer):
class Meta:
# 指明关联的模型类
model = BookInfo
# 指明返回的字段
fields = "__all__"
我们现在对于HeroInfo,创建一个序列化器
class HeroInfoModelSerializer(serializers.ModelSerializer):
class Meta:
model = HeroInfo
fields = '__all__'
申明:
- model 指明参照哪个模型类
- fields 指明为模型类的哪些字段生成
前面我们介绍了ModelSerializer的一个特性就是,可以根据模型类来决定创建的序列化器会有哪些字段,为了验证,我们可以看一下序列化器在不传参的情况下,是什么样的:
In [3]: s = BookInfoModelSerializer()
In [4]: s
Out[4]:
BookInfoModelSerializer():
id = IntegerField(label='ID', read_only=True)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(label='发布日期')
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
is_delete = BooleanField(label='逻辑删除', required=False)
image = ImageField(allow_null=True, label='图片', max_length=100, required=False)
由此可见,ModelSerializer确实可以满足我们的需求,而不需要我们把字段一个一个进行手敲了。
字段的指定
(1)fields
上面我在代码中也标注了,fields可以指定我们定义的序列化器拥有的字段;__all__
是默认包含原模型类的所有字段;当然了,我们也是可以写明我们具体需要哪些字段:
class BookInfoModelSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date')
(2)exclude
exclude的作用是可以排除哪些字段不可以用
class BookInfoModelSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
exclude = ('image',)
注意:exclude和fields在一个序列化器中,只能存在一个,不然会报错的。
(3)关联字段处理
ModelSerializer会默认使用主键作为关联字段,如下:
hbook = PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())
我们可以通过 depth
来简单的设置嵌套模式:
现在将HeroInfo序列化器改成这样:
class HeroInfoModelSerializer(serializers.ModelSerializer):
class Meta:
model = HeroInfo
fields = '__all__'
depth = 1
然后我们的外键hbook就变成这样了:
hbook = NestedSerializer(read_only=True):
id = IntegerField(label='ID', read_only=True)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(label='发布日期')
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
is_delete = BooleanField(label='逻辑删除', required=False)
image = ImageField(allow_null=True, label='图片', max_length=100, required=False)
注意:depth应该是整数,表明嵌套的层级数量。
(4)显示指名字段–包括关联字段的设置
参考代码:
class HeroInfoModelSerializer(serializers.ModelSerializer):
hbook = BookInfoModelSerializer()
class Meta:
model = HeroInfo
fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook'
注意,如果想设置指名的字段,并且指名的字段包括关联字段,而且关联字段想通过自己设置,比如这里的hbook = BookInfoModelSerializer()
, 那么,我们必须要在fields中写上这个关联字段,不能以为外面写了关联字段,里面可以不写,那是不行的。
(5)read_only_fields
指名只读字段,用于序列化的输出
class BookInfoModelSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
read_only_fields = ('id', 'bread', 'bcomment')
序列化器的额外参数的传递
extra_kwargs参数可以添加或修改ModelSerializer原有的选项参数;
比如在上面的代码中,我们有一个阅读量和评论的数据的最小值,默认是负数min_value=-2147483648,
,这肯定是不合理的,所以就需要修改。
在BookInfoModelSerializer 中添加 extra_kwargs这个参数,并把想要修改的选项参数进行修改或者增加就可以了。
extra_kwargs = {
'bread': {'min_value': 0, 'required': True},
'bcomment': {'min_value': 0, 'required': True},
}
修改后的数据如下:
In [3]: s = BookInfoModelSerializer()
In [4]: s
Out[4]:
BookInfoModelSerializer():
id = IntegerField(label='ID', read_only=True)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(label='发布日期')
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=0, required=True)
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=0, required=True)
is_delete = BooleanField(label='逻辑删除', required=False)
image = ImageField(allow_null=True, label='图片', max_length=100, required=False)