一、序列化器-Serializer 是什么?
简单来说,我们从数据库取出来的数据做一个json的处理,其实这就叫序列化。
就是把模型类数据,或者querySet数据转化成json的过程,就是序列化
二、通过举例来,说明 序列化器-Serializer
1. 首先创建好模型类,并连接上数据库
(1).新建一个 app,sers
(2).创建一个模型类,(为了方便默认就使用sqlite)
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='出版日期')
(3). python manage.py makemigrations
(4). python manage.py migrate
(5). python manage.py shell (使用shell插入两条数据)
2. 对单个数据进行 增删改查(全部)查(单个)
(1). 设置好路由
(2). 首先,查找所有书籍,这块要就要 “对数据库查询的数据进行序列化”
from django.http import HttpResponse
from django.shortcuts import render
from rest_framework.views import APIView
from sers.models import Book
from rest_framework import serializers
from rest_framework.response import Response
# 针对模型,设计序列化器
class BookSerializers(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
date = serializers.DateField(source='pub_date')
class BookView(APIView):
# 查
def get(self, request):
# 获取所有的书籍
book_list = Book.objects.all()
# 构建序列化器对象 BookSerializers(instance=,data=,many=)
# instance,是用来做序列化器的
# data,是用来做反序列化器的
# many, 序列化的是一个模型类对象还是多个模型类对象, True/Falseid
serializer = BookSerializers(instance=book_list, many=True)
return Response(serializer.data)
因为我们通过从模型类查询的数据,是一个querySet对象或者模型类对象,这块进行序列化并不是很简单了
所以要基于DRF的序列化器,实现一个灵活并且强大的序列化过程
使用Postman调用接口,请求后发现,就会把数据打包成,OrderedDict一个有序字典,
(3). 使用DRF的Response响应类
DRF响应类,会根据序列化的结果处理成一个json的Content-Type,返回给客户端
使用后如下图:
3. 序列化器的解析的过程
(1). 解析过程
- many=True,则说明,是一个大列表,里面有多个对象
- 则先创建一个空列表,比如说: temp=[]
- 最后会循环刚才传入的从模型类中查到结果列表,即本文的book_list
for obj in book_list:
d = {}
# 可以灵活的取决序列化那些字段,如下
d['title'] = obj.title
d['price'] = obj.price
d['pub_date'] = obj.pub_date
temp.append(d)
- 结果就是,一个列表套有多个数据,就是多个字典,即, [{},{},{}…]
(2). 当模型类的字段名成,返回给前端时,字段名称需要修改,则,在序列化器中使用source属性
如下
date = serializers.DateField(source='pub_date')
结果:
4. 举例restful接口的简单规则
- /book/ GET 查看所有资源,返回所有资源
- /book/ POST 添加资源,返回添加的资源
- /book/1 GET 查看某个资源,返回这一个资源
- /book/1 PUT 编辑某个资源,返回这编辑之后的这个资源
- /book/1 DELETE 删除某个资源,返回空
5. POST,添加资源(反序列化)
(1). 添加一本书,postman发送这个post请求,对应的view改怎么写
(2). 上述的带的参数,获取到数据
request.data
(3). 序列化器,里面定义的类型、以及参数,例如max_length,这块就是做数据校验用的
- required=False, 可以不用传,默认是True
- 注意,序列化器的类型,参数,最好要与模型类保持一致
# 针对模型,设计序列化器
class BookSerializers(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
date = serializers.DateField(source='pub_date')
(4). 数据校验 serializer.is_valid() 返回一个布尔值,所有字段都符合才返回True,反之,返回False
不符合数据的都放在,serializer.errors
def post(self, request):
# 获取参数
data = request.data
# 构建序列化器对象
serializer = BookSerializers(data=data)
# 校验数据
# 校验原理:
# 1.所有符合的数据都放在,serializer.validated_data
# 2.不符合数据的都放在,serializer.errors
if serializer.is_valid(): # 返回一个布尔值,所有字段都符合才返回True,反之,返回False
# 数据校验通过
pass
else:
# 数据校验失败
return Response(serializer.errors)
- 例如我,title搞一个长度特别长的,但我序列化器里面最长就32,这块校验就会报具体的错误信息
所有符合的数据都放在,serializer.validated_data
当校验通过,然后返回添加的数据
def post(self, request):
# 获取参数
data = request.data
# 构建序列化器对象
serializer = BookSerializers(data=data)
# 校验数据
# 校验原理:
# 1.所有符合的数据都放在,serializer.validated_data
# 2.不符合数据的都放在,serializer.errors
if serializer.is_valid(): # 返回一个布尔值,所有字段都符合才返回True,反之,返回False
# 数据校验通过,存入数据库中
new_book = Book.objects.create(**serializer.validated_data)
return Response(serializer.data)
else:
# 数据校验失败
return Response(serializer.errors)
使用postman调用之后,的结果
三、序列化器的的save操作
1.一般情况往数据库里面插数据
Book.objects.create(**serializer.validated_data)
最好用 一个函数,包含起来,然后调用这个函数进行保存,如下
2. 使用序列化器进行保存数据
(1)使用序列化器对象的save()方法
serializer.save()
(2) save()的源码
断言的跳过不看,直接看 self.instance,发现如果self对象里面
有instance时,则调用update()方法
没有instance时,则调用create()方法
但是当我们点过去update()方法或者create()方法后
有一句话,create()` must be implemented
也就是说,这个update()以及create()方法,要我们继承后,去实现,不然就会报错
def save(self, **kwargs):
assert hasattr(self, '_errors'), (
'You must call `.is_valid()` before calling `.save()`.'
)
assert not self.errors, (
'You cannot call `.save()` on a serializer with invalid data.'
)
# Guard against incorrect use of `serializer.save(commit=False)`
assert 'commit' not in kwargs, (
"'commit' is not a valid keyword argument to the 'save()' method. "
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
"You can also pass additional keyword arguments to 'save()' if you "
"need to set extra attributes on the saved model instance. "
"For example: 'serializer.save(owner=request.user)'.'"
)
assert not hasattr(self, '_data'), (
"You cannot call `.save()` after accessing `serializer.data`."
"If you need to access data before committing to the database then "
"inspect 'serializer.validated_data' instead. "
)
validated_data = {**self.validated_data, **kwargs}
# 自己写的序列化器的对象 self
# instance 没传的话,create方法
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.instance = self.create(validated_data)
assert self.instance is not None, (
'`create()` did not return an object instance.'
)
return self.instance
def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')
def update(self, instance, validated_data):
raise NotImplementedError('`update()` must be implemented.')
(3) 实现create()方法
好处就是,解耦,将保存的逻辑解耦出去,
from django.http import HttpResponse
from django.shortcuts import render
from rest_framework.views import APIView
from sers.models import Book
from rest_framework import serializers
from rest_framework.response import Response
# 针对模型,设计序列化器
class BookSerializers(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
date = serializers.DateField(source='pub_date')
# 重写或者说是,实现create()方法
def create(self, validated_data):
new_book = Book.objects.create(**self.validated_data)
return new_book
class BookView(APIView):
# 查
def get(self, request):
# 获取所有的书籍
book_list = Book.objects.all()
# 构建序列化器对象 BookSerializers(instance=,data=,many=)
# instance,是用来做序列化器的
# data,是用来做反序列化器的
# many, 序列化的是一个模型类对象还是多个模型类对象, True/Falseid
serializer = BookSerializers(instance=book_list, many=True)
return Response(serializer.data)
# 增
def post(self, request):
# 获取参数
data = request.data
# 构建序列化器对象
serializer = BookSerializers(data=data)
# 校验数据
# 校验原理:
# 1.所有符合的数据都放在,serializer.validated_data
# 2.不符合数据的都放在,serializer.errors
if serializer.is_valid(): # 返回一个布尔值,所有字段都符合才返回True,反之,返回False
# 数据校验通过,存入数据库中
# new_book = Book.objects.create(**serializer.validated_data)
serializer.save()
return Response(serializer.data)
else:
# 数据校验失败
return Response(serializer.errors)
四、序列化器,对资源进行增删改查(全部)查(一个)
具体看代码
from django.http import HttpResponse
from django.shortcuts import render
from rest_framework.views import APIView
from sers.models import Book
from rest_framework import serializers
from rest_framework.response import Response
# 针对模型,设计序列化器
class BookSerializers(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
date = serializers.DateField(source='pub_date')
# 重写或者说是,实现create()方法
def create(self, validated_data):
new_book = Book.objects.create(**self.validated_data)
return new_book
def update(self, instance, validated_data):
Book.objects.filter(pk=instance.pk).update(**self.validated_data)
update_book = Book.objects.get(pk=instance.pk)
return update_book
class BookView(APIView):
# 查所有
def get(self, request):
# 获取所有的书籍
book_list = Book.objects.all()
# 构建序列化器对象 BookSerializers(instance=,data=,many=)
# instance,是用来做序列化器的
# data,是用来做反序列化器的
# many, 序列化的是一个模型类对象还是多个模型类对象, True/Falseid
serializer = BookSerializers(instance=book_list, many=True)
return Response(serializer.data)
# 增加一个
def post(self, request):
# 获取参数
data = request.data
# 构建序列化器对象
serializer = BookSerializers(data=data)
# 校验数据
# 校验原理:
# 1.所有符合的数据都放在,serializer.validated_data
# 2.不符合数据的都放在,serializer.errors
if serializer.is_valid(): # 返回一个布尔值,所有字段都符合才返回True,反之,返回False
# 数据校验通过,存入数据库中
# new_book = Book.objects.create(**serializer.validated_data)
serializer.save()
return Response(serializer.data)
else:
# 数据校验失败
return Response(serializer.errors)
class BookDetailsView(APIView):
# 查一个
def get(self, request, id):
book = Book.objects.get(pk=id)
serializer = BookSerializers(instance=book)
return Response(serializer.data)
def put(self, request, id):
book = request.data
update_book = Book.objects.get(pk=id)
# 构建序列化器对象
serializer = BookSerializers(instance=update_book, data=book)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors)
def delete(self, request, id):
Book.objects.get(pk=id).delete()
return Response()