为什么要用序列化

当我们做前后端分离的项目时,前后端交互一般都是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--序列化的更多相关文章

  1. DRF 序列化组件

    Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...

  2. python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)

    昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...

  3. python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)

    昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...

  4. Django的DRF序列化方法

    安装rest_framework -- pip install djangorestframework -- 注册rest_framework序列化 -- Python--json -- 第一版 用v ...

  5. drf序列化器与反序列化

    什么是序列化与反序列化 """ 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 """ drf序列化与反序列化 &qu ...

  6. drf序列化及反序列化

    假如把drf看做一个汉堡包,我们之前讲的模块属于汉堡包前面的盖盖(请求模块.渲染模块)和底底(异常模块.解析模块.响应模块),但是真正中间的夹心没有讲,那么今天我就和大家来看一下汉堡包的夹心(序列化及 ...

  7. drf序列化和反序列化

    目录 drf序列化和反序列化 一.自定义序列化 1.1 设置国际化 二.通过视图类的序列化和反序列化 三.ModelSerializer类实现序列化和反序列化 drf序列化和反序列化 一.自定义序列化 ...

  8. DRF 序列化组件 模型层中参数补充

    一. DRF序列化 django自带有序列化组件,但是相比rest_framework的序列化较差,所以这就不提django自带的序列化组件了. 首先rest_framework的序列化组件使用同fr ...

  9. 4)drf序列化组件 Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)

    知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 一.Serializer 偏底层 一般不用 理解原理 1.序列化准备 ...

  10. 揭开DRF序列化技术的神秘面纱

    在RESTful API中,接口返回的是JSON,JSON的内容对应的是数据库中的数据,DRF是通过序列化(Serialization)的技术,把数据模型转换为JSON的,反之,叫做反序列化(dese ...

随机推荐

  1. pytorch基础-搭建网络

    搭建网络的步骤大致为以下: 1.准备数据 2. 定义网络结构model 3. 定义损失函数4. 定义优化算法 optimizer5. 训练 5.1 准备好tensor形式的输入数据和标签(可选) 5. ...

  2. React: 研究React的组件化

    一.简介大概 在以往的Web开发中,会把web页面所有的复杂控件作为一个单一的整体进行开发,由于控件之间需要进行通信,因此不同的组件之间的耦合度会很多,由于开发一个控件的时候要考虑到控件与控件之间的联 ...

  3. React中useEffect使用

    2019-08-24 07:00:00 文摘资讯 阅读数 1364  收藏 博文的原始地址     之前我们已经掌握了useState的使用,在 class 中,我们通过在构造函数中设置 this.s ...

  4. python TKinter的主窗口运行程序完毕后,怎么让其自动关闭

    如题: 在pycharm 调试Tkinter程序的时候,关闭右上角的X 实际上并未退出进程,长期以往 再大的内存也会被耗尽. 一般就是下面的代码: """ from tk ...

  5. 华为mate10 pro内置浏览器出现的令人头疼的样式兼容问题

    问题描述:   下图红色框区域内容在华为mate10 pro(以下简称mate10)内置浏览器中整体向左偏移,没有居中,其它手机浏览器都无该问题,如下图 问题分析   经过一番追根溯源,我发现是 bo ...

  6. hyper-v Centos7 网卡配置无效

    环境: Win 10 Hyper-v 安装虚拟机:Centos 7 遇到问题: 网络配置无效,使用命令“ip addr” 网卡没有出现在列表中,显示了一个奇怪的网卡名字如“enp0s010f”,配置文 ...

  7. javascript检索某个字符或字符串在源字符串中的位置(下标)

    indexOf()方法 JavaScript中的String对象提供了一个indexOf(searchValue, fromIndex)方法用于检索某个字符或字符串在源字符串中第一次出现的位置(下标) ...

  8. Java开发桌面程序学习(四)——常用应用布局模板和简单分析

    布局 前言 刚开始的时候,不知道使用什么布局,发现SceneBuilder其实有8.5版本的,里面就是有提供一个简单的桌面程序模板,8.5可以去官网下载,不过网速好像有点慢,慢慢等吧,官网下载地址 布 ...

  9. VS2019安装好后,经常打不开软件没反应解决方法

    原文地址:https://blog.csdn.net/FL1623863129/article/details/89013137 VS2019于昨日正式发布,博主立马下载一个专业版尝尝鲜,但是发现项目 ...

  10. HC595驱动数码管

    74HC595是一个8位串行输入.并行输出的位移缓存器 引脚定义 Q0~Q7:并行输出 Q7':串行输出 SH_CP:移位寄存器时钟输入 ST_CP:存储寄存器时钟输入 DS:串行输入 原理图 举例 ...