Django REST framework - 序列化组件
序列化器-Serializer
什么是rest_framework序列化?
在写前后端不分离的项目时:
我们有form组件帮我们去做数据校验
我们有模板语法,从数据库取出的queryset对象不需要人为去转格式
当我们写前后端分离项目的时:
我们需要自己去做数据校验
我们需要手动去转数据格式,因为跨平台数据传输都用json字符串,不能直接jsonqueryset对象
序列化器的作用
1 序列化:把python中的对象转成json格式字符串
序列化器会把模型对象转换成字典,经过response以后变成json字符串
2 反序列化:把json格式字符串转成python中的对象
把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3 注意:drf的序列化组件(序列化器)
把对象(Book,queryset对象)转成字典
因为有字典,直接丢到Response中就可以了
序列化,反序列化
-对象----》json
-json---》对象
序列化器
-定义一个类,继承Serializer
-在类内些字段(常用字段,和非常用字段)(字段参数)
-在视图类中,实例化得到一个序列化类的对象,传入要序列化的数据
-对象.data---》就是字典
-source
序列化器的基本使用
from rest_framework.serializers import Serializer,ModelSerializer
from rest_framework import serializers
Serializer是rest_framework原生的序列化组件
ModelSerializer是rest_framework在原生的序列化组件的基础上封装了一层的序列化组件
用法:1、在用我们的rest_framework序列化组件的时候,我们的视图层都必须写视图类,不能再写视图函数
2、我们需要针对每一张模型表写一个类来继承Serailizer或者ModelSerailizer类,
注:当我们在视图类里需要对数据进行序列化或者反序列化的时候,在自己定义的类传入需要序列化的数据实例化,
调用.data即可拿到序列化或者校验后的数据了
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer
1 写一个序列化的类,继承Serializer
class BookSerializer(serializers.Serializer):
# 在这里写要序列化的字段
# 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
# 字段类,有很多字段参数()
name = serializers.CharField()
price = serializers.IntegerField()
# publish = serializers.CharField()
2 在类中写要序列化的字段(常用字段,和非常用字段)(字段参数)
name = serializers.CharField()
price = serializers.IntegerField()
3 在视图类中使用(实例化得到一个序列化类的对象,传入要序列化的数据)
class BookView(APIView):
def get(self, request):
book_list = models.Book.objects.all()
# instance=None, 要序列化的数据
# data=empty ,要反序列化的数据(目前data先不用)
# many=True 如果序列化多条,一定要写many=True
book_ser = BookSerializer(instance=book_list, many=True)
# book_ser.data就是序列化后的数据
return Response(book_ser.data)
4 得到序列化后的数据,返回(对象.data---》就是字典)
book_ser.data
5 字段参数,source,指定要序列化表中的哪个字段
路由层 urls.py
from django.urls import path
from app import views
urlpatterns = [
path('admin/', admin.site.urls),
# 获取所有的书籍信息
path('books_new/', views.BookView.as_view()),
# 对某本书进行操作
path('books_new/<int:id>/', views.BookViewId.as_view()),
]
模型层 models.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32, verbose_name='书名')
publish = models.CharField(max_length=32, verbose_name='出版社')
price = models.IntegerField(verbose_name='价格')
序列化器层 serializer.py
from rest_framework import serializers
from app import models
# 新建序列化类,继承Serializer
class BookSerializer(serializers.Serializer):
# 类中定义和模型表一一对应的字段,在这里写要序列化的字段
# 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
# 字段类,有很多字段参数()
name = serializers.CharField()
price = serializers.IntegerField()
publish = serializers.CharField()
视图层 views.py
# 获取所有书籍信息
class BookView(APIView):
def get(self, request):
book_list = models.Book.objects.all()
book_ser = BookSerializer(instance=book_list, many=True)
# book_ser.data就是序列化后的数据
return Response(book_ser.data)
"""
instance=None, 要序列化的数据
data=empty ,要反序列化的数据(目前data先不用)
many=True 如果序列化多条,一定要写many=True
"""
# 对某一本书进行操作
class BookViewId(APIView):
# 对某一个进行操作需要带上id
def get(self, request, id):
book = models.Book.objects.all().filter(pk=id).first()
book_ser = BookSerializer(instance=book)
return Response(book_ser.data)
source
1 指定要序列化的字段(数据表中字段)
publish = serializers.CharField(source='publish.city') # 拿到出版社所在的城市
2 指定方法
3 深度表查询
4 用的最多:只有一个字段(也可以跨表)
SerializerMethodField
1 用的最多,跨表查(要么是列表,要么是字典)
publish=serializers.SerializerMethodField()
def get_publish(self,obj):
return {'name':obj.publish.name,'city':obj.publish.city}
authors = serializers.SerializerMethodField()
def get_authors(self, obj):
return [{'name':author.name, 'age': author.age} for author in obj.authors.all()]
在模型表中写方法
# 表模型中写的
def publish_name(self):
return {'name':self.publish.name,'city':self.publish.city}
@property
def author_list(self):
return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]
#序列化类中
# publish = serializers.CharField(source='publish_name')
publish_name = serializers.DictField()
author_list=serializers.ListField()
序列化类常用字段类型及属性
常用字段类型:


