序列化和反序列化

1.序列化Serialization

1.1 什么是序列化和反序列化?

将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例如将Django中的模型类对象装换为JSON字符串,这个转换过程我们称为序列化。

如:

  books = BookInfo.objects.all()
        # 2. 遍历查询集,取出每个书籍模型对象,把模型对象转换成字典
        # 定义一个列表变量用来保存所有字典
        print(books)
        book_list = []
        for book in books:
            book_dict = {
                'id': book.id,
                'pub_date': book.pub_date,
                'readcount': book.readcount,
                'commentcount': book.commentcount,
                'image': book.image.url if book.image else ''
            }
            book_list.append(book_dict)
        # 响应
        return JsonResponse(book_list, safe=False)

反之,将其他格式(字典、JSON、XML等)转换为程序中的数据,例如将JSON字符串转换为Django中的模型类对象,这个过程我们称为反序列化。

如:

       # 获取前端传入的请求体数据
        json_bytes = request.body
        # 把bytes类型的json字符串转换成json_str
        json_str = json_bytes.decode()
        # 将json字符串转换成字典
        book_dict = json.loads(json_str)

        # 创建模型对象并保存(把字典转换成模型并存储)
        book = BookInfo.objects.create(
            name=book_dict['name'],
            pub_date=book_dict['pub_date']
        )

我们可以看到,在开发REST API时,视图中要频繁的进行序列化与反序列化的编写。

总结

在开发REST API接口时,我们在视图中需要做的最核心的事是:

  • 将数据库数据序列化为前端所需要的格式,并返回;
  • 将前端发送的数据反序列化为模型类对象,并保存到数据库中。

1.2 序列化器的作用

1.对数据进行转换,序列化(输出、read_only)和反序列化(输入、write_only)

2.进行数据的校验,判断用户发送的数据是否合法,is_valid(raise_exception=True)

1.3 定义序列化

1.3.1 定义方法

Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。

例如,我们已有了一个数据库模型类BookInfo

class BookInfo(models.Model):
    # 属性名=属性类型(选项)
    name = models.CharField(max_length=10, verbose_name='名称')
    # 发布日期
    pub_date = models.DateField(verbose_name='发布日期', null=True)
    # 阅读量
    readcount = models.IntegerField(default=0, verbose_name='阅读量')
    # 评论量
    commentcount = models.IntegerField(default=0, verbose_name='评论量')
    # 逻辑删除
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    # 图片    必须设置默认值null=True
    image = models.ImageField(upload_to='book', verbose_name='图片')

我们想为这个模型类提供一个序列化器,可以定义如下:

class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True) # 表明该字段仅用于序列化输出,默认False
    name = serializers.CharField(label="名称", max_length=20)
    pub_date = serializers.DateField(label="发布日期", required=False) 表明该字段在反序列化时必须输入,默认True
    readcount = serializers.IntegerField(label="阅读量", required=False)
    commentcount = serializers.IntegerField(label="评论量", required=False)
    is_delete = serializers.BooleanField(label="逻辑删除", required=False)
    image = serializers.ImageField(label="图片", required=False)

注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。序列化的字段可以比模型的多或者少,但是一旦是对模型字段序列化,那么字段值要跟模型的一样

1.3.2 字段与选项
字段 字段构造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField UUIDField(format='hex_verbose') format: 1) 'hex_verbose'"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex'"5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressField IPAddressField(protocol='both', unpack_ipv4=False, **options)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices与Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

选项参数:

参数名称 作用
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最小值
min_value 最大值

通用参数:

参数名称 说明
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息

1.4 序列化使用

我们在django shell中来学习序列化器的使用。

python manage.py shell
1.4.1 基本使用

1) 先查询出一个图书对象

from book.models import BookInfo

book = BookInfo.objects.get(id=2)

2) 构造序列化器对象

from book.serializer import BookInfoSerializer

serializer = BookInfoSerializer(book)

3)获取序列化数据

通过data属性可以获取序列化后的数据

serializer.data
# {'id': 2, 'btitle': '天龙八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}

4)如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明

