自定义序列化器(序列化操作)——两个方向,三种形式(对应三种方案实现)

1、自定义序列化器:

  • (1)、定义一个BookInfo模型类的序列化器 —— 用来序列化/反序列化操作BookInfo模型类对象的
  • (2)、通过定义和模型类“同名类属性、类型一一对应”的形式,来指定参与序列化的字段
  • (3)、模型类隐藏字段也可以映射 —— 只要模型类有的字段都可以映射

新建一个serializers.py文件

from rest_framework import serializers
# serializers.Serializer: 该类,是所有自定义序列化器的基类

# 1、定义一个BookInfo模型类的序列化器 —— 用来序列化/反序列化操作BookInfo模型类对象的
class BookInfoSerializer(serializers.Serializer):
    # 2、通过定义和模型类“同名类属性、类型一一对应”的形式,来指定参与序列化的字段
    # 该指定,决定了序列化结果(字典)有哪些字段
    # 3、模型类隐藏字段也可以映射 —— 只要模型类有的字段都可以映射
    id = serializers.IntegerField()
    btitle = serializers.CharField()
    bpub_date = serializers.DateField()
    bread = serializers.IntegerField()
    bcomment = serializers.IntegerField()
    is_delete = serializers.BooleanField()
    image = serializers.ImageField()

2、标准序列化操作流程

  • (1)、获取目标数据(一个or多个模型类对象)
    • 单一对象:book = BookInfo.objects.get(pk=1)
    • 多个对象:books = BookInfo.objects.all()
  • (2)、实例化序列化器对象
    • 单一对象序列化的时候:bs = BookInfoSerializer(instance=book)
    • 多个对象序列化的时候:bs = BookInfoSerializer(instance=books, many=True)
      • many=True表示序列化操作传入的instance是一个查询集(多个对象)
  • (3)、序列化结果
    • 单一对象序列化结果(dict): bs.data
    • 多个对象序列化结果(OrderedDict): bs.data(注:OrderedDict是特殊的字典,操作和普通字典一样)
      序列化单一对象实例:
>>> from books_test.serializers import*
>>> from books_test.models import*
>>> book = BookInfo.objects.get(pk=1)
>>> bs = BookInfoSerializer(instance=book)
>>> bs.data
{'id': 1, 'bpub_date': '1980-05-01', 'image': None, 'btitle': '射雕英雄传', 'bcomment': 34, 'is_delete': False, 'bread': 100}
>>> 

3、如何序列化其他的隐藏字段呢?
3.1、前置条件 ——models.py模型类定义:
# related_name定义一个主表隐藏字段为heros代表从表英雄多个对象

#定义图书模型类BookInfo
class BookInfo(models.Model):
    # .....
    # heros隐藏字段,代表与当前书本(主表)关联的多个英雄(从表)模型类对象
		# .....

    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.btitle

#定义英雄模型类HeroInfo
class HeroInfo(models.Model):
    # .....
    # hbook代表与当前英雄(从表)关联的单一的书本(主表)对象
    # related_name定义一个主表隐藏字段为heros代表从表英雄多个对象
    hbook = models.ForeignKey(BookInfo, related_name='heros',on_delete=models.CASCADE, verbose_name='图书')  # 外键
		# .....

    def __str__(self):
        return self.hname

方向一:序列化主表数据,的时候,顺带着序列化关联的的从表多个数据;
3.2、编辑自定义序列器serializers.py(加上隐藏字段heros)
(注意:图书表和英雄表是一对多关系,so方案一需加上many=true条件)

# 导包
from rest_framework import serializers
from books_test.models import HeroInfo

class HeroInfoSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    hname = serializers.CharField()
    hgender = serializers.IntegerField()
    hcomment = serializers.CharField()
    is_delete = serializers.BooleanField()

