序列化组件

django自带的有序列化组件不过不可控不建议使用(了解)

from django.core import serializers 

class Books(APIView):
def get(self,request):
response = {'code':100,'msg':'查询成功'}
books = models.Book.objects.all()
# 了解django自带的序列化组件
ret= serializers.serialize("json",books)
return HttpResponse(ret)

使用drf的序列化组件

  自定义py文件里为了和view视图函数隔离开 自定义文件中写serializer组件

    1 新建一个序列化类继承Serializer   2  在类中写序列化的字段

      source='表中字段'  自定义的字段不能和表中的字段名一样 username=serializer.CharField(source='name')  username自定义的字段 source指定的是表中的字段

      要序列化的对象默认传给instance 视图函数中的instance可以不写  

      source可以写跨表字段'publish.name'  之前跨表是book.publish.name 现在用source就可以省略book了 写成publish.name  

      source不但可以指定一个字段 还可以指定一个方法

#自定义的py文件中

from rest_framework import serializers    #序列化组件

class BookSerializer(serializers.Serializer):
# 指定source = 'name' 表示序列化模型表中的name字段 重命名为name5(name5这个字段名 和source=’name'指定的模型表中的name字段名不能一样)
name5 = serializers.CharField(source='name')
# write_only 序列化的时候,该字段前端不显示
# read_only 反序列化的时候,该字段不传 前端传过来的时候可以不传参数或者字段
price = serializers.CharField(write_only=True) #如果要取 出版社的city 之前跨表查询是 book.publish.city 现在 source = 'publish.city' 不需要点击本身这张表的字段了
# source的值传给了默认形参instance
publish = serializers.CharField(source='publish.name') #出版社名字 #source不但可以指定一个字段,还可以指定一个方法  自定义choices字段取值固定用法get_字段_display
book_type = serializers.CharField(source='get_category_display',read_only=True)
#model.py模型表
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
category = models.IntegerField(choices=((0,'文学类'),(1,'情感类')),default=1,null=True)
publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE,null=True)
authors = models.ManyToManyField(to='Author') def __str__(self):
return self.name def test(self):
return '方法'

  在视图中使用序列化的类

     实例化序列化的类产生对象,在产生对象的时候,传入需要序列化的对象 

    对象.data    

     return Response(对象.data) 返回值用Response返回

       如果序列化多条 many=True(也就是queryset对象,就需要写many=True)  如果序列化一条(可以不用写many=False默认就是False)instance是要序列化的对象

     

from app01.app01serializer import BookSerializer    #自定义的py文件下的序列化组件
from rest_framework.response import Response #返回用的 class Books(APIView):
def get(self,request):
response = {'code':100,'msg':'查询成功'}
books = models.Book.objects.all() bookser = BookSerializer(instance=books,many=True)
# 如果序列化多条,many=True(也就是queryset对象,就需要写)
print(bookser.data,type(bookser.data))
response['data'] = bookser.data
return Response(response)

    SerializerMethodField 对应着一个方法:get_字段名 方法返回值是什么该字段就是什么  write_only 反序列化的时候该字段前端不显示  read_only 反序列化的时候前端可以不传这个字段

自定义py文件下的序列化组件 类下

from rest_framework import serializers  # 序列化组件
from app01 import models class BookSerializer(serializers.Serializer):
#序列化出版社的详情,指定SerializerMethodField之后,可以对应一个方法,返回什么内容,publish_detail就是什么内容
publish_detail = serializers.SerializerMethodField(read_only=True)
#对应的方法固定写法get_字段名
def get_publish_detail(self,obj): #这个obj 就是app01.models.Book
print(obj,type(obj))
return {'name':obj.publish.name,'city':obj.publish.city} # 返回所有作者信息
authors = serializers.SerializerMethodField(read_only=True)
def get_authors(self,obj):
return [{'name':author.name,'age':author.age} for author in obj.authors.all()]
序列化的两种方式

1 Serializers没有指定表模型

  source:指定要序列化那个字段,可以是字段,可以是方法

  SerializerMethodFields的用法

方式1:
authors = serializer.SerializerMethodField()
def get_authors(self,obj):
return {'name':obj.publish.name,'city':obj.publish.city}
#拓展性差 如果要查询一张表完整数据 那要写很多kv键值对 方式2:
class AuthorSerializer(serializer.Serializer):
name = serializer.CharField()
age = serializer.CharField() authors = serializer.SerializerMethodField()
def get_authors(self,obj):
ret = AuthorSerializer(instance=obj.authors.all(),man=True) #instance是默认参数可以不写
return ret.data

2 ModelSerializers:指定了表模型

  class Meta:  model=表模型  fields = ('__all__')显示所有的字段  fields = ('id','name')显示部分字段  exclude=['name'] 排除这个字段其他内容都显示 不能和fields同时使用  depth=1跨表深度是1,官方建议不要超过10,个人建议不要超过3  重写某个字段 在Meta外部,重写某些字段,方式同Serializers

