为什么要用序列化

当我们做前后端分离的项目时,前后端交互一般都是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. ubuntu下使用redshift开启护眼模式

    前面提到flux这东西在一些机器上并不能work,而且也找到了一些关于他不能work的线索(戳这里看原因).根据这些线索我们发现用flux不行了,得换用redshift,那好吧,我们就来装redshi ...

  2. Spring Cloud 教程

    Spring Cloud系列教程: Spring Boot + Spring Cloud 构建微服务系统(一):服务注册和发现(Consul) Spring Boot + Spring Cloud 构 ...

  3. oracle查询字段重复数据

    select in_ordr_no,count(*) from t_pay_jnl group by in_ordr_no having count(*) > 按照字段in_ordr_no查询重 ...

  4. matlab中的colormap

    matlab colormaps 默认颜色图是 parula ,颜色图从左往右数值不断增大. 颜色图名称 色阶 parula jet hsv hot cool spring summer autumn ...

  5. DirectShow 应用开发过程

    本文准备总结一些 Direct Show 常用的API接口函数,方便以后查询回忆.如果这里没有你想了解的函数,你可以自行搜索MSDN + 函数名去 MSDN 查找你想要了解的函数,也可以查看百度百科相 ...

  6. 用OC基于链表实现链队列

    一.简言 在前面已经用C++介绍过链队列的基本算法,可以去回顾一下https://www.cnblogs.com/XYQ-208910/p/11692065.html.少说多做,还是上手撸代码实践一下 ...

  7. Python自动群发邮件,只需20行代码!

    今日分享 Python自动群发邮件 import smtplib from email import (header) from email.mime import (text, applicatio ...

  8. swoole的process模块创建和使用子进程

    swoole中为我们提供了一个进程管理模块 Process,替换PHP的 pcntl 扩展,方便我们创建进程,管理进程,和进程间的通信. swoole提供了2种进程间的通信: 1.基于 unix so ...

  9. Maven设置本地仓和阿里云远程仓

    在maven项目导入jar包坐标时需要连接maven官方仓库下载,但是下载速度感人,所以来修改一下设置. 设置成为本地仓和连接阿里云的远程仓库. (本地仓如果没有这个jar) 找出相应配置文件:例如我 ...

  10. node开发基础概念

    1.以严格模式运行一个js文件 node --use_strict xxx.js 2.退出node交互模式 连续按两次Ctrl+C. 3,node.js的模块不支持ES6的export.import规 ...