一、序列化器-serializer

  1. 序列化,序列化器会把模型对象转成字典,经过response以后变成JSON字符串
  2. 反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
  3. 反序列化:完成数据校验功能

二、序列化器的使用

序列化器的使用分为两个阶段:

  1. 在客户端请求时,使用序列化器可以完成对数据的反序列化。
  2. 在服务器响应时,使用序列化器可以完成对数据的序列化。

简单使用

1、创建一个表模型

  1. from django.db import models
  2. class Books(models.Model):
  3. title = models.CharField(verbose_name='书名', max_length=32)
  4. publish = models.CharField(verbose_name='出版社', max_length=32)
  5. price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2)

2、新建一个py文件,写一个序列化的类,继承Serializer

3、在类中写要序列化的字段,想序列化那个字段,就在类中写那个字段

  1. from rest_framework import serializers
  2. class BooksSerializer(serializers.Serializer):
  3. title = serializers.CharField()
  4. publish = serializers.CharField()
  5. price = serializers.DecimalField()

4、在视图类中使用,导入——》实例化得到序列化对象,把要序列化的对象传入

5、序列化的对象.data——》是一个字典

6、把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse

  1. from rest_framework.views import APIView
  2. from rest_framework.request import Request
  3. from app01.models import Books
  4. from app01.ser import BooksSerializer
  5. class BookView(APIView):
  6. def get(self, request, pk):
  7. # 响应信息
  8. response_msg = {'status': 200, 'message': '查询成功'}
  9. # 获取要序列化的对象
  10. book = Books.objects.filter(pk=pk).first()
  11. # 要序列化谁就把谁传到序列化类去
  12. book_ser = BooksSerializer(book)
  13. # book_ser.data————》序列化对象.data————》就是序列化后的字典
  14. # 将查询结果添加到响应信息内
  15. response_msg['data'] = book_ser.data
  16. return Response(response_msg)
  17. # urls.py
  18. re_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),

7、如果要被序列化的是包含多条数据的查询集queryset,可以通过添加many=True参数

  1. from rest_framework.views import APIView
  2. from rest_framework.response import Response
  3. from app01.models import Books
  4. from app01.ser import BooksSerializer
  5. class BooksView(APIView):
  6. def get(self, request):
  7. # 响应信息
  8. response_msg = {'status': 200, 'message': '查询成功'}
  9. books = Books.objects.all()
  10. # 要序列化谁就把谁传到序列化类去
  11. book_ser = BooksSerializer(books, many=True)
  12. # book_ser.data————》序列化对象.data————》就是序列化后的字典
  13. # 将查询结果添加到响应信息内
  14. response_msg['data'] = book_ser.data
  15. return Response(response_msg)
  16. # urls.py
  17. re_path(r'^books/', views.BookView.as_view()),

高级使用

source

1、可以修改字段名字

  1. class BooksSerializer(serializers.Serializer):
  2. xxx = serializers.CharField(source='title') # 相当于——》xxx = Books.title
  3. # 响应
  4. {
  5. "status": 200,
  6. "message": "查询成功",
  7. "data": {
  8. "xxx": "魔道祖师" ————》响应的字段名被修改了
  9. }
  10. }

2、可以跨表查询

  1. class BookSerializer(serializers.Serializer):
  2. publish_email = serializers.CharField(source='publish.email')
  3. # 相当于——》publish_email = Book.publish.email 连表查询publish表的email字段
  4. # 响应
  5. {
  6. "status": 200,
  7. "message": "查询成功",
  8. "data": {
  9. "publish_email": "modao@163.com"
  10. }
  11. }

3、可以执行方法

  1. # models.py
  2. class Book(models.Model):
  3. title = models.CharField(max_length=32)
  4. price = models.IntegerField()
  5. pub_date = models.DateTimeField()
  6. publish = models.ForeignKey("Publish", on_delete=models.CASCADE, null=True)
  7. authors = models.ManyToManyField("Author")
  8. def func(self):
  9. return '666666'
  10. # ser.py
  11. class BookSerializer(serializers.Serializer):
  12. msg = serializers.CharField(source='func')
  13. # msg = Book.func ——》调用Book类中的func()方法的返回值
  14. # 响应
  15. {
  16. "status": 200,
  17. "message": "查询成功",
  18. "data": {
  19. "msg": "666666"
  20. }
  21. }

**SerializerMethodField( ) **