class AuthorSerializer(serializers.Serializer):
name = serializers.CharField()
age = serializers.CharField()
# class Meta:
# fields = ('__all__') serializers木有这个meta方法 只有modelserializer有 class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book #哪一张模型表
# fields = ('nid','name') #显示的字段
fields = ('__all__') #显示所有字段信息
# exclude = ['name'] #排除
# depth=1
# 深度是1,官方建议不要超过10,个人建议不要超过3
category = serializers.CharField(source='get_category_display')
authors = serializers.SerializerMethodField()
def get_authors(self,obj):
# 可以写列表生成式 如果是很多的话就要在生成式里面写很多 而且拓展性很差 可以继续写serializer
ret=AuthorSerializer(instance=obj.authors.all(),many=True)
return ret.data name5= serializers.CharField(source='name') #重写name字段 与meta同级别 方式和Serializers重写或者序列化组件一样

反序列化

1 使用继承了Serializers序列化类的对象,反序列化  

  json格式转成对象,保存到数据库

  在保存之前一定要先调用  对象.is_valid()方法

  在自己写的序列化类中重写create方法,反序列化  

  重写create放法,实现序列化(根据业务需求具体实现还是自定义create方法)

  在序列化类中:  序列化类中写create方法表里面需要什么字段还是要传什么字段

from rest_framework import serializers  # 序列化组件
class BookSerializer(serializers.Serializer):
#反序列化创建
def create(self, validated_data):
ret = models.Book.objects.create(**validated_data)
return ret

  在视图中:

from app01.app01serializer import BookSerializer    #自定义py文件里为了和view视图函数隔离开 自定义文件就写serializer组件

class Books(APIView):
#使用Serializers序列化类的对象,反序列化
def post(self,request):
#实例化产生一个序列化类的对象,data是要反序列化的字典
bookser = BookSerializer(data=request.data)
if bookser.is_valid():
#清洗通过的数据
ret = bookser.create(bookser.validated_data)
return Response()

2 使用继承了ModelSerializers序列化类的对象,反序列化

  json格式转成对象,保存到数据库

  在保存之前一定要先调用  对象.is_valid()

  在视图中  在视图中写save() 表里面需要什么字段还是要传什么字段

from django.shortcuts import render,HttpResponse,redirect

from rest_framework.views import APIView
from app01 import models from rest_framework.response import Response #返回用的 # 把对象转成json格式字符串
from app01.app01serializer import BookSerializer #自定义py文件里为了和view视图函数隔离开 自定义文件就写serializer组件 class Books(APIView): # 使用继承了ModelSerializers序列化类的对象,反序列化
def post(self,request):
#实例化产生一个序列化类的对象,data是要反序列的字典
bookser = BookSerializer(data=request.data)
if bookser.is_valid(raise_exception=True): #抛出的异常有异常就返回了 下面代码不执行 可以不写if判断
#清洗通过的数据
bookser.save()
反序列化的校验

反序列化的校验局部校验   validate_字段名(self,value):

  如果校验失败,抛出ValidationError(抛出的异常信息需要去视图层bookser.errors中取)

  如果校验通过直接return value

from rest_framework import exceptions

序列化类下面写:
#反序列化的校验(局部校验,全局校验)
def validate_name(self,value): print(value)
raise exceptions.ValidationError('不能以sb开头')
# if value.startswith('sb'):
# raise ValidationError('不能以sb开头')
# return value
视图层 post请求内    校验错误信息
def post(self,request):
#实例化产生一个序列化类的对象,data是要反序列化的字典
bookser=BookSerializer(data=request.data)
# bookser.data
if bookser.is_valid(raise_exception=True):  有异常就直接返回了 下面代码不会被执行 如果执行说明已经通过了
#清洗通过的数据
bookser.save()
else:
print(bookser.errors['name'][0])
return Response()

反序列化的校验全局  validate(self,attrs)  attrs所有校验通过的数据,是个字典  如果校验失败,抛出ValidationError  如果校验通过直接返回return attrs

序列化组件类中
#去局校验
def validate(self,attrs):
print(attrs) return attrs
读源码分析

全局和局部钩子源码部分

调用了bookser.is_valid方法才走校验---》Serlizer(没有is_valid)->BaseSerializer(is_valid) 走了self.run_validtaion方法(先从自身找)

(在Serializer找到)self.run_validation方法

  

Serializer中找to_internal_value

  

  找所有的字段于是就执行了局部校验的函数

全局校验

走自身的这个方法(Serializer的)

run_validators方法super继承run_validators--->BaseSerializer没有找--->Field中有这个方法 run_validators

然后全局校验的第一步走完了

在序列化的时候,传many=True和many=False,生成的对象并不是一个对象  Serializer中的基类BaseSerializer中的__new__

序列化对象.data 的时候做了什么事?

执行了Serializer内的data方法

又执行了父类(BaserSerializer)的data方法