# 定义一个BookInfo模型类的序列化器
class BookInfoSerializer(serializers.Serializer):
    # 2、通过定义和模型类“同名类属性、类型一一对应”的形式,来指定参与序列化的字段
    # 该指定,决定了序列化结果(字典)有哪些字段
    # 3、模型类隐藏字段也可以映射 —— 只要模型类有的字段都可以映射
    id = serializers.IntegerField()
    btitle =serializers.CharField()
    bpub_date = serializers.DateField()
    bread = serializers.IntegerField()
    bcomment = serializers.IntegerField()
    is_delete = serializers.BooleanField()
    image = serializers.ImageField()
    # 隐藏字段heros
    # 序列化主表BookInfo的时候,它的属性heros是关联的从表的多个对象

    # 关联对象序列化方案一:序列化成关联对象的主键
    # heros = serializers.PrimaryKeyRelatedField(
    #     queryset=HeroInfo.objects.all(), # 指定当前关联对象的查询集 —— 作用于反序列化
    #     many=True # 表示当前字段heros序列化的是多个英雄对象
    # )

    # 关联对象序列化方案二:序列化成关联对象的模型类HeroInfo的__str__方法返回的结果(hname)
    # heros = serializers.StringRelatedField(many=True)

    # 关联对象序列化方案三:自定义关联对象序列化
    # heros = HeroInfoSerializer(many=True)

3.2.1、测试:python3 manage.py shell 进入交互式环境
方案一结果:多出键值'heros': [1, 2, 3, 4, 5]

>>> from books_test.models import *
>>> from books_test.serializers import *
>>> book = BookInfo.objects.get(pk=1)
>>> bs = BookInfoSerializer(instance=book)
>>> bs.data
{'image': None, 'is_delete': False, 'bcomment': 34, 'bread': 12, 'btitle': '射雕英雄传', 'heros': [1, 2, 3, 4, 5], 'id': 1, 'bpub_date': '1980-05-01'}
>>> 

方案二结果:多出键值'heros': ['郭靖', '黄蓉', '黄药师', '欧阳锋', '梅超风']

>>> from books_test.models import *
>>> from books_test.serializers import *
>>> book = BookInfo.objects.get(pk = 1)
>>> bs = BookInfoSerializer(instance=book)
>>> bs.data
{'heros': ['郭靖', '黄蓉', '黄药师', '欧阳锋', '梅超风'], 'id': 1, 'bread': 12, 'btitle': '射雕英雄传', 'image': None, 'is_delete': False, 'bpub_date': '1980-05-01', 'bcomment': 34}
>>> 

