DRF--序列化
为什么要用序列化
当我们做前后端分离的项目时,前后端交互一般都是JSON格式的数据,那么我们给前端的数据就要转为JSON格式,就需要我们拿到数据库后的数据进行序列化。在看DRF的序列化之前,先来看看django的序列化
from django.db import models # Create your models here. __all__ = ["Book", "Publisher", "Author"] class Book(models.Model):
title = models.CharField(max_length=32)
CHOICES = ((1, "python"), (2, "Liunux"), (3, "Go"))
category = models.IntegerField(choices=CHOICES)
pub_time = models.DateField()
publisher = models.ForeignKey(to="Publisher")
authors = models.ManyToManyField(to="Author") class Publisher(models.Model):
title = models.CharField(max_length=32) def __str__(self):
return self.title class Author(models.Model):
name = models.CharField(max_length=32) def __str__(self):
return self.name
model.py
from django.http import JsonResponse
from django.shortcuts import render
from django.views import View
from djangoDemo.models import Book, Publisher # 第一版用values方法取数据
class BookView(View):
def get(self, request):
book_queryset = Book.objects.values("id", "title", "pub_time", "publisher")
book_list = list(book_queryset)
ret = []
for book in book_list:
book["publisher"] = {
"id": book["publisher"],
"title": Publisher.objects.filter(id=book["publisher"]).first().title,
}
ret.append(book)
# ret = json.dumps(book_list, ensure_ascii=False)
# return HttpResponse(ret)
return JsonResponse(ret, safe=False, json_dumps_params={"ensure_ascii": False})
序列化
DRF的序列化
从上面的例子中可以看出来,这样我们序列化出来的数据,写法很麻烦。所以我们用DRF的序列化,要用别人的序列化就要遵守别人的规则,首先需要在app里注册
INSTALLED_APPS = [
'django.contrib.admin', ... 'rest_framework',
]
注册好了之后要声明序列化类,在当前app下创建一个py文件
from rest_framework import serializers # 出版社的序列化器,前面的变量要和model里的变量名一样
class PublisherSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=32) class AuthorSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=32) class BookSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=32)
pub_time = serializers.DateField()
category = serializers.CharField(source="get_category_display") # 选择的需要指定source publisher = PublisherSerializer() # 一对多的表
authors = AuthorSerializer(many=True) # 多对多的表需要指定many=True
上面我们就写好了序列化的类,注意:匹配上的字段进行序列化,匹配不上则丢弃,所以前端需要哪些字段就写哪些,如果不写的就不序列化
外键关系的序列化是嵌套的序列化器对象
注意many=True
然后再视图函数里写序列化对象
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from djangoDemo.models import Book # 导入表
from .serializers import BookSerializer class BookView(APIView):
def get(self, request):
book_queryset = Book.objects.all()
# 拿出来的是一个queryset,用序列化器进行序列化
ser_obj = BookSerializer(book_queryset, many=True)
return Response(ser_obj.data) # 序列化后的数据在data里
注意:当查询出的数据是一个queryset时,需要加many=True,内部会认为是一个可迭代的对象,会去循环。当查询出的是一条数据时,不需要加many=True,会报错
当我们访问这个接口时,返回的数据就是如下的格式
{
"id": 1,
"title": "python从入门到放弃",
"pub_time": "2019-09-10",
"category": "python",
"publisher": {
"id": 1,
"title": "清华"
},
"authors": [
{
"id": 1,
"name": "马云"
},
{
"id": 2,
"name": "刘亦菲"
}
]
}
反序列化
当我们进行post请求的时候,我们需要定义数据格式,然后让前端的妹子传给我们对应的格式。格式确定之后我们还要校验前端妹子传过来的格式和字段,比如字段的类型还有长度,我们不能相信前端妹子的话,妹子说“我没事”。难道就真没事了吗?所以数据校验是必不可少的。
数据格式当然是json格式的,那怎么校验数据呢,在上面我们写了个序列化类,来序列化返回给前端的数据,我们也可以用来校验前端传给我们的数据。因为id是自动递增的,所以前端不需要传,我们也不需要校验,可以加个参数required=False,表示只序列化不反序列化。还有些字段,比如上面的category字段,我们序列化的时候返回的是后面的汉字,而反序列化的时候,我们希望是前面的数字,所以我们需要重写这个字段,如果字段里有read_only=True,表示只序列化。如果是write_only=True,表示只反序列化
返回的数据是上面格式的,我们如果新增数据,希望数据是下面这个格式的
{ "title": "HTML",
"pub_time": "2019-09-10",
"post_category": 1,
"publisher_id":1,
"author_list": [1,2]
}
注意,前面的key是序列化器里对应的字段
先来改写序列化器
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=False) # 只序列化,不走校验
title = serializers.CharField(max_length=32)
pub_time = serializers.DateField()
category = serializers.CharField(source="get_category_display", read_only=True) # 只序列化用
# 因为前端传的是数字,所以需要重写
post_category = serializers.IntegerField(write_only=True) # 只反序列化用 publisher = PublisherSerializer(read_only=True) # 一对多的表 只序列化用
authors = AuthorSerializer(many=True, read_only=True) # 多对多的表需要指定many=True 只序列化用 publisher_id = serializers.IntegerField(write_only=True) # 只反序列化用
author_list = serializers.ListField(write_only=True) # 只反序列化用 def create(self, validated_data):
# validated_data校验通过的数据
# 通过ORM操作给book表增加数据
book_obj = Book.objects.create(title=validated_data['title'],
pub_time=validated_data['pub_time'],
category=validated_data['post_category'],
publisher_id=validated_data['publisher_id'])
book_obj.authors.add(*validated_data['author_list']) # 这个参数可能是一个列表
return book_obj
在来改写视图函数,新增post请求
class BookView(APIView):
def get(self, request):
book_queryset = Book.objects.all()
# 拿出来的是一个queryset,用序列化器进行序列化
ser_obj = BookSerializer(book_queryset, many=True)
return Response(ser_obj.data) # 序列化后的数据在data里 def post(self, request):
# 确定数据类型以及数据结构
# 对前端传来的数据进行校验
book_obj = request.data # post传来的数据
ser_obj = BookSerializer(data=book_obj) # 有data参数,表示反序列化
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.validated_data)
return Response(ser_obj.errors) # 返回错误
这样,当我们提交像上面一样的数据格式之后,在看get请求,就返回如下的数据
[
{
"id": 1,
"title": "python从入门到放弃",
"pub_time": "2019-09-10",
"category": "python",
"publisher": {
"id": 1,
"title": "清华"
},
"authors": [
{
"id": 1,
"name": "马云"
},
{
"id": 2,
"name": "刘亦菲"
}
]
},
{
"id": 2,
"title": "Linux跑路",
"pub_time": "2019-09-18",
"category": "Liunux",
"publisher": {
"id": 2,
"title": "北大"
},
"authors": [
{
"id": 2,
"name": "刘亦菲"
}
]
},
{
"id": 3,
"title": "HTML",
"pub_time": "2019-09-10",
"category": "python",
"publisher": {
"id": 1,
"title": "清华"
},
"authors": [
{
"id": 1,
"name": "马云"
},
{
"id": 2,
"name": "刘亦菲"
}
]
}
]
序列化返回给前端的数据
put反序列化
上面的序列化是post请求的,那我们修改数据的时候可能是只对某一个字段进行修改
路由:
urlpatterns = [
url(r'^book/$', BookView.as_view()),
url(r'^book/(?P<id>\d+)', BookEditView.as_view()),
]
在 BookSerializer 序列化类里添加一个update方法
def update(self, instance, validated_data):
# instance 更新的book_obj对象
# validated_data 校验通过的数据
instance.title = validated_data.get("title",instance.title)
instance.pub_time = validated_data.get("pub_time",instance.pub_time)
instance.category = validated_data.get("post_category",instance.category)
instance.publisher_id = validated_data.get("publisher_id",instance.publisher_id)
if validated_data.get("author_list"): # 可能有多个值
instance.author.set(validated_data["author_list"])
instance.save() # 保存
return instance
因为不知道修改的是哪个字段,所以都要写
在写put请求
class BookEditView(APIView):
def get(self, request, id):
book_obj = Book.objects.filter(id=id).first()
ser_obj = BookSerializer(book_obj) # 查询出的是一条数据,不需要加 many=True
return Response(ser_obj.data) def put(self, request, id):
book_obj = Book.objects.filter(id=id).first()
# instance必传,data=request.data前端传的参数,partial=True部分修改
ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.data) # 返回数据,注意不是ser_obj.validated_data
return Response(ser_obj.errors)
DRF--序列化的更多相关文章
- DRF 序列化组件
Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...
- python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)
昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...
- python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)
昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...
- Django的DRF序列化方法
安装rest_framework -- pip install djangorestframework -- 注册rest_framework序列化 -- Python--json -- 第一版 用v ...
- drf序列化器与反序列化
什么是序列化与反序列化 """ 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 """ drf序列化与反序列化 &qu ...
- drf序列化及反序列化
假如把drf看做一个汉堡包,我们之前讲的模块属于汉堡包前面的盖盖(请求模块.渲染模块)和底底(异常模块.解析模块.响应模块),但是真正中间的夹心没有讲,那么今天我就和大家来看一下汉堡包的夹心(序列化及 ...
- drf序列化和反序列化
目录 drf序列化和反序列化 一.自定义序列化 1.1 设置国际化 二.通过视图类的序列化和反序列化 三.ModelSerializer类实现序列化和反序列化 drf序列化和反序列化 一.自定义序列化 ...
- DRF 序列化组件 模型层中参数补充
一. DRF序列化 django自带有序列化组件,但是相比rest_framework的序列化较差,所以这就不提django自带的序列化组件了. 首先rest_framework的序列化组件使用同fr ...
- 4)drf序列化组件 Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)
知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 一.Serializer 偏底层 一般不用 理解原理 1.序列化准备 ...
- 揭开DRF序列化技术的神秘面纱
在RESTful API中,接口返回的是JSON,JSON的内容对应的是数据库中的数据,DRF是通过序列化(Serialization)的技术,把数据模型转换为JSON的,反之,叫做反序列化(dese ...
随机推荐
- Ubuntu sudo 免密码
sudo visudo 这里默认打开的是 nano 编辑器,不习惯可以把默认编辑器换成 vim, 参考 Ubuntu 修改默认编辑器 test ALL=NOPASSWD: ALL
- golang数据结构之利用栈求计算表达式(加减乘除)
例如:3+2*6-2 先定义两个栈,一个为数值栈,一个为运算符栈: stack.go package stack import ( "errors" "fmt" ...
- mysql--事务详解
事务的四大特性: # 原子性(atomicity) 一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作 ...
- Python连载50-贪婪匹配、XPath介绍
一.贪婪和非贪婪 1.贪婪:尽可能多的匹配,(*)表示贪婪匹配 2.非贪婪:找到符合条件的最小内容即可,(?)表示非贪婪 3.正则默认使用贪婪匹配 import re title = u"& ...
- swoole4创建Mysql连接池
一 .什么是mysql连接池 场景:每秒同时有1000个并发,但是这个mysql同时只能处理400个连接,mysql会宕机. 解决方案:连接池,这个连接池建立了200个和mysql的连接,这100 ...
- 拎壶带你冲----教育类mysql用户表设计参考
说起用户表,大概是每个应用/网站立项动工(码农们)考虑的第一件事情.用户表结构的设计,算是整个后台架构的基石.如果基石不稳,待到后面需求跟进了发现不能应付,回过头来反复修改用户表,要大大小小作改动的地 ...
- 将tf-faster-rcnn检测结果画在一张图像内
https://blog.csdn.net/weixin_42111393/article/details/82940681
- EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks
增加模型精度的方法有增加网络的深度,特征图的通道数以及分辨率(如下图a-d所示).这篇文章研究了模型缩放,发现仔细平衡网络的深度.宽度和分辨率可以获得更好的性能(下图e).在此基础上,提出了一种新的缩 ...
- html的特殊符号对照表
HTML的特殊符号对照表. 特殊符号 命名实体 十进制编码 特殊符号 命名实体 十进制编码 特殊符号 命名实体 十进制编码 Α Α Α Β Β Β Γ Γ Γ Δ Δ Δ Ε Ε Ε Ζ Ζ Ζ Η ...
- 一篇短文带您了解一下EasyCaching
前言 从2017年11月11号在Github创建EasyCaching这个仓库,到现在也已经将近一年半的时间了,基本都是在下班之后和假期在完善这个项目. 由于EasyCaching目前只有英文的文档托 ...