其实执行的是Serializer内的to_representation方法

最终执行的是每个字段对象的get_attribute方法    

Serializer---》BaseSerializer ---》Field --》

self.source_attrs  Field类自己的方法

每个字段source后面指定的根据  点  切分  切分后的列表(publish.name:就会被分成[publish,name])

如果是方法会执行方法,如果是字段,通过反射取出值

Field类里面的方法

instance 当前序列化的对象(从data方法中看到self.instance就是当前序列化)

从BaseSerializer data中

而BaseSerializer初始化的时候

DRF 序列化组件 序列化的两种方式 反序列化 反序列化的校验的更多相关文章

  1. React组件导入的两种方式(动态导入组件的实现)

    一. react组件两种导入方式 React组件可以通过两种方式导入另一个组件 import(常用) import component from './component' require const ...

  2. vue实现组件切换的两种方式

    <!DOCTYPE html> <html> <head> <title>组件的切换</title> <meta charset=&q ...

  3. vue之provide和inject跨组件传递属性值失败(父组件向子组件传值的两种方式)

    简单介绍:当一个子组件需要用到父组件的父组件的某些参数.那么这个时候为了避免组件重复传参,使用vue的依赖注入是个不错的方法,直接在最外层组件设置一个provide,内部不管多少嵌套都可以直接取到最外 ...

  4. Django学习——ajax发送其他请求、上传文件(ajax和form两种方式)、ajax上传json格式、 Django内置序列化(了解)、分页器的使用

    1 ajax发送其他请求 1 写在form表单 submit和button会触发提交 <form action=""> </form> 注释 2 使用inp ...

  5. java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))

    Java提高篇--对象克隆(复制)(转自:http://www.cnblogs.com/Qian123/p/5710533.html#_label0)   阅读目录 为什么要克隆? 如何实现克隆 浅克 ...

  6. K:java中序列化的两种方式—Serializable或Externalizable

    在java中,对一个对象进行序列化操作,其有如下两种方式: 第一种: 通过实现java.io.Serializable接口,该接口是一个标志接口,其没有任何抽象方法需要进行重写,实现了Serializ ...

  7. 一步步分析Java深拷贝的两种方式-clone和序列化

    今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clon ...

  8. react学习笔记1之声明组件的两种方式

    //定义组件有两种方式,函数和类 function Welcome(props) { return <h1>Hello, {props.name}</h1>; } class ...

  9. 使用react定义组件的两种方式

    react组件的两种方式:函数定义,类定义 在定义一个组件之前,首先要明白一点:react元素(jsx)是react组件的最基本的组成单位 组件要求: 1,为了和react元素进行区分,组件名字首必须 ...

随机推荐

  1. nginx变量与实列

    nginx内置变量 内置变量存放在  ngx_http_core_module 模块中,变量的命名方式和apache 服务器变量是一致的.总而言之,这些变量代表着客户端请求头的内容,例如$http_u ...

  2. Python基础之range()

    range:指定范围,生成指定数字. 1. range() for i in range(1, 10): print(i) 执行结果为: 1 2 3 4 5 6 7 8 9 2. range()步长 ...

  3. HDFS 特殊权限位

    HDFS 特殊权限位 标签(空格分隔): Hadoop 之前对HDFS更或者说是对Linux中文件的权限没有进行一个完整的学习,只是知道有所有者.所属组和其它权限,具体到某个人的权限有读(r).写(w ...

  4. 论一种基于JS技术的WEB前端动态生成框图的方法

    前言 HTML是一种标记语言,由HTML的标签元素和文本编写的文档可被浏览器描述为一幅网页.通常情况下网页的实现是由HTML.CSS和Javascript三者结合完成的,HTML负责网页的结构,CSS ...

  5. linux环境中关闭tomcat,通过shutdown.sh无法彻底关闭--线程池

    最近测试环境上测试的项目通过shutdown.sh始终无法彻底关闭. 之前临时解决方法两种: 第一:通过ps -ef|grep tomcat查看到tomcat的进程直接使用kill来杀死进程. 第二: ...

  6. json常用的注解

    json注解: 1.@JsonIgnoreProperties: 此注解是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响. 写法将此标签加在model ...

  7. Could not attach to a Hearthstone process.

    配置的加载 // Hearthbuddy.Windows.ConfigurationWindow // Token: 0x060001DB RID: 475 RVA: 0x00088A3C File ...

  8. kotlin class

    每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托.委托到同一个类的另一个构造函数用 this 关键字即可 class Person { constructor(pare ...

  9. go命令行参数

    go命令行参数例子: package main import( "fmt" "os" "strings" ) func main(){ wh ...

  10. C++ STL——常用算法

    目录 一 常用查找算法 二 常用遍历算法 注:原创不易,转载请务必注明原作者和出处,感谢支持! 注:内容来自某培训课程,不一定完全正确! 一 常用查找算法 /* find算法 查找元素 @param ...