方案三结果:多出键值 'heros': [OrderedDict([('id', 1), ('hname', '郭靖'), ('hgender', 1), ('hcomment', '降龙十八掌'), ('is_delete', False)]), OrderedDict([('id', 2), ('hname', '黄蓉'), ('hgender', 0), ('hco打狗棍法'), ('is_delete', False)]), OrderedDict([('id', 3), ('hname', '黄药师'), ('hgender', 1), ('hcomment', '弹指神通'), ('is_delete', False)]), OrderedDict([('id', 4), ('hname', '欧阳锋'), ('hgender', 1), ('hcomment'_delete', False)]), OrderedDict([('id', 5), ('hname', '梅超风'), ('hgender', 0), ('hcomment', '九阴白骨爪'), ('is_delete', False)])]

>>> from books_test.models import *
>>> from books_test.serializers import *
>>> book = BookInfo.objects.get(pk = 1)
>>> bs = BookInfoSerializer(instance=book)
>>> bs.data
{'bread': 12, 'is_delete': False, 'heros': [OrderedDict([('id', 1), ('hname', '郭靖'), ('hgender', 1), ('hcomment', '降龙十八掌'), ('is_delete', False)]), OrderedDict([('id', 2), ('hname', '黄蓉'), ('hgender', 0), ('hco打狗棍法'), ('is_delete', False)]), OrderedDict([('id', 3), ('hname', '黄药师'), ('hgender', 1), ('hcomment', '弹指神通'), ('is_delete', False)]), OrderedDict([('id', 4), ('hname', '欧阳锋'), ('hgender', 1), ('hcomment'_delete', False)]), OrderedDict([('id', 5), ('hname', '梅超风'), ('hgender', 0), ('hcomment', '九阴白骨爪'), ('is_delete', False)])], 'id': 1, 'btitle': '射雕英雄传', 'bcomment': 34, 'image': None, 'bpub_date': '1980-05-01'}
>>> 

方向二:序列化从表数据,的时候,顺带着序列化关联的主表单一数据;
3.3、编辑自定义序列器serializers.py(加上隐藏字段hbook)
(注意:代表当前英雄对象(从),关联书本(主)单一对象)

# 图书序列化器
class BookInfoSerializer(serializers.Serializer):
    btitle = serializers.CharField()
    bpub_date = serializers.DateField()
    bread = serializers.IntegerField()
    bcomment = serializers.IntegerField()
    is_delete = serializers.BooleanField()
    image = serializers.ImageField()

# 英雄序列化器
class HeroInfoSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    hname = serializers.CharField()
    hgender = serializers.IntegerField()
    hcomment = serializers.CharField()
    is_delete = serializers.BooleanField()
    # 代表当前英雄对象(从),关联的书本(主)单一对象
    
    # 关联对象序列化方案一:序列化成关联对象的主键
    # hbook = serializers.PrimaryKeyRelatedField(
    #     queryset=BookInfo.objects.all()
    # )
    # 关联对象序列化方案二:序列化成关联对象的__str__方法返回的结果(btitle)
    # hbook = serializers.StringRelatedField()
    # 关联对象序列化方案三:自定义关联对象序列化
    hbook = BookInfoSerializer()

**3.3.1、**测试:
方案一结果:多出键值'hbook': 1

>>> from books_test.models import *
>>> from books_test.serializers import *
>>> hero = HeroInfo.objects.get(pk =1)
>>> hs = HeroInfoSerializer(instance=hero)
>>> hs.data
{'hname': '郭靖', 'hcomment': '降龙十八掌', 'id': 1, 'is_delete': False, 'hgender': 1, 'hbook': 1}
>>> 

方案二结果:多出键值'hbook': '射雕英雄传'

>>> from books_test.models import *
>>> from books_test.serializers import *
>>> hero = HeroInfo.objects.get(pk =1)
>>> hs = HeroInfoSerializer(instance=hero)
>>> hs.data
{'is_delete': False, 'id': 1, 'hgender': 1, 'hname': '郭靖', 'hcomment': '降龙十八掌', 'hbook': '射雕英雄传'}
>>> 

方案二结果:多出键值'hbook': OrderedDict([('id', 1), ('btitle', '射雕英雄传'), ('bpub_date', '1980-05-01'), ('bread', 12), ('bcomment', 34), ('is_delete'image', None), ('heros', [1, 2, 3, 4, 5])])

>>> from books_test.models import *
>>> from books_test.serializers import *
>>> hero = HeroInfo.objects.get(pk=1)
>>> hs = HeroInfoSerializer(instance=hero)
>>> hs.data
{'id': 1, 'hgender': 1, 'hname': '郭靖', 'hcomment': '降龙十八掌', 'is_delete': False, 'hbook': OrderedDict([('id', 1), ('btitle', '射雕英雄传'), ('bpub_date', '1980-05-01'), ('bread', 12), ('bcomment', 34), ('is_delete'image', None), ('heros', [1, 2, 3, 4, 5])])}
>>> 

三种形式:

  • (1)、关联字段的类型定义成:PrimaryKeyRelatedField(queryset, many):把关联对象序列化成其主键值
    • queryset=关联模型类的查询集作用于反序列化
    • many=True表示关联字段是多个对象的时候设置的(关联字段是从表多条数据)
  • (2)、StringRelatedField: 把关联对象序列化成其__str__方法返回的结果
  • (3)、针对关联对象,自定义序列化器:序列化结果取决于自定义序列化器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值