它需要有一个配套的方法,方法名叫做get_字段名,返回值就是要显示的东西

  1. class BookSerializer(serializers.Serializer):
  2. authors = serializers.SerializerMethodField()
  3. def get_authors(self, instance):
  4. # instance ——》 Book对象
  5. authors = instance.authors.all() # 取出所有作者
  6. author_list = []
  7. for author in authors:
  8. author_list.append({'name': author.name, 'age': author.age})
  9. return author_list

通用参数

read_only:(只读)表明该字段仅用于序列化输出,默认False,如果设置成True,响应中可以看到该字段,修改时,不需要传该字段

write_only:(只写)表明该字段仅用于反序列化输入,默认False,如果设置成True,响应中看不到该字段,修改时,该字段需要传

  1. from rest_framework import serializers
  2. class BooksSerializer(serializers.Serializer):
  3. title = serializers.CharField(read_only = True) # 响应中能看到改字段,修改不需要传值
  4. publish = serializers.CharField(write_only = True) # 响应中看不到改字段,修改需要传值
  5. price = serializers.DecimalField()
  6. # 还有参数如下:
  7. required 表明该字段在反序列化时必须输入,默认True
  8. default 反序列化时使用的默认值
  9. allow_null 表明该字段是否允许传入None,默认False
  10. validators 该字段使用的验证器
  11. error_messages 包含错误编号与错误信息的字典

三、反序列化数据校验

当使用序列化器对数据进行反序列化时,就需要对数据进行校验了,只有校验成功的数据才能被保存成模型类对象

将要校验的数据传入序列化器中并实例化:obj = BooksSerializer(data=request.data),调用is_valid()方法校验,校验成功返回True,失败返回False。

失败,可以通过序列化器对象的errors获取错误信息(字典)

成功,可以公共序列化对象的validated_data属性获取数据。

校验方法有:局部钩子,全局钩子,validators,和序列化类型和字段属性也是

字段属性

  1. max_length 最大长度
  2. min_lenght 最小长度
  3. allow_blank 是否允许为空
  4. trim_whitespace 是否截断空白字符
  5. max_value 最小值
  6. min_value 最大值

局部钩子

在序列化器类中创建局部钩子:validate_字段名,并且接收一个参数

  1. # ser.py
  2. class BooksSerializer(serializers.Serializer):
  3. title = serializers.CharField()
  4. publish = serializers.CharField()
  5. price = serializers.DecimalField(max_digits=5, decimal_places=2)
  6. # 局部钩子对price字段校验
  7. def validate_price(self, data):
  8. if float(data) > 20:
  9. # 校验成功就通过
  10. return data
  11. else:
  12. # 校验失败就抛异常
  13. raise ValidationError('价格太低')

全局钩子

全局钩子:validate( ), 接收一个参数,

同时对多个字段进行比较验证

  1. # ser.py
  2. class BooksSerializer(serializers.Serializer):
  3. title = serializers.CharField()
  4. publish = serializers.CharField()
  5. price = serializers.DecimalField(max_digits=5, decimal_places=2)
  6. def validate(self, validate_data):
  7. title = validate_data.get('title')
  8. publish = validate_data.get('publish')
  9. if not title == publish:
  10. return validate_data
  11. else:
  12. raise ValidationError('书名和出版社不能一致')

validators

使用字段的validators=[func],来校验

  1. # ser.py
  2. # 校验函数
  3. def check_price(data):
  4. if float(data) > 10:
  5. return data
  6. else:
  7. raise ValidationError('价格太低')
  8. class BooksSerializer(serializers.Serializer):
  9. title = serializers.CharField()
  10. publish = serializers.CharField()
  11. price = serializers.CharField(validators=[check_price]) # 配置

四、序列化器操作数据

查询所有

  1. # views.py
  2. class BooksView(APIView):
  3. def get(self, request):
  4. # 响应信息
  5. response_msg = {'status': 200, 'message': '查询成功'}
  6. # 获取所有数据
  7. books = Books.objects.all()
  8. # 把数据谁传到序列化器中
  9. book_ser = BooksSerializer(instance=books, many=True) # 序列化多条需要加 many=True
  10. # book_ser.data————》序列化对象.data————》就是序列化后的字典
  11. # 将查询结果添加到响应信息内
  12. response_msg['data'] = book_ser.data
  13. return Response(response_msg)
  14. # urls.py
  15. path('books/', views.BooksView.as_view()),

