drf-序列化器serializer
一、序列化器-serializer
- 序列化,序列化器会把模型对象转成字典,经过response以后变成JSON字符串
- 反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
- 反序列化:完成数据校验功能
二、序列化器的使用
序列化器的使用分为两个阶段:
- 在客户端请求时,使用序列化器可以完成对数据的反序列化。
- 在服务器响应时,使用序列化器可以完成对数据的序列化。
简单使用
1、创建一个表模型
from django.db import models
class Books(models.Model):
title = models.CharField(verbose_name='书名', max_length=32)
publish = models.CharField(verbose_name='出版社', max_length=32)
price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2)
2、新建一个py文件,写一个序列化的类,继承Serializer
3、在类中写要序列化的字段,想序列化那个字段,就在类中写那个字段
from rest_framework import serializers
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField()
4、在视图类中使用,导入——》实例化得到序列化对象,把要序列化的对象传入
5、序列化的对象.data
——》是一个字典
6、把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse
from rest_framework.views import APIView
from rest_framework.request import Request
from app01.models import Books
from app01.ser import BooksSerializer
class BookView(APIView):
def get(self, request, pk):
# 响应信息
response_msg = {'status': 200, 'message': '查询成功'}
# 获取要序列化的对象
book = Books.objects.filter(pk=pk).first()
# 要序列化谁就把谁传到序列化类去
book_ser = BooksSerializer(book)
# book_ser.data————》序列化对象.data————》就是序列化后的字典
# 将查询结果添加到响应信息内
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
re_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),
7、如果要被序列化的是包含多条数据的查询集queryset,可以通过添加many=True参数
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.models import Books
from app01.ser import BooksSerializer
class BooksView(APIView):
def get(self, request):
# 响应信息
response_msg = {'status': 200, 'message': '查询成功'}
books = Books.objects.all()
# 要序列化谁就把谁传到序列化类去
book_ser = BooksSerializer(books, many=True)
# book_ser.data————》序列化对象.data————》就是序列化后的字典
# 将查询结果添加到响应信息内
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
re_path(r'^books/', views.BookView.as_view()),
高级使用
source
1、可以修改字段名字
class BooksSerializer(serializers.Serializer):
xxx = serializers.CharField(source='title') # 相当于——》xxx = Books.title
# 响应
{
"status": 200,
"message": "查询成功",
"data": {
"xxx": "魔道祖师" ————》响应的字段名被修改了
}
}
2、可以跨表查询
class BookSerializer(serializers.Serializer):
publish_email = serializers.CharField(source='publish.email')
# 相当于——》publish_email = Book.publish.email 连表查询publish表的email字段
# 响应
{
"status": 200,
"message": "查询成功",
"data": {
"publish_email": "modao@163.com"
}
}
3、可以执行方法
# models.py
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.IntegerField()
pub_date = models.DateTimeField()
publish = models.ForeignKey("Publish", on_delete=models.CASCADE, null=True)
authors = models.ManyToManyField("Author")
def func(self):
return '666666'
# ser.py
class BookSerializer(serializers.Serializer):
msg = serializers.CharField(source='func')
# msg = Book.func ——》调用Book类中的func()方法的返回值
# 响应
{
"status": 200,
"message": "查询成功",
"data": {
"msg": "666666"
}
}
**SerializerMethodField( ) **
它需要有一个配套的方法,方法名叫做get_字段名
,返回值就是要显示的东西
class BookSerializer(serializers.Serializer):
authors = serializers.SerializerMethodField()
def get_authors(self, instance):
# instance ——》 Book对象
authors = instance.authors.all() # 取出所有作者
author_list = []
for author in authors:
author_list.append({'name': author.name, 'age': author.age})
return author_list
通用参数
read_only:(只读)表明该字段仅用于序列化输出,默认False,如果设置成True,响应中可以看到该字段,修改时,不需要传该字段
write_only:(只写)表明该字段仅用于反序列化输入,默认False,如果设置成True,响应中看不到该字段,修改时,该字段需要传
from rest_framework import serializers
class BooksSerializer(serializers.Serializer):
title = serializers.CharField(read_only = True) # 响应中能看到改字段,修改不需要传值
publish = serializers.CharField(write_only = True) # 响应中看不到改字段,修改需要传值
price = serializers.DecimalField()
# 还有参数如下:
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
三、反序列化数据校验
当使用序列化器对数据进行反序列化时,就需要对数据进行校验了,只有校验成功的数据才能被保存成模型类对象
将要校验的数据传入序列化器中并实例化:obj = BooksSerializer(data=request.data)
,调用is_valid()
方法校验,校验成功返回True,失败返回False。
失败,可以通过序列化器对象的errors
获取错误信息(字典)
成功,可以公共序列化对象的validated_data
属性获取数据。
校验方法有:局部钩子,全局钩子,validators,和序列化类型和字段属性也是
字段属性
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最小值
min_value 最大值
局部钩子
在序列化器类中创建局部钩子:validate_字段名,并且接收一个参数
# ser.py
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
# 局部钩子对price字段校验
def validate_price(self, data):
if float(data) > 20:
# 校验成功就通过
return data
else:
# 校验失败就抛异常
raise ValidationError('价格太低')
全局钩子
全局钩子:validate( ), 接收一个参数,
同时对多个字段进行比较验证
# ser.py
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
def validate(self, validate_data):
title = validate_data.get('title')
publish = validate_data.get('publish')
if not title == publish:
return validate_data
else:
raise ValidationError('书名和出版社不能一致')
validators
使用字段的validators=[func]
,来校验
# ser.py
# 校验函数
def check_price(data):
if float(data) > 10:
return data
else:
raise ValidationError('价格太低')
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.CharField(validators=[check_price]) # 配置
四、序列化器操作数据
查询所有
# views.py
class BooksView(APIView):
def get(self, request):
# 响应信息
response_msg = {'status': 200, 'message': '查询成功'}
# 获取所有数据
books = Books.objects.all()
# 把数据谁传到序列化器中
book_ser = BooksSerializer(instance=books, many=True) # 序列化多条需要加 many=True
# book_ser.data————》序列化对象.data————》就是序列化后的字典
# 将查询结果添加到响应信息内
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
path('books/', views.BooksView.as_view()),
查询单条
# views.py
class BookView(APIView):
def get(self, request, pk):
# 响应信息
response_msg = {'status': 200, 'message': '查询成功'}
# 获取要序列化的对象
book = Books.objects.filter(pk=pk).first()
# 要序列化谁就把谁传到序列化器中
book_ser = BooksSerializer(instance=book)
# book_ser.data————》序列化对象.data————》就是序列化后的字典
# 将查询结果添加到响应信息内
response_msg['data'] = book_ser.data
return Response(response_msg)
# urls.py
re_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),
新增数据
新增数据需要在序列化器中重写create( ) 方法:
注意没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,调用save()方法的时候,update()被调用。
# views.py
class BookView(APIView):
def post(self, request):
# 响应信息
response_msg = {'status': 201, 'message': '增加成功'}
# 修改才有instance,新增没有instance,只有data
book_ser = BooksSerializer(data=request.data)
# 校验字段
if book_ser.is_valid():
book_ser.save() # 需要在序列化器中重写create()方法
# 保存成功把原数据返回
response_msg['data'] = book_ser.data
else:
response_msg['status'] = 202
response_msg['message'] = '数据校验失败'
response_msg['data'] = book_ser.error_messages
return Response(response_msg)
# ser.py
class BooksSerializer(serializers.Serializer):
title = serializers.CharField()
publish = serializers.CharField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
# 重写create
def create(self, validated_data): # validated_data——>传入的新增数据
instance = Books.objects.create(**validated_data)
# instance——> 新增的字段对象,需要返回
return instance
# urls.py
path('book/', views.BookView.as_view()),
修改数据
修改数据需要在序列化器中重写update( ) 方法:
# views.py
class BookView(APIView):
def put(self, request, pk):
# 响应信息
response_msg = {'status': 200, 'message': '修改成功'}
# 获取需要修改的字段对象
book = Books.objects.filter(pk=pk).first()
# 将字段对象和修改数据添加到序列化器中
book_ser = BooksSerializer(instance=book, data=request.data)
# 校验数据
if book_ser.is_valid():
book_ser.save() # 需要在序列化器中重写update()方法
response_msg['data'] = book_ser.data
else:
response_msg['status'] = 202
response_msg['message'] = '数据校验失败'
response_msg['data'] = book_ser.error_messages
return Response(response_msg)
# urls.py
re_path('book/(?P<pk>\d+)', views.BookView.as_view()),
删除数据
# views.py
class BooksView(APIView):
def delete(self, request, pk):
# 响应信息
response_msg = {'status': 200, 'message': '删除成功'}
# 删除数据
Books.objects.filter(pk=pk).delete()
return Response(response_msg)
# urls.py
re_path('book/(?P<pk>\d+)', views.BooksView.as_view()),
五、模型类序列化器
DRF提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerializer与常规的Serializer相同,但是提供了:
- 基于模型类自动生成一系列字段
- 基于模型类自动为Serializer生成validators,比如unique_together
- 包含默认的create( ) 和update( )。
实例:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book # 指明参照那个模型类
fields = '__all__' # 为模型类的那些字段生成
字段操作
1、可以使用fields来明确字段,__all__
表示包含所以字段,具体那些字段->fields = ('title','price')
2、exclude
表示排除那些字段,不能和fields一起写——>exclude = ('price',)
3、额外参数extra_kwargs
,给字段添加额外的参数
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book # 指明参照那个模型类
fields = '__all__' # 为模型类的那些字段生成
# 类似于 title = serializers.CharField(read_only = True)
extra_kwargs = {
'title': {'read_only': True},
}
六、源码分析many=True
当我们需要查询多条数据时就需要在实例化序列化器的时候传many=True
book_ser = BooksSerializer(instance=books, many=True) # 查询多条
book_one_ser = BooksSerializer(instance=book) # 查询单条
print(type(book_ser))
#<class 'rest_framework.serializers.ListSerializer'>
print(type(book_one_ser))
#<class 'app01.ser.BookModelSerializer'>
# 对象的生成-->先调用类的__new__方法,生成空对象,如果many=True,生成ListSerializer对象,反之生成Serializer对象
# 类的__new__方法控制对象的生成
def __new__(cls, *args, **kwargs):
# 如果many=True,就会自动创建ListSerializer类
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
return super().__new__(cls, *args, **kwargs)
drf-序列化器serializer的更多相关文章
- DRF 序列化器-Serializer (2)
作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...
- 066.Python框架DRF之序列化器Serializer
一 序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成 ...
- DRF序列化器
序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成字典 ...
- Cf序列化器-Serializer解析
Cf序列化器-Serializer 定义序列化器 Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Seri ...
- day82 序列化器-Serializer
目录 一.序列化器的基本功能 二.定义序列化器 三.创建Serializers对象 四.序列化器的使用 1 序列化 2 反序列化 2.1 数据验证(类比forms组件) 2.2 数据保存 一.序列化器 ...
- drf序列化器serializers.SerializerMethodField()的用法
问题描述: 为什么DRF中有时候返回的json中图片是带域名的,有时候是不带域名的呢? 解析: 带域名的结果是在view中对模型类序列化的,DRF在序列化图片的时候 会检查上下文有没有request, ...
- drf序列化器的实例
应用目录结构: views.py from django.shortcuts import render # Create your views here. from django.views imp ...
- DRF序列化器的使用
序列化器的使用 序列化器的使用分两个阶段: 在客户端请求时,使用序列化器可以完成对数据的反序列化. 在服务器响应时,使用序列化器可以完成对数据的序列化. 序列化的基本使用 使用的还是上一篇博文中使用的 ...
- drf序列化器与反序列化
什么是序列化与反序列化 """ 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 """ drf序列化与反序列化 &qu ...
- 4)drf序列化组件 Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)
知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 一.Serializer 偏底层 一般不用 理解原理 1.序列化准备 ...
随机推荐
- [刷题] 347 Top K Frequent Elements
要求 给定一个非空数组,返回前k个出现频率最高的元素 示例 [1,1,1,2,2,3], k=2 输出:[1,2] 思路 出队逻辑,普通队列是先进先出,优先队列是按最大/最小值出队 通过堆实现优先队列 ...
- QT windows 应用程序 exe ,设置详细信息并解决中文乱码问题
原博主:https://blog.csdn.net/xiezhongyuan07/article/details/87691490 1.新创建一个.rc文件,随意命名,例如叫app.rc 并编辑 1 ...
- HBase HA 集群环境搭建
安装准备 确定已安装并启动 HDFS(HA)集群 角色分配如下: node-01: namenode datanode regionserver hmaster zookeeper node-02: ...
- Centos6.9以下查看端口占用情况和开启端口命令
Centos查看端口占用情况命令,比如查看80端口占用情况使用如下命令: lsof -i tcp:80 列出所有端口 netstat -ntlp 1.开启端口(以80端口为例) ...
- JDK5.0新特性 (Day_07)
JDK5.0新特性 目录 静态导入 自动装箱/拆箱 for-each循环 可变参数 枚举 JDK 5.0 新特性简介 JDK 5.0 的一个重要主题就是通过新增一些特性来简化开发,这些特性包括 ...
- docker中ubuntu源更新慢加速 换为国内源 Debian10源
本来以为是Ubuntu打包的镜像,换了阿里源老是报错100公钥不可用,结果发现是Debian的操作系统,换位Debian的操作系统打包的,换位Debian的源即可 #源如果使用错误也会报错,没有Deb ...
- 防火墙 firewall iptables
firewalld FirewallD 使用服务service 和区域zone来代替 iptables 的规则rule和链chain,默认情况下,有以下的区域zone可用: drop – 丢弃所有传入 ...
- Python-名片管理器
# 需要完成的基本功能: # 添加名片 # 删除名片 # 修改名片 # 查询名片 # 退出系统 # 程序运行后,除非选择退出系统,否则重复执行功能 list_info = [] # 创建一个空列表 # ...
- AtCoder Regular Contest 121 D - 1 or 2
题目链接:点我点我 Problem Statement Snuke has a blackboard and NN candies. The tastiness of the ii-th candy ...
- 高频访问SQLite数据库
SQLite 是一款开源的 SQL 数据库引擎,由于其自包含.无服务.零配置和友好的使用许可(完全免费)等特点,在桌面和移动平台被广泛使用. 在应用开发过程中,如果想保存点数据,自然而然地就会想到 S ...