序列化和反序列化
序列化,是指将复杂的QuerySet和Model类型转换成Python基本数据类型,从而将这些基本数据类型以JSON的形式响应给客户端。
反序列化则和序列化相反,是指将Http请求中传入的JSON数据转换成复杂的数据类型,从而保存在数据库中。
在REST Framework中,提供了多个用于序列化操作的类,但常用的也就如下两个:
Serializer:进行序列化基本的类;
ModelSerializer:继承于Serializer,内部实现了通用的序列化逻辑,其中包含了与Model字段对应的字段,可以快速对Model进行序列化。
使用时需要导入对应模块:
from rest_framework import serializers
Serializers 序列化组件
- Serializer 组件
- ModelSerializer组件
- HyperlinkedIdentityField组件 - 用于链接的拼接
serializer
from rest_framework.views import APIView
from rest_framework.serializers import Serializer
from rest_framework import serializers
# 写一个与modles内表类对应的Serializer类,用于获取需求序列化的字段
# 字段必须在modles对应表内进行定义
class BookSerializer(Serializer):
name = serializers.CharField()
# price=serializers.CharField()
# date=serializers.CharField()
class Books(APIView):
def get(self, request):
# 序列化多个对象(many=True)
books = models.Book.objects.all()
# instance=books要序列化的queryset对象,many=True,表示序列化多条
ser = BookSerializer(instance=books, many=True)
print(ser.data)
# [OrderedDict([('name', 'name')]), OrderedDict([('name', '水')]), OrderedDict([('name', '水都是')])]
# instance:可以不写,按位置传 - instance位于位置传参的第一位
# ser=BookSerializer(books,many=True)
# 序列化单个对象 many=False
book = models.Book.objects.all().first()
ser=BookSerializer(book,many=False)
# ser.data 拿到的是序列化之后的字典,字典里可能套了列表,所以safe=False
return JsonResponse(ser.data, safe=False)
ModelSerializer
- ModelSerializer组件必须配合Meta使用,对指定的字段进行序列化处理和返回
- Meta内注意事项:
- model需导入models内对应处理表类
- fields - 用于获取需处理的表内字段
- fields=‘all’ - 获取所有字段进行序列化处理;后续可用常规方式重写属性,覆盖all序列的操作
- fields = [‘nid’,‘name’] - 获取指定字段进行序列化处理并返回
- exclude=[‘publish’,‘authors’] - 用于去除字段,不序列化并且不返回
- depth = 2 - 关系表的深度指定(不建议使用,对数据库的频繁操作降低效率)
from ap01.models import Book
from rest_framework import serializers
class AuthorSerializer(serializers.Serializer):
nid = serializers.CharField()
name = serializers.CharField()
age = serializers.CharField()
class BookSerializer(serializers.ModelSerializer):
# 必须写一个Meta内部类
class Meta:
# 序列化的对象,models内的对应表类
# 需导入from ap01.models import Book
model = Book
# 对表内所有字段进行序列化处理
fields = '__all__'
# 指定只取这两个字段
# fields = ['nid','name']
# 去掉指定的字段,选入字段不进行序列化且不返回
# exclude=['publish','authors']
# fields,跟exclude不能连用
# 指定深度(官方建议小于10,我给你的建议小于3),和关联表的深度 - 不建议使用
# depth = 2
# 重写属性,覆盖Meta内初始化操作
publish = serializers.CharField(source='publish.name')
authors = serializers.SerializerMethodField()
def get_authors(self, book):
# 拿到这本书的所有作者
aus = book.authors.all()
# 可以继续用序列化类,来处理
auth_ser = AuthorSerializer(aus, many=True)
return auth_ser.data
HyperlinkedIdentityField - 用于链接的拼接
'''
mySer.py
HyperlinkedIdentityField 必传参数:
- view_name:urls.py路由文件内反向解析名
- lookup_field:models内对应路由传入的参数
- lookup_url_kwarg:urls.py路由文件内对应有名参数名
- 注意:可以传入跨表字段,必须是联系表
例如:假设publish表类内存在外联关系表book - 'book_id'
'''
class PublishSerializer(serializers.Serializer):
name = serializers.CharField()
city = serializers.CharField()
publish_url = serializers.HyperlinkedIdentityField(view_name='urls_publish',lookup_field='nid',lookup_url_kwarg='id')
'''
urls.py
'''
url(r'^publish/(?P<id>\d+)', views.Publish.as_view(),name='urls_publish'),
'''
views.py
PublishSerializer 必传参数:
- instance:序列化对象
- mangy:序列化对象的单复数
- context:获取链接中的域名,即 http://127.0.0.1:8000
'''
class Publish(APIView):
def get(self, request, *args, **kwargs):
ret = models.Publish.objects.all()
publish_ser = PublishSerializer(ret, many=True,context={'request': request})
return JsonResponse(publish_ser.data, safe=False)