查询单条

  1. # views.py
  2. class BookView(APIView):
  3. def get(self, request, pk):
  4. # 响应信息
  5. response_msg = {'status': 200, 'message': '查询成功'}
  6. # 获取要序列化的对象
  7. book = Books.objects.filter(pk=pk).first()
  8. # 要序列化谁就把谁传到序列化器中
  9. book_ser = BooksSerializer(instance=book)
  10. # book_ser.data————》序列化对象.data————》就是序列化后的字典
  11. # 将查询结果添加到响应信息内
  12. response_msg['data'] = book_ser.data
  13. return Response(response_msg)
  14. # urls.py
  15. re_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),

新增数据

新增数据需要在序列化器中重写create( ) 方法:

注意没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,调用save()方法的时候,update()被调用。

  1. # views.py
  2. class BookView(APIView):
  3. def post(self, request):
  4. # 响应信息
  5. response_msg = {'status': 201, 'message': '增加成功'}
  6. # 修改才有instance,新增没有instance,只有data
  7. book_ser = BooksSerializer(data=request.data)
  8. # 校验字段
  9. if book_ser.is_valid():
  10. book_ser.save() # 需要在序列化器中重写create()方法
  11. # 保存成功把原数据返回
  12. response_msg['data'] = book_ser.data
  13. else:
  14. response_msg['status'] = 202
  15. response_msg['message'] = '数据校验失败'
  16. response_msg['data'] = book_ser.error_messages
  17. return Response(response_msg)
  18. # ser.py
  19. class BooksSerializer(serializers.Serializer):
  20. title = serializers.CharField()
  21. publish = serializers.CharField()
  22. price = serializers.DecimalField(max_digits=5, decimal_places=2)
  23. # 重写create
  24. def create(self, validated_data): # validated_data——>传入的新增数据
  25. instance = Books.objects.create(**validated_data)
  26. # instance——> 新增的字段对象,需要返回
  27. return instance
  28. # urls.py
  29. path('book/', views.BookView.as_view()),

修改数据

修改数据需要在序列化器中重写update( ) 方法:

  1. # views.py
  2. class BookView(APIView):
  3. def put(self, request, pk):
  4. # 响应信息
  5. response_msg = {'status': 200, 'message': '修改成功'}
  6. # 获取需要修改的字段对象
  7. book = Books.objects.filter(pk=pk).first()
  8. # 将字段对象和修改数据添加到序列化器中
  9. book_ser = BooksSerializer(instance=book, data=request.data)
  10. # 校验数据
  11. if book_ser.is_valid():
  12. book_ser.save() # 需要在序列化器中重写update()方法
  13. response_msg['data'] = book_ser.data
  14. else:
  15. response_msg['status'] = 202
  16. response_msg['message'] = '数据校验失败'
  17. response_msg['data'] = book_ser.error_messages
  18. return Response(response_msg)
  19. # urls.py
  20. re_path('book/(?P<pk>\d+)', views.BookView.as_view()),

删除数据

  1. # views.py
  2. class BooksView(APIView):
  3. def delete(self, request, pk):
  4. # 响应信息
  5. response_msg = {'status': 200, 'message': '删除成功'}
  6. # 删除数据
  7. Books.objects.filter(pk=pk).delete()
  8. return Response(response_msg)
  9. # urls.py
  10. re_path('book/(?P<pk>\d+)', views.BooksView.as_view()),

五、模型类序列化器

DRF提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。

ModelSerializer与常规的Serializer相同,但是提供了:

  • 基于模型类自动生成一系列字段
  • 基于模型类自动为Serializer生成validators,比如unique_together
  • 包含默认的create( ) 和update( )。

实例:

  1. class BookSerializer(serializers.ModelSerializer):
  2. class Meta:
  3. model = Book # 指明参照那个模型类
  4. fields = '__all__' # 为模型类的那些字段生成

字段操作

1、可以使用fields来明确字段,__all__表示包含所以字段,具体那些字段->fields = ('title','price')

2、exclude表示排除那些字段,不能和fields一起写——>exclude = ('price',)

3、额外参数extra_kwargs,给字段添加额外的参数

  1. class BookSerializer(serializers.ModelSerializer):
  2. class Meta:
  3. model = Book # 指明参照那个模型类
  4. fields = '__all__' # 为模型类的那些字段生成
  5. # 类似于 title = serializers.CharField(read_only = True)
  6. extra_kwargs = {
  7. 'title': {'read_only': True},
  8. }

六、源码分析many=True

