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是特殊的字典,操作和普通字典一样)
序列化单一对象实例:
- 单一对象序列化结果(dict):
>>> 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)、针对关联对象,自定义序列化器:序列化结果取决于自定义序列化器