字段参数针对性分类
# 针对charfield
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
# 针对interfield
max_value 最小值
min_value 最大值
# 通用的,大家都有
# 这两个最重要
read_only 表明该字段仅用于序列化输出,默认False(序列化)
write_only 表明该字段仅用于反序列化输入,默认False(反序列化)
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
error_messages 包含错误编号与错误信息的字典
validators 该字段使用的验证器(了解)
反序列化、局部和全局钩子
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。
验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,可以通过序列化器对象的validated_data属性获取数据。
在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。
反序列化
1 如果要反序列化,继承了Serializer,必须重写create方法
2 使用
# 视图类
def post(self, request):
publish_ser = serializer.PublishSerializer(data=request.data)
if publish_ser.is_valid(): # 校验数据
# 直接保存,保存到哪个表里?需要重写save
publish_ser.save()
return Response(publish_ser.data)
else:
print(publish_ser.errors)
return Response('数据有问题啊')
# 序列化类
def create(self, validated_data):
# 校验过后的数据
res = models.Publish.objects.create(**validated_data)
return res
"""
父类的save内部调用了create,所以我们重写create
return res 给了self.instance以后,instance就有值了
publish_ser.data,instance就有值调用data就能拿到序列化后的数据
is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,
REST frame
局部和全局钩子
# validate_字段名
def validate_name(self, data):
# data就是当前字段的值
if data.startswith('sb'):
raise ValidationError('不能以sb开头')
else:
return data
# 在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证
def validate(self, attrs):
if attrs.get('name') == attrs.get('city'):
raise ValidationError('city和名字不能一样')
else:
return attrs
模型序列化全
视图类
from rest_framework.views import APIView
from rest_framework.response import Response
from restful import models
from restful import serializer
class BookViews(APIView):
# 查询所有
def get(self, request, *args, **kwargs):
response = {'status': 200, 'msg': '查询'}
try:
# 取出数据库所有
book_s = models.Book.objects.all()
# 序列化全部
books = serializer.BookModelSerializer(instance=book_s, many=True) # many全部
# book.data字典加入到data列表里
response['data'] = books.data
except Exception as e:
# 返回错误信息
response['msg'] = str(e)
return Response(response)
# 增加
def post(self, request):
response = {'status': 200, 'msg': '新增'}
try:
# data反序列化
book_ser = serializer.BookModelSerializer(data=request.data)
# 校验
if book_ser.is_valid():
# 保存
book_ser.save()
# book.data字典加入到data列表里
response['data'] = book_ser.data
else:
# book.error错误信息加入到msg列表里
response['msg'] = book_ser.errors
except Exception as e:
# 返回错误信息
response['msg'] = str(e)
return Response(response)
class BooksViewsId(APIView):
# 查询一个
def get(self, request, id):
response = {'status': 200, 'msg': '查询'}
try:
# 取出id
book_s = models.Book.objects.all().filter(pk=id).first()
# 序列化
book_k = serializer.BookModelSerializer(instance=book_s)
# book.data字典加入到data列表里
response['data'] = book_k.data
except Exception as e:
# 返回错误信息
response['msg'] = str(e)
return Response(response)
# 修改数据
def put(self, request, id):
response = {'status': 200, 'msg': '修改'}
try:
# 取出id
books_list = models.Book.objects.all().filter(pk=id).first()
# 拿到id号反序列化
book_ser = serializer.BookModelSerializer(instance=books_list, data=request.data)
# 校验
if book_ser.is_valid():
# 保存
book_ser.save()
# book.data字典加入到data列表里
response['data'] = book_ser.data
else:
# book.error错误信息加入到msg列表里
response['msg'] = book_ser.errors
except Exception as e:
# 返回错误信息
response['msg'] = str(e)
return Response(response)
# 删除
def delete(self, request, id):
# 查询到id号
res = models.Book.objects.filter(pk=id).delete()
# 判断第一个删除
if res[0] > 0:
return Response('')
else:
return Response('删除的不存在')
序列化类
from rest_framework import serializers
from restful import models
from rest_framework.exceptions import ValidationError
# 继承ModelSerializer类
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
# __all__ 查询所有
fields = '__all__'
# 字段限制
extra_kwargs = {
'name': {'max_length': 6, 'required': True},
'price': {'min_value': 0, 'required': True},
}
# 局部钩子
def validate_name(self, data):
# data就是当前字段的值
if data.startswith('sb'):
raise ValidationError('不能以sb开头')
else:
return data
# 全局钩子
def validate(self, attrs):
if attrs.get('name') == attrs.get('price'):
raise ValidationError('名字一样')
else:
return attrs
# 重写字段
publish = serializers.SerializerMethodField()
# 字段详情,必须加get_字段名方法
def get_publish(self, obj):
return {'name': obj.publish.name, 'city': obj.publish.city}
# 重写字段
authors = serializers.SerializerMethodField()
# 字段详情,必须加get_字段名方法
def get_authors(self, obj):
return [{'name': author.name, 'age': author.age} for author in obj.authors.all()]
路由
from restful import views
urlpatterns = [
path('books/<int:id>/', views.BooksViewsId.as_view()),
path('booka/', views.BookViews.as_view()),
]
settings配置app(注意记得配置数据库也可以用自带sqllite3)
INSTALLED_APPS = [
'rest_framework'
]
models 表(注意迁移)
from django.db import models
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish_date = models.DateField()
publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.name
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class AuthorDatail(models.Model):
nid = models.AutoField(primary_key=True)
telephone = models.BigIntegerField()
birthday = models.DateField()
addr = models.CharField(max_length=64)
def __str__(self):
return self.addr
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name
admin 配置(注意创建用户 createsuperuser)
from django.contrib import admin
from restful import models
admin.site.register(models.Book)
admin.site.register(models.Author)
admin.site.register(models.AuthorDatail)
admin.site.register(models.Publish)
序列化类源码分析
序列化many参数源码分析(了解)
1 序列化类实例化的时候,传了many,序列化多条,不传,就序列化单条
#many=True,实例化得到的对象是ListSerializer
ser=serializer.BookModelSerializer(instance=qs,many=True)
print(type(ser))
#rest_framework.serializers.ListSerializer
# 列表中套了很多BookModelSerializer
#many=False,实例化得到的对象是BookModelSerializer
ser=serializer.BookModelSerializer(instance=book)
print(type(ser))
#app01.serializer.BookModelSerializer
类实例化:在执行__init__之前,先执行了__new__生成一个空对象(决定了是哪个类的对象)
在__new__中进行判断,如果many=True,就返回ListSerializer的对象
局部全局钩子的源码分析(了解)
is_valid()
判断_validated_data如果没有
执行了 self.run_validation(self.initial_data)
目前在BaseSerializer,如果按住ctrl点击,会直接进到它父类的run_validation,进到Field,不是真正执行的方法
我们需要从头找,实际上是Serializer类的run_validation
def run_validation(self, data=empty):
value = self.to_internal_value(data)#字段自己的校验和局部钩子
try:
self.run_validators(value)
value = self.validate(value) # 全局钩子
assert value is not None,
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
return value
局部钩子是在 to_internal_value执行的
def to_internal_value(self, data):
for field in fields:
validate_method = getattr(self, 'validate_' + field.field_name, None)
if validate_method is not None:
validated_value = validate_method(validated_value)
##总结:
is_valid---》BaseSerializer的is_valid--》执行了self.run_validation(self.initial_data)---》Serializer的run_validation---》self.to_internal_value(data):局部钩子|||
value = self.validate(value) :全局钩子
self.to_internal_value(data):局部钩子----》getattr(self, 'validate_' + field.field_name, None)
序列化对象.data
序列化对象.data方法--调用父类data方法---调用对象自己的
to_representation(自定义的序列化类无此方法,去父类找)
Serializer类里有to_representation方法
for循环执行attribute = field.get_attribute(instance)
再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source
然后执行get_attribute方法,source_attrs
当参数传过去,判断是方法就加括号执行,是属性就把值取出来
请求与响应
请求对象 request
1 Request:新的request
2 常用属性
1).data
request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,但提供如下特性:
包含了解析之后的文件和非文件数据
包含了对POST、PUT、PATCH请求方式解析后的数据
利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
2).query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已
响应对象 Response
#一直会用
data: 为响应准备的序列化处理后的数据(字典)
#偶尔会用
headers: 用于存放响应头信息的字典;
status: 状态码,默认200;(http请求的状态码)
# 基本不用
template_name: 模板名称,如果使用HTMLRenderer 时需指明;
content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
总结
0 drf是django的一个app
-序列化器
-Request
-Response
-版本控制
-认证,频率,权限
-过滤,排序,分页
-视图相关
-自动生成接口文档(coreapi,swagger)
-jwt做认证(第三方)
-xadmin---》对admin的美化(bootstrap+jq,1.x版本),simple-ui
-RBAC:基于角色的访问控制(公司内部项目)
1 序列化器
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
2 Serializer
-序列化
-实例化序列化对象,many参数作用
-source
-SerializerMethodField
-模型表中写方法
-反序列化
-ser=BookSerializer(data=request.data)
-数据校验:ser.is_valid()
-存数据:手动存,重写BookSerializer的create方法,update方法
-ser.save() 如果是新增,会调用create,如果是修改,会调用update
-ser.data 如果有instance对象,就是对instance做序列化
-全局,局部钩子,字段参数
3 ModelSerializer
-class Meta:
model=Book
fields=‘__all__’
extra_kwargs
-重写某个字段:跟之前学的又一样了
-子序列化
4 常用非常用字段
5 字段参数
6 如果第三张表是手动建的,authors是存不进去的
{
name:ddd
price:10
publish:1
authors:[1,2]
}
7 请求对象的属性
8 响应对象
-data:响应数据
-status:响应状态码
-header:响应头
-content_type:响应类型
9 加入serializer后整个后端逻辑

浙公网安备 33010602011771号