当我们需要查询多条数据时就需要在实例化序列化器的时候传many=True

  1. book_ser = BooksSerializer(instance=books, many=True) # 查询多条
  2. book_one_ser = BooksSerializer(instance=book) # 查询单条
  3. print(type(book_ser))
  4. #<class 'rest_framework.serializers.ListSerializer'>
  5. print(type(book_one_ser))
  6. #<class 'app01.ser.BookModelSerializer'>
  7. # 对象的生成-->先调用类的__new__方法,生成空对象,如果many=True,生成ListSerializer对象,反之生成Serializer对象
  8. # 类的__new__方法控制对象的生成
  9. def __new__(cls, *args, **kwargs):
  10. # 如果many=True,就会自动创建ListSerializer类
  11. if kwargs.pop('many', False):
  12. return cls.many_init(*args, **kwargs)
  13. return super().__new__(cls, *args, **kwargs)

drf-序列化器serializer的更多相关文章

  1. DRF 序列化器-Serializer (2)

    作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...

  2. 066.Python框架DRF之序列化器Serializer

    一 序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成 ...

  3. DRF序列化器

    序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成字典 ...

  4. Cf序列化器-Serializer解析

    Cf序列化器-Serializer 定义序列化器 Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Seri ...

  5. day82 序列化器-Serializer

    目录 一.序列化器的基本功能 二.定义序列化器 三.创建Serializers对象 四.序列化器的使用 1 序列化 2 反序列化 2.1 数据验证(类比forms组件) 2.2 数据保存 一.序列化器 ...

  6. drf序列化器serializers.SerializerMethodField()的用法

    问题描述: 为什么DRF中有时候返回的json中图片是带域名的,有时候是不带域名的呢? 解析: 带域名的结果是在view中对模型类序列化的,DRF在序列化图片的时候 会检查上下文有没有request, ...

  7. drf序列化器的实例

    应用目录结构: views.py from django.shortcuts import render # Create your views here. from django.views imp ...

  8. DRF序列化器的使用

    序列化器的使用 序列化器的使用分两个阶段: 在客户端请求时,使用序列化器可以完成对数据的反序列化. 在服务器响应时,使用序列化器可以完成对数据的序列化. 序列化的基本使用 使用的还是上一篇博文中使用的 ...

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

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

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

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

随机推荐

  1. iUploader 2.0 七牛云上传工具

    iUploader 软件介绍: iUploader主要功能将文件上传至七牛云,返回 Markdown 格式的链接到剪贴板 功能介绍: 图片本地压缩 图片右键上传 图片截取上传 图片复制上传 图片拖拽上 ...

  2. Envoy:TLS双向认证

    环境准备 主机 角色 数量 front-envoy front envoy 1 service envoy 作为内部后端的envoy 2 end 后端应用程序 2 访问 / front-envoy = ...

  3. [刷题] 220 Contains Duplicate III

    要求 给出整型数组nums和整数k,是否存在索引i和j 使得nums[i]和nums[j]之差不超过t,且i和j之差不超过k 思路 建立k个元素的有序查找表 每次有新元素加入,寻找查找表中大于 num ...

  4. 【BIGDATA】ElasticSearch HEAD插件的GET请求的坑

    今使用HEAD插件,发现复杂查询功能下,使用GET请求有坑. 查询语句如下: GET kk/_search { "query": { "match": { &q ...

  5. 单用户模式修改root密码

    单用户模式修改root密码 1.进入引导菜单界面2.按e进入grub,在linux或linux16那行结尾加上 rw init=/bin/bash,按Ctrl+x或F103.进入bash-4.3# , ...

  6. C语言scanf跳出循环的问题

    注意:%C前面有个空格,如果不加空格,会跳出while循环. 第一次输入的时候,回车键会滞留在输入缓冲区,第二次要去输的时候,会直接去读回车键 在第二次要去输入的时候,可以先清除缓冲区,用getcha ...

  7. 附: Python爬虫 数据库保存数据

    原文 1.笔记 #-*- codeing = utf-8 -*- #@Time : 2020/7/15 22:49 #@Author : HUGBOY #@File : hello_sqlite3.p ...

  8. 046.Python协程

    协程 1 生成器 初始化生成器函数 返回生成器对象,简称生成器 def gen(): for i in range(10): #yield 返回便能够保留状态 yield i mygen = gen( ...

  9. 022.Python模块序列化模块(json,pickle)和math模块

    序列化模块 一  序列化模块 pickle 1.1 基本认识 序列化:把不能够直接存储的数据变成可存储的过程就是序列化 反序列化:把储存的数据拿出来恢复成原来的数据类型就是反序列化 例如,一个文件不可 ...

  10. 016.Python闭包函数以及locals和globals

    一 闭包函数 内函数使用了外函数的局部变量,并且外函数把内函数返回出来的过程叫做闭包,这个内函数叫做闭包函数 1.1 闭包函数语法 def outer(): a = 5 def inner(): pr ...