DRF 序列化组件 模型层中参数补充
一. DRF序列化
django自带有序列化组件,但是相比rest_framework的序列化较差,所以这就不提django自带的序列化组件了。
首先rest_framework的序列化组件使用同from组件有点类似,当反序列化前端返回的数据之后,需要先调用is_valid进行校验,其中也有局部钩子validate_字段名,全局钩子validate,is_valid校验过后才可调用.data与.errors。
rest_framework有两种序列化方式,分别是继承Serializer和ModelSerializer,如果序列化的数据是多条时,一定要指定many=True,不然会报错。many=True与False的区别是前者返回列表套字典,而后者只有一个字典,即就一条数据。
from rest_framework.serializers import Serializer, ModelSerializer
1.1 继承Serializer的序列化
models.py中代码如下:
from django.db import models # Create your models here. class Book(models.Model):
title = models.CharField(max_length=32)
price = models.IntegerField()
# db_constraint=False时,一对多表只存在逻辑上的关系,处理数据无需考虑外键关系,但是依旧可以正常使用ORM
# on_delete在django1版本中默认是CASCADE,即级联删除。on_delete有四种选择,SET_NULL即外键对应一表
# 数据删除时,将该字段设置为空,需要设置null=True或default
# related_name='反向查询的依据名字'
# 外键对应的表点该依据名字.all来查询多关系表的数据,不需要表名小写+_set.all来获取
publish = models.ForeignKey("Publish", related_name='books', db_constraint=False, on_delete=models.SET_NULL, null=True)
authors = models.ManyToManyField("Author", db_constraint=False) def __str__(self):
return self.title class Publish(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField() def __str__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField() def __str__(self):
return self.name
序列化类BookSerializer如下:
class BookSerializer(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
# source的作用很强大,其中的值相当于self.publish.name,
# 当有字段使用choices属性时,可以指定source='get_字段名_display'来直接获取对应的值
# source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号
publish = serializers.CharField(source='publish.name')
# 可以指定一个函数,函数名固定get_字段名,函数return的值就是该字段的值
# read_only是反序列化时不传,write_only是序列化时不显示
author_detail = serializers.SerializerMethodField(read_only=True) # 该函数return的值就是author_detail字段的值
def get_author_detail(self, book_obj):
authors = book_obj.authors.all()
# 函数内部可以直接调用其他序列化类
return AuthorSerializer(authors, many=True).data # 局部钩子
def validate_title(self, value): # value是当前的title的值
from rest_framework import exceptions
if 'h' in value:
# 这是将校验未通过的信息存入序列化obj.errors中
raise exceptions.ValidationError('h是不可能h的')
return value # 全局钩子
def validate(self, attrs): # attrs是包含了所有字段及数据的字典
from rest_framework import exceptions
if attrs.get('title') == attrs.get('price'):
return attrs
else:
raise exceptions.ValidationError('书名怎么和价格一样')
注意,无论是局部钩子还是全局钩子函数,都要序列化对象走is_valid方法时才会触发,而且全局要所有需要序列化的字段通过校验才会触发。
上述需要的AuthorSerializer如下:
# 作者Author序列化类
class AuthorSerializer(serializers.Serializer):
name = serializers.CharField(max_length=32)
age = serializers.IntegerField()
在表中写入数据后,在视图views.py中写CBV继承ListAPIView:
from rest_framework.generics import ListAPIView
from app01 import models
from app01 import app01serializers
# Create your views here. class BookAPIView(ListAPIView):
queryset = models.Book.objects
serializer_class = app01serializers.BookSerializer
然后开路由:
from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^books/', views.BookAPIView.as_view()),
]
随后用postman测试该接口:
这里要注意,如果是前端往后端提交post请求创建新的数据时,要反序列化,然后调用is_valid校验数据,之后才能调用.dada与.errors。因为继承Serializer是没有指定表的,我们需要在对应的序列化类中重写create方法,将.dada当create的参数传入,然后create中写保存的逻辑,如果涉及到多表,那么要全靠自己逻辑去写了,在视图中执行is_valid前将其他表需要的参数取出执行保存操作即可。
反序列时需要把将参数指定给data:
bs=BookSerializer(data=request.data)
如果intence参数和data参数都给予了值,那么会执行更新操作:
def put(self, request, pk):
book_obj = models.Book.objects.filter(pk=pk).first() bs=BookSerializers(data=request.data, instance=book_obj)
if bs.is_valid():
bs.save() # update
return Response(bs.data)
else:
return Response(bs.errors)
1.2 继承ModelSerializer的序列化
继承Modelserializer的序列化比较方便,因为不需要逐个写字段及字段的类型等。
序列化类如下:
class BookSerializer(serializers.ModelSerializer):
# 生成publish_detail的第三种方式
publish = PublishSerializer() class Meta:
model = models.Book
# fields = '__all__' 所有字段序列化,不过一般我们不会使用该方式
# 一般采用下列方式,里面可以填表拥有的字段,
# 也可以写该表中外键字段、多对多表正向或反向对应点语法采用的字段
# 其中反向查询时我们一般采用.表名小写的方式,可以在Foreign中设置字段related_name='反向查询点语法后的名称'
# 比如Book表中外键字段publish设置属性related_name='books',那么Publish表反向查询书籍时,
# .books_all()即可拿到该出版社出版的所有书籍对象(不然要写.book_set.all())
fields = ['title', 'price', 'publish', 'author_detail']
# exclude=('title',) #拿出除了title的所有字段,不能跟fields同时用
# depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层
继承ModelSerializer的类也可以写全局钩子、局部钩子,以及对字段进行处理,不过已订购要写在class Meta的外面。
fields中可以写模型表带有的字段,包含外键字段及ManyToMany字段,当指定了related_name时,反向查询的表可以写related_name指定的名字来访问另一张表。
这里提一嘴,rest_framework提供了深度属性depth,但是不建议使用,因为不可控性太强。一般涉及到多表时,我们都在模型表中进行,比如此处的author_detail,是多对多关系表中book对应的所有author对象,我们在Book模型表中增加以下方法:
@property
def author_detail(self):
result_list = []
authors = self.authors.all()
for author in authors:
dic = {'name': author.name, 'age': author.age}
result_list.append(dic)
return result_list
上面publish也可以在模型表中定义,比如写publish_detail:
# 生成publish_detail方式一
@property
def publish_detail(self):
publish_obj = self.publish
return {'name': publish_obj.name, 'email': publish_obj.email} # 生成publish_detail方式二
@property
def publish_detail(self):
from app01 import app01serializers
publish_obj = self.publish
return app01serializers.PublishSerializer(publish_obj).data
然后将序列化类中的publish改为publish_detail,用postman测试接口:
结果是一样的,继承ModelSerializer因为需要指定模型表,所有不需要重写create方法,直接调用.save方法即可。
1.3 模型层中参数的补充
比如当我们创建外键关系与多对多关系表时,django 1.x版本默认都是级联删除的,即on_delete=CASCADE,而django 2.x版本需要自己指定。
on_delete一共有四个值可以选择:
1. on_delete = models.SET_NULL # 关联表字段删除后,该ForeignKey字段的值置为空,需要设置null=True或者是设置default
2. on_delete = models.SET_DEFAULT # 关联表字段删除后,该ForeignKey字段的值置为默认值,需要设置default字段
3. on_delete = models.DO_NOTHING # 关联表字段删除后,该ForeignKey字段的值不变
4. on_delete = models.CASCADE # 关联表字段删除后,级联删除
Foreign与ManyToMany字段还有db_constraint与related_name字段。指定db_constraint=False时,一对多的表只存在逻辑上的关系(此时数据库如navicat中表关系图它们之间的线会断开),处理数据无需考虑外键关系,不过依旧可以使用ORM正常操作正反向查询等。
指定related_name字段时,反向查询无需按表名小写的方式,直接点该related_name定义的字段即可。举例,比如Book表与Author表一对多,外键在Book表中,那么Author查询Book表的数据就是反向查询,需要author_obj.book_set.all()获取作者对应的所有书籍数据。这时指定related_name='books',那么只需采用author_obj.books.all()即可。
如果不清楚可以再看看该博客:https://www.cnblogs.com/liuqingzheng/articles/9766376.html
DRF 序列化组件 模型层中参数补充的更多相关文章
- DRF 序列化组件
Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...
- DRF 序列化组件 序列化的两种方式 反序列化 反序列化的校验
序列化组件 django自带的有序列化组件不过不可控不建议使用(了解) from django.core import serializers class Books(APIView): def ge ...
- 4)drf序列化组件 Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)
知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 一.Serializer 偏底层 一般不用 理解原理 1.序列化准备 ...
- cvb源码分析,resful规范,drf,drf序列化组件,95
1 CBV的源码分析 -Class Base View(基于类的视图) -Function Base View(基于函数的视图) -def as_view 类方法 -def view:类方法内部,闭包 ...
- DRF 序列化组件单增
目录 自定义序列化(矬) Serializer类(方式繁琐) 底层序列化类 UserSerializer 视图序列化步骤 底层反序列化类 UserCreatSerializer 视图反序列化步骤 Mo ...
- DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...
- Django中模型层中ORM的单表操作
ORM概念: MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员 ...
- drf序列化组件
rest_framework序列化之Serializer 步骤: 1.自定义一个类,继承Serializer类: 2.在类中写要序列化的字段: 3.使用:在views.py文件中,book_ser=B ...
- Django中模型层中ORM的多表操作
ORM的多表创建(一对一.一对多,多对多): 1模型创建 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等 ...
随机推荐
- 招聘,api、app、web自动化,性能,持续集成,其他
招聘: api接口自动化测试 app功能自动化测试 web功能自动化测试 性能测试 自动化平台与持续集成 其他
- Vue1.0用法详解
Vue.js 不支持 IE8 及其以下版本,因为 Vue.js 使用了 IE8 不能实现的 ECMAScript 5 特性. 开发环境部署 可参考使用 vue+webpack. 基本用法 1 2 3 ...
- 从未来看 C#
前言 如今 C# 虽然发展到了 8.0 版本,引入了诸多的函数式特性,但其实在 C# 未来的规划当中,还有很多足以大规模影响现有 C# 代码结构和组成的特性,本文中将会对就重要的特性进行介绍,并用代码 ...
- CSS——NO.10(设置技巧)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- 如何看待Java是世界上最好的语言?
Java出现二十多年以来,一直都是主流的开发语言,Java创建于 1995 年,在 20多年的发展历程中,Java 已经证明自己是用于自定义软件开发的顶级通用编程语言. Java 广泛应用于科学教育. ...
- swagger 以及swaggerUI使用的步骤
1.swagger,可以这么理解swagger是接口规范.Rest Api 传递参数的除了get请求外,put post,需要传递json.或者就是直接都通过传递json到后台 这里主要介绍一下spr ...
- ef01
1.ef简介 学习地址: https://www.entityframeworktutorial.net/ orm:Object relations mapping 对象关系映射 实体类中的属性与数据 ...
- elasticsearch 单机安装
一.elasticsearch下载 1.elastic 官网:https://www.elastic.co/cn/ 2.elasticsearch 下载地址:https://www.elastic.c ...
- OpenGL 实践之贝塞尔曲线绘制
说到贝塞尔曲线,大家肯定都不陌生,网上有很多关于介绍和理解贝塞尔曲线的优秀文章和动态图. 以下两个是比较经典的动图了. 二阶贝塞尔曲线: 三阶贝塞尔曲线: 由于在工作中经常要和贝塞尔曲线打交道,所以简 ...
- MySQL使用前查看状态
1.检查MySQL服务器是否启动:ps -ef | grep mysqld 如果MySql已经启动,以上命令将输出mysql进程列表,如下所示:mysql下一行 如果mysql未启动,你可以使用以下命 ...