book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data
book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data
# [OrderedDict([('id', 2), ('btitle', '天龙八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bcomment', 40), ('image', N]), OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image'ne)]), OrderedDict([('id', 4), ('btitle', '雪山飞狐'), ('bpub_date', '1987-11-11'), ('bread', 58), ('bcomment', 24), ('ima None)]), OrderedDict([('id', 5), ('btitle', '西游记'), ('bpub_date', '1988-01-01'), ('bread', 10), ('bcomment', 10), ('im', 'booktest/xiyouji.png')])]
1.4.2 关联对象嵌套序列化

如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明。

例如,在定义英雄数据的序列化器时,外键book(即所属的图书)字段如何序列化?

我们先定义PeopleInfoSerialzier除外键字段外的其他部分

class PeopleInfoSerializer(serializers.ModelSerializer):
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    """人物数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名称', max_length=20)
    gender = serializers.IntegerField(label="性别", required=False)
    description = serializers.CharField(label="描述", required=False)
    is_delete = serializers.BooleanField(label="逻辑删除", required=False)

    class Meta:
        model = PeopleInfo
        fields = '__all__'

对于关联字段,可以采用以下几种方式:

1) PrimaryKeyRelatedField

此字段将被序列化为关联对象的主键。默认是将关联模型的id序列化

book = serializers.PrimaryKeyRelatedField(label='图书', read_only=True)
或
book = serializers.PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())

指明字段时需要包含read_only=True或者queryset参数:

  • 包含read_only=True参数时,该字段将不能用作反序列化使用
  • 包含queryset参数时,将被用作反序列化时参数校验使用

使用效果:

from book.serializer import PeopleInfoSerializer
from book.models import PeopleInfo
people = PeopleInfo.objects.get(id=6)
serializer = PeopleInfoSerializer(people)
serializer.data
#  {'id': 6, 'name': '乔峰', 'gender': 1, 'description': '降龙十八掌', 'is_delete': False, 'book': 2}  # book值为对应的id
1.4.3 StringRelatedField

此字段将被序列化为关联对象的字符串表示方式(即str方法的返回值)

hbook = serializers.StringRelatedField(label='图书')

使用效果

from book.serializer import PeopleInfoSerializer
from book.models import PeopleInfo
people = PeopleInfo.objects.get(id=6)
serializer = PeopleInfoSerializer(people)
serializer.data
 {'id': 6, 'name': '乔峰', 'gender': 1, 'description': '降龙十八掌', 'is_delete': False, 'book': '天龙八部'}  # book值为name
1.4.4 使用关联对象的序列化器

关联

# 序列化器()
hbook = BookInfoSerializer()

使用效果:

from book.serializer import PeopleInfoSerializer
from book.models import PeopleInfo
people = PeopleInfo.objects.get(id=6)
serializer = PeopleInfoSerializer(people)
serializer.data
#{'id': 6, 'name': '乔峰', 'gender': 1, 'description': '降龙十八掌', 'is_delete': False, 'book': OrderedDict([('id'
, 2), ('name', '天龙八部'), ('pub_date', '1986-07-24'), ('readcount', 36), ('commentcount', 40), ('is_delete', False), ('i
mage', '/book/timg_swWK9I8.jpg')])}

1.4.5 many参数

关联只能一个关联另一个,不能两个互相关联,所以在使用Book关联People时要把people对Book的关联去掉

如果关联的对象数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每个BookInfo对象关联的英雄HeroInfo对象可能有多个,此时关联字段类型的指明仍可使用上述几种方式,只是在声明关联字段时,多补充一个many=True参数即可。

此处仅拿PrimaryKeyRelatedField类型来举例,其他相同。注意字段命名为关联对象名_set

在BookInfoSerializer中添加关联字段:

class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label="名称", max_length=20)
    pub_date = serializers.DateField(label="发布日期", required=False)
    readcount = serializers.IntegerField(label="阅读量", required=False)
    commentcount = serializers.IntegerField(label="评论量", required=False)
    is_delete = serializers.BooleanField(label="逻辑删除", required=False)
    image = serializers.ImageField(label="图片", required=False)
    peopleinfo_set = serializers.PrimaryKeyRelatedField(many=True) # 新增

使用效果:

from book.serializer import BookInfoSerializer
from book.models import BookInfo
people = BookInfo.objects.get(id=2)
serializer = BookInfoSerializer(people)
serializer.data
# {'id': 2, 'name': '天龙八部', 'pub_date': '1986-07-24', 'readcount': 36, 'commentcount': 40, 'is_delete': False, 'image': '/book/timg_swWK9I8.jpg'}

书籍对象关联人物信息(一个对多个)

class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label="名称", max_length=20)
    pub_date = serializers.DateField(label="发布日期", required=False)
    readcount = serializers.IntegerField(label="阅读量", required=False)
    commentcount = serializers.IntegerField(label="评论量", required=False)
    is_delete = serializers.BooleanField(label="逻辑删除", required=False)
    image = serializers.ImageField(label="图片", required=False)
    # peopleinfo_set = serializers.PrimaryKeyRelatedField(many=True)
    peopleinfo_set = PeopleInfoSerializer(many=True)

使用效果:

from books.serializer import BookInfoserializer

from books.models import BookInfo
people = BookInfo.objects.get(id=2)
serializer = BookInfoSerializer(people)
serializer.data
#  {'id': 2, 'name': '天龙八部', 'pub_date': '1986-07-24', 'readcount': 36, 'commentcount': 40, 'is_delete': False, '
image': '/book/timg_swWK9I8.jpg', 'peopleinfo_set': [OrderedDict([('id', 6), ('name', '乔峰'), ('gender', 1), ('descriptio
n', '降龙十八掌'), ('is_delete', False)]), OrderedDict([('id', 7), ('name', '段誉'), ('gender', 1), ('description', '六脉
神剑'), ('is_delete', False)]), OrderedDict([('id', 8), ('name', '虚竹'), ('gender', 1), ('description', '天山六阳掌'), ('
is_delete', False)]), OrderedDict([('id', 9), ('name', '王语嫣'), ('gender', 0), ('description', '神仙姐姐'), ('is_delete'
, False)])]}

1.5 序列化步骤总结

序列化:将模型转挽成json数据 。序列化器的类应该单独创建一个serializers.py

1.定义序列化器类(模型名/类视图名 Serializer)招承 Serializer

2.定义序列化性中的字段参照模型(序列优暮中的字段可以比模型多或少如果表示是模型中的字段在序列

社中这个字段名应读和模型中字段名一致

3.如果在多的一方里面则关联序列化(外健) ,如果是在一的一方里面关联序列化多(多的一方模型名小写_set)

4.如果在一的一方关联序列化多时,需要指定关联字段 many=True

5.将要序列化模型或查询集传给序列化器类的instance,参数如果传的是查询集多指定many=Ture

6.获取序列化后的数据 序 列化器对象.data属性

序列化只是单纯的转字典

2.反序列化

2.1 验证

使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。

在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。

验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。

验证成功,可以通过序列化器对象的validated_data属性获取数据。

在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。

如我们前面定义过的BookInfoSerializer

class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label="名称", max_length=20)
    pub_date = serializers.DateField(label="发布日期", required=False)
    readcount = serializers.IntegerField(label="阅读量", required=False)
    commentcount = serializers.IntegerField(label="评论量", required=False)
    is_delete = serializers.BooleanField(label="逻辑删除", required=False)
    image = serializers.ImageField(label="图片", required=False)

通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证

from booktest.serializers import BookInfoSerializer
data = {'pub_date':'2021-1-20'}
serializer = BookInfoSerializer(data=data)  # 序列化对象
serializer.is_valid()  # 返回False   # 调用序列化器的校验方法 True或False
serializer.errors    # 获取校验的错误信息
#  {'name': [ErrorDetail(string='该字段是必填项。', code='required')]}
serializer.validated_data  # {}  # 获取反序列化校验后的数据还是字典

data = {'name': 'python'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid()  # True
serializer.errors  # {}
serializer.validated_data  #  OrderedDict([('name', '天龙八部')])

is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。

# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True) # raise_exception=True如果多指定这个,将来校验出错后,会自动抛出错误信息
from booktest.serializers import BookInfoSerializer
data = {'pub_date':'2021-1-20'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid(raise_exception=True)   # Return a 400 response if the data was invalid.
#---------------------------------------------------------------------------
#ValidationError                           Traceback (most recent call last)
#<ipython-input-17-55b906b95aaf> in <module>
#----> 1 serializer.is_valid(raise_exception=True)

#~\AppData\Local\Programs\Python\Python37\lib\site-packages\rest_framework\serializers.py in is_valid(self, raise_exception
#)
#    226
#    227         if self._errors and raise_exception:
#--> 228             raise ValidationError(self.errors)
#    229
#    230         return not bool(self._errors)

#ValidationError: {'name': [ErrorDetail(string='该字段是必填项。', code='required')]}

serializer.errors
#  {'name': [ErrorDetail(string='该字段是必填项。', code='required')]}
serializer.validated_data  # {}

2.2 保存

如果在验证成功后,想要基于validated_data完成数据对象的创建,可以通过实现create()和update()两个方法来实现。

    def create(self, validated_data):
        """新建"""
        book = BookInfo(**validated_data)
        return book

    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例"""
        instance.name = validated_data.get('name', instance.name)
        instance.pub_date = validated_data.get('pub_date', instance.pub_date)
        instance.readcount = validated_data.get('readcount', instance.readcount)
        instance.commentcount = validated_data.get('commentcount', instance.commentcount)
        return instance

如果需要在返回数据对象的时候,也将数据保存到数据库中,则可以进行如下修改

    def create(self, validated_data):
        # 添加到模型类--从而实现保存
        book = BookInfo(**validated_data)
        book.save()
        return book

    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例"""
        instance.name = validated_data.get('name', instance.name)
        instance.pub_date = validated_data.get('pub_date', instance.pub_date)
        instance.readcount = validated_data.get('readcount', instance.readcount)
        instance.commentcount = validated_data.get('commentcount', instance.commentcount)
        instance.save()  # 加个save方法
        return instance

实现了上述两个方法后,在反序列化数据的时候,就可以通过save()方法返回一个数据对象实例了

book = serializer.save()

如果创建序列化器对象的时候,没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,则调用save()方法的时候,update()被调用。

>>> from users.serializers import BookInfoSerializer
>>> data = {"name":"hualong","pub_date":"2023-06-26"}
>>> ser = BookInfoSerializer(data=data)
>>> ser.is_valid()
True
>>> ser.validated_data
OrderedDict([('name', 'hualong'), ('pub_date', datetime.date(2023, 6, 26))])
>>> ser.create(ser.validated_data)
<BookInfo: hualong>


>>> from users.models import BookInfo
>>> book = BookInfo.objects.get(id=10)
>>> book
data = {"name":"西游记后传"}
>>> ser = BookInfoSerializer(data=data)
>>> ser.is_valid()
True
>>> book
<BookInfo: 西游记后传>
>>> ser.validated_data
OrderedDict([('name', '西游记后传2')])
>>> ser.update(book, ser.validated_data)
<BookInfo: 西游记后传2>

两点说明:

1) 在对序列化器进行save()保存时,可以额外传递数据,这些数据可以在create()和update()中的validated_data参数获取到

serializer.save(owner=request.user)

2)默认序列化器必须传递所有required的字段,否则会抛出验证异常。但是我们可以使用partial参数来允许部分字段更新

# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)

2.3 反序列化步骤总结

反序列化:拿到前端传入的数据—>序列化器的data一>调用序列化器的.is_valid()方法进行校验—>调用序列化器的.save()方法
1.获取前端传入的json字典数据
⒉创建序列化器给序列化器的data参数传参(要以关键字方式传递)
3.调用序列化器的.is_valid(raise_exception=True)进行校验,如果校验出错会自动抛出错误信息

4.调用序列化器的.save()方法,调用save时会判断当初始创建序列化器时是否传入的instance
5.如果传了instance也传了data那么调用save实际调用序列化器中的update方法反之就是调用序列化器中的create方法

反序列化最后会自动帮你完成序列化

3.模型类序列化器ModelSerializer

如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。ModelSerializer继承自Serializer

ModelSerializer与常规的Serializer相同,但它提供了:

  • ModelSerializer可以根据模型自动生成序列化器中的字段
  • ModelSerializer里面已经帮我们实现了create()方法和update()方法
  • ModelSerializer自动为Serializer生成validators,比如unique_together

3.1 定义

比如我们创建一个BookInfoSerializer

class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        fields = '__all__'
  • model 指明参照哪个模型类
  • fields 指明为模型类的哪些字段生成

我们可以在python manage.py shell中查看自动生成的BookInfoSerializer的具体实现

 from book.serializer import BookInfoSerializer
 serializer = BookInfoSerializer()
 serializer
# BookInfoSerializer():
#     id = IntegerField(label='ID', read_only=True)
#     name = CharField(label='名称', max_length=10)
#     pub_date = DateField(allow_null=True, label='发布日期', required=False)
#     readcount = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
#     commentcount = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
#     is_delete = BooleanField(label='逻辑删除', required=False)
#     image = ImageField(label='图片', max_length=100)   
    

3.2 指定字段

  1. 使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        fields = ('id', 'name', 'pub_date')

效果演示:

 from book.serializer import BookInfoSerializer
 serializer = BookInfoSerializer()
 serializer
# BookInfoSerializer():
#     id = IntegerField(label='ID', read_only=True)
#     name = CharField(label='名称', max_length=10)
#     pub_date = DateField(allow_null=True, label='发布日期', required=False)   
  1. 使用exclude可以明确排除掉哪些字段
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        exclude = ('image',) # 注意单个字段,后面还要加个逗号

效果演示:

 from book.serializer import BookInfoSerializer
 serializer = BookInfoSerializer()
 serializer
# BookInfoSerializer():
#     id = IntegerField(label='ID', read_only=True)
#     name = CharField(label='名称', max_length=10)
#     pub_date = DateField(allow_null=True, label='发布日期', required=False)
#     readcount = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
#     commentcount = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
#     is_delete = BooleanField(label='逻辑删除', required=False) # 注意:这里没有image
  1. 默认ModelSerializer使用主键作为关联字段,但是我们可以使用depth来简单的生成嵌套表示,depth应该是整数,表明嵌套的层级数量。如:
class HeroInfoSerializer2(serializers.ModelSerializer):
    class Meta:
        model = HeroInfo
        fields = '__all__'
        depth = 1

形成的序列化器如下:

from book.serializer import PeopleInfoSerializer
serializer = PeopleInfoSerializer()
serialize
# PeopleInfoSerializer():
#     id = IntegerField(label='ID', read_only=True)
#     name = CharField(label='名称', max_length=20)
#     gender = ChoiceField(choices=((0, 'male'), (1, 'female')), label='性别', required=False, validators=[<django.core.vali
# dators.MinValueValidator object>, <django.core.validators.MaxValueValidator object>])
#     description = CharField(allow_null=True, label='描述信息', max_length=200, required=False)
#     is_delete = BooleanField(label='逻辑删除', required=False)
#     book = NestedSerializer(read_only=True):
#         id = IntegerField(label='ID', read_only=True)
#         name = CharField(label='名称', max_length=10)
#         pub_date = DateField(allow_null=True, label='发布日期', required=False)
#         readcount = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
#         commentcount = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
#         is_delete = BooleanField(label='逻辑删除', required=False)
#         image = ImageField(label='图片', max_length=100)

  1. 指明只读字段

可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段

class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
        class Meta:
        model = BookInfo
        fields = ('id', 'name', 'pub_date')
        read_only_fields = ('id', 'name')

效果演示:

 from book.serializer import BookInfoSerializer
 serializer = BookInfoSerializer()
 serializer
# BookInfoSerializer():
#     id = IntegerField(label='ID', read_only=True)
#     name = CharField(label='名称', read_only=True)
#     pub_date = DateField(allow_null=True, label='发布日期', required=False)

3.2.3 添加额外参数

我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数

class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
     class Meta:
        model = BookInfo
        fields = ('id', 'name', 'pub_date', 'readcount', 'commentcount')
        extra_kwargs = {
            'readcount': {'min_value': 0, 'required': True},
            'commentcount': {'min_value': 0, 'required': True},
        }

效果演示:

 from book.serializer import BookInfoSerializer
 serializer = BookInfoSerializer()
 serializer
 # BookInfoSerializer():
#     id = IntegerField(label='ID', read_only=True)
#     name = CharField(label='名称', max_length=10)
#     pub_date = DateField(allow_null=True, label='发布日期', required=False)
#     readcount = IntegerField(label='阅读量', max_value=2147483647, min_value=0, required=True)    
#     commentcount = IntegerField(label='评论量', max_value=2147483647, min_value=0, required=True)
   注意,readcount和commentcount的参数指修改了
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容