Django REST Framework序列化器
Django序列化和json模块的序列化
从数据库中取出数据后,虽然不能直接将queryset和model对象以及datetime类型序列化,但都可以将其转化成可以序列化的类型,再序列化。
功能需求都能做到,但是比较麻烦,每次需要手动实现。且取出的数据还需要进行转化,比如某些字段在存储时将汉字转化成数字,取出来后要将数字转化成汉字,这都是需要每次手动操作。
Django REST Framework序列化
作用:
- 对数据库中取出的数据序列化
- 字段值的转化(包括choice、外键、一对一关系、多对多关系)
- 字段验证(自动验证和自定义验证)
models.py
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="图书名称")
CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
category = models.IntegerField(choices=CHOICES, verbose_name="图书的类别")
pub_time = models.DateField(verbose_name="图书的出版日期") publisher = models.ForeignKey(to="Publisher", on_delete=None)
author = models.ManyToManyField(to="Author") def __str__(self):
return self.title class Meta:
verbose_name_plural = "Book"
db_table = verbose_name_plural class Publisher(models.Model):
title = models.CharField(max_length=32, verbose_name="出版社的名称") def __str__(self):
return self.title class Meta:
verbose_name_plural = "Publisher"
db_table = verbose_name_plural class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者的姓名") def __str__(self):
return self.name class Meta:
verbose_name_plural = "Author"
db_table = verbose_name_plural
serializers.Serializer序列化
views.py
from .seriallzers import BookSeriallzer # 自定义的问加减
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
ret = BookSeriallzer(book_list, many=True) # 序列化过程
return Response(ret.data)
def post(self, request):
print("数据",request.data)
serializer = BookSeriallzer(data=request.data) # 反序列化
if serializer.is_valid():
print("验证通过")
serializer.save() # save()方法保存数据库,需要在序列化器里自定义create方法
return Response(serializer.data)
else:
return Response(serializer.errors)
seriallzers.py
from rest_framework import serializers def my_validate(value):
if "mingan" in value.lower():
raise serializers.ValidationError("不能含有敏感信息")
else:
return value class BookSeriallzer(serializers.Serializer):
id = serializers.IntegerField(required=False) # required False的意思是 反序列化(存库)的时候非必需
title = serializers.CharField(max_length=32, validators=[my_validate]) # 此种验证方式比局部钩子优先级高
CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display", read_only=True) # 只在序列化(读库)的时候起作用
w_category = serializers.ChoiceField(choices=CHOICES, write_only=True) # 只在反序列化的时候用(存库)
pub_time = serializers.DateField() publisher = PublishSeriallzer(read_only=True)
publisher_id = serializers.IntegerField(write_only=True) author = AuthorSeriallzer(many=True, read_only=True) # 通过many参数来区别是普通外键还是多对多关系
author_list = serializers.ListField(write_only=True) def create(self, validated_data):
book = Book.objects.create(title=validated_data["title"],category=validated_data["w_category"],
pub_time=validated_data["pub_time"], publisher_id=validated_data["publisher_id"])
book.author.add(*validated_data["author_list"])
return book def update(self, instance, validated_data):
"instance是views函数中传来的book_obj"
instance.title = validated_data.get("title", instance.title) # 如果已验证的数据中没有title字段,不更新,不会报错
instance.category = validated_data.get("w_category", instance.category)
instance.pub_time = validated_data.get("pub_time", instance.pub_time)
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 def validate_title(self, value):
"局部钩子,自定义对title字段的验证"
if "python" not in value.lower():
raise serializers.ValidationError("标题必须含有python")
return value def validate(self, attrs):
"全局的校验规则,可以进行多字段联合校验"
if attrs["w_category"] == 1 and attrs["publisher_id"] == 1:
return attrs
else:
raise serializers.ValidationError("分类以及标题不符合要求")
验证顺序:validators属性 -> 局部钩子 -> 全局钩子
这样就实现了 序列化 和 反序列化的过程,包括特殊字段(时间类型、外键关系、chioce)转化以及存库时的验证。
需要说明的是:
- choice字段、外键由于存取的需求不一致(存数字,取汉字、外键对应的其它字段),需要将序列化和反序列化的过程区分开来,分成两个变量名。用read_only和write_only区分
- 验证发生在反序列化的过程(存库),会自动验证字段类型、必填属性、长度等条件。
- 自定义验证有三种方式,要注意先后顺序。
但是,序列化和反序列化的过程非常不简洁,写了太多的东西。
serializers.ModelSerializer序列化
ModelSerializer类可以与ORM映射表结合,自动对应序列化关系。
from .models import Book, Publisher class BookSeriallzer(serializers.ModelSerializer):
category_display = serializers.SerializerMethodField() # 读取数据时的字段名(与"category"区分开来,下同)
publisher_info = serializers.SerializerMethodField() # 配合 get_字段名() 钩子,自定义通过外键取出的字段
authors = serializers.SerializerMethodField() def get_category_display(self, obj):
return obj.get_category_display() def get_publisher_info(self, obj):
# obj 是每个book对象
publisher_obj = obj.publisher
return {"id": publisher_obj.id, "title": publisher_obj.title} # 只取出来自己想要的数据,不会有其他的冗余数据 def get_authors(self, obj):
authors = obj.author.all()
return [{"id": author.id, "name": author.name} for author in authors] class Meta:
model = Book # 对应ORM表
# fields = ["id", "title", "pub_time", "category"] # 需要取出的字段
fields = "__all__" # 表示要取出所有字段
# depth = 1 # 序列化的外键层级。如果不规定此值,所有的外键字段都只是id。有个缺点:会取出外键对应的所有数据,非常冗余
extra_kwargs = {
"category": {"write_only": True}, # “category”字段只写
"publisher": {"write_only": True},
"author": {"write_only": True}
}
这样,我们只需要将存取不一致的行为定义好即可,其它字段都可以自动对应好。非常方便。
Django REST Framework序列化器的更多相关文章
- [Django REST framework - 序列化组件、source、钩子函数]
[Django REST framework - 序列化组件.source.钩子函数] 序列化器-Serializer 什么是rest_framework序列化? 在写前后端不分离的项目时: 我们有f ...
- Django REST framework - 解析器和渲染器
目录 Django REST framework - 解析器和渲染器 解析器 Django中的数据解析 DRF中的解析器 渲染器 Django REST framework - 解析器和渲染器 解析器 ...
- Django 学习之Django Rest Framework_序列化器_Serializer
作用: 1.序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串. 2.反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型. 3 ...
- Django REST framework序列化
一.简介 Django REST framework是基于Django实现的一个RESTful风格API框架,能够帮助我们快速开发RESTful风格的API. 官网:https://www.djang ...
- Django REST Framework 序列化和校验 知识点
DRF序列化 Django ORM对象 --> JSON格式的数据 序列化 JSON格式的数据 --> Django ORM数据 反序列化 需要两个工具: from rest_framew ...
- Django Rest framework序列化流程
目录 一 什么是序列化 二 Django REST framework配置流程之Serializer 三 Django REST framework配置流程之ModelSerializer 一 什么是 ...
- Django:RestFramework之-------序列化器
8.序列化 功能: 对请求数据进行验证 对Queryset进行序列化 8.1一个简单序列化: import json from api import models from rest_framewor ...
- django rest framework 解析器组件 接口设计,视图组件 (1)
一.解析器组件 -解析器组件是用来解析用户请求数据的(application/json), content-type 将客户端发来的json数据进行解析 -必须适应APIView -request.d ...
- 02 Django REST Framework 序列化
01-创建序列化类 # 方式一: publish_list = models.Publish.objects.all() # 导入序列化组件 from django.core import seria ...
随机推荐
- Unity进阶:行为树 02 夺旗战搭建场景,AI脚本,旗子拿起
版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...
- Unity之与Web的交互
一.下载,安装,配置,启动Apache 1.进入官网下载Apache 2.解压到根目录 3.记事本打开如下配置文件 4.安装apache 5.出现错误:(该错误是由于端口被占用引起的) 6.修改配置文 ...
- Java并发编程——线程池的使用
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...
- 分布式任务调度框架 Azkaban —— Flow 1.0 的使用
一.简介 Azkaban 主要通过界面上传配置文件来进行任务的调度.它有两个重要的概念: Job: 你需要执行的调度任务: Flow:一个获取多个 Job 及它们之间的依赖关系所组成的图表叫做 Flo ...
- CF-920C-Swap Adjacent Elements 贪心
题意 给你一个1-n的排列. 并给你一个字符串——其中用0和1表示对应数列中的位置上的值可不可以和后面相邻的数交换. 判断该数列能否在限制中交换为不降序数列. 思路 由于刚学了树状数组,一开始以为是用 ...
- poj 3468 A Simple Problem with Integers(原来是一道简单的线段树区间修改用来练练splay)
题目链接:http://poj.org/problem?id=3468 题解:splay功能比线段树强大当然代价就是有些操作比线段树慢,这题用splay实现的比线段树慢上一倍.线段树用lazy标记差不 ...
- 杭电多校第九场 D Rikka with Stone-Paper-Scissors 数学
Rikka with Stone-Paper-Scissors Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/52428 ...
- bzoj 2726 任务安排 斜率优化DP
这个题目中 斜率优化DP相当于存在一个 y = kx + z 然后给定 n 个对点 (x,y) 然后给你一个k, 要求你维护出这个z最小是多少. 那么对于给定的点来说 我们可以维护出一个下凸壳,因为 ...
- CF994B Knights of a Polygonal Table 第一道 贪心 set/multiset的用法
Knights of a Polygonal Table time limit per test 1 second memory limit per test 256 megabytes input ...
- 【Offer】[11] 【旋转数组的最小元素】
题目描述 思路分析 Java代码 代码链接 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4, ...