本系列文章中的上一篇文章:rest_framework.views.APIView 源码解析
urls.py 文件
from django.urls import path
from sers.views import BookView
urlpatterns = [
path('sers/book/', BookView.as_view()),
}
models.py 文件
from django.db import models
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="书籍名称")
price = models.IntegerField(verbose_name="价格")
pub_date = models.DateField(verbose_name="出版日期")
view.py 文件
导入的包
from rest_framework.views import APIView from rest_framework import serializers from rest_framework.response import Response from sers.models import Book
序列化器定义
# 2、定义序列化器
# 一个序列化类是针对某个模型(数据库表)进行设计的
class BookSerializer(serializers.Serializer):
# 这些字段对应着数据库表的字段和类型
# CharField、IntegerField、DateField 在反序列化的时候校验数据用的
# 比如 title 要求是字符串,且长度要求不超过 32 位
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
# pub_date = serializers.DateField()
# 如果想序列化后的键的名字自定义
# 则要指定 source="pub_date" 参数,对应数据库里的字段名
date = serializers.DateField(source="pub_date")
# 重写父类中的 create 方法,实现自己的数据保存逻辑
# create 方法需要返回值,因为在源码中 save 方法需要接收 create 方法的返回值
def create(self, validated_data):
new_book = Book.objects.create(**self.validated_data)
return new_book
BookView 类
get 方法中是序列化的使用,post 方法中是反序列化的使用
class BookView(APIView):
# 假设有一个 get 请求,查询所有书籍信息
def get(self, request):
# 1、获取所有的书籍对象,返回一个 QuerySet 集合
book_list = Book.objects.all()
# 3、构建序列化器对象
# instance=book_list 表示将 book_list 进行序列化
# many=True 因为要序列化的是一个集合,所以有多个序列化对象, 所以 many=True
# data=book_list 则表示将 book_list 进行反序列化
_serializers = BookSerializer(instance=book_list, many=True)
# 将序列化的结果返回给客户端
# serializers.data 存放着序列化的结果
# HttpResponse 将序列化后的结果按照自己的处理逻辑进行解析,然后发回给客户端
# 但是前端拿到的结果还是有一些不便于阅读
# return HttpResponse(_serializers.data)
"""
_serializers.data 时发生以下动作:
temp = []
for obj in book_list:
t = {}
# BookSerializer 类中有几个字段,字典 t 中就会有几个键值对
# BookSerializer 类中的字段名要和数据库表字段一样
# 否则 obj.title 获取值的时候就会出错
t["title"] = obj.title
t["price"] = obj.price
# 除非自定义了名字:date = serializers.DateField(source="pub_date")
# t["pub_date"] = obj.pub_date
t["date"] = obj.date
temp.append(t)
return temp
"""
# 而利用 rest_framework.response 中的 Response 对序列化的结果进行处理
# 将会得到一个真正的 Content-Type 为 json 的 json 格式的数据
return Response(_serializers.data)
# 假设有一个 post 请求,添加一个书籍
def post(self, request):
# 获取前端传过来的要添加的书籍信息
# 因为继承了 APIView ,request 在 dispatch 中被重新构建了
# 所以获取 post 请求的数据通过 request.date 得到
# 得到的数据格式为 json 格式
# book = request.date
# 构建序列化器对象
serializer = BookSerializer(data=request.date)
# 校验数据
"""
is_valid() 方法的执行过程:
遍历所有的字段,看是否满足序列化器中定义的要求
(如 title 是否是字符串,长度是否超过32位)
通过校验的字段和其值放在字典 serializer.validated_date 中
没有通过的字段放在字典 serializer.errors 中,其中键为字段名,值为错误原因
如果所有字段都通过,is_valid() 方法返回 True,否则返回 False
"""
if serializer.is_valid():
# 校验通过,将数据添加到数据库
# new_book = Book.objects.create(**serializer.validated_data)
# 一般如果数据库表关系复杂一点的话,那么保存数据到数据库的操作应该抽取出来
# 应该调用 序列化器实例对象的 save() 方法
serializer.save()
# 向前端返回这个书籍
# 数据已经通过校验,直接将传过来的数据序列化之后返回
return Response(serializer.data)
else:
# 校验失败,返回错误信息
Response(serializer.errors)
serializers.save() 方法分析
"""
serializer.save() 的源码
先看序列化器 BookSerializer ,类中没有 save() 方法,
class BookSerializer(serializers.Serializer):
# ...# 重写父类中的 create 方法,实现自己的数据保存逻辑
# create 方法需要返回值,因为在源码中 save 方法需要接收 create 方法的返回值
def create(self, validated_data):
new_book = Book.objects.create(**self.validated_data)
return new_book再找 BookSerializer 的父类 Serializer,也没有 save() 方法
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
# ...
再找 Serializer 的父类 BaseSerializer,找到了 save() 方法
class BaseSerializer(Field):
# create() 方法中什么都没做,而是直接抛出了异常,这样做的目的就是为了让子类重写该方法
def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')def save(self, **kwargs):
# ...
# 此时 self 指的是 BookSerializer 的实例对象 serializer
# instance 表示的是要序列化的数据,因为在 post 方法中进行的是反序列化
# 所以传的是 data 关键字参数,没有传 instance
# 所以走的是 else 中的代码
# 也就是说如果要进行序列化,传 instance 参数,调用 save 方法时走的是 if 中的代码
# 如果进行的是反序列化,传的是 data 参数,调用 save 方法走的就是 else 中的代码
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
assert self.instance is not None, (
'`update()` did not return an object instance.'
)
else:
# self.create() 方法的查找:通过一层层的查找最后也是在 BaseSerializer 类中找到了
self.instance = self.create(validated_data)
assert self.instance is not None, (
'`create()` did not return an object instance.'
)文章来源:https://www.toymoban.com/news/detail-667634.htmlreturn self.instance
"""文章来源地址https://www.toymoban.com/news/detail-667634.html
到了这里,关于rest_framework(3)序列化和反序列化(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!