DRF框架的序列化组件

  在前后端分离的应用模式中,后端仅返回前端所需的数据,返回的数据类似是JSON,因此需要使用序列化组件进行序列化再将数据返回

使用JsonResponse做序列化

#  使用JsonResponse做序列化
class  SearchBook(View):
def  get(self, request):         book_queryset = Book.objects.values('id', 'title', 'category', 'pub_time', 'publisher')
        book_list = list(book_queryset)
        for  book  in  book_list:
             #  将publisher转化为字典格式
            publisher_obj = Publisher.objects.filter(id=book['publisher']).first()
            book['publisher'] = {
                'id': publisher_obj.id,
                'title': publisher_obj.title
            }
         #  JsonResponse序列化列表,需要加safe=False,json_dumps_params={'ensure_ascii':False}处理编码问题
        ret = JsonResponse(book_list, safe=False, json_dumps_params={'ensure_ascii': False})     
        return HttpResponse(ret)

使用django进行序列化

#  使用Django自带的serializers做序列化
from django.core.serializers import serialize class  SearchBook1(View):
def  get(self, request):         book_queryset = Book.objects.all()
         #  使用serialize进行序列化
        ret = serialize('json', book_queryset, ensure_ascii=False)  #  ensure_ascii=False处理编码问题
        return HttpResponse(ret)

使用DRF框架的准备

1.导入模块

from rest_framework.response import Response
from rest_framework.views import APIView

  

2.注册rest_framework

# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'SerDemo.apps.SerdemoConfig',
'rest_framework' # 注册rest_framework
]

DRF框架的APIView

所有的类都继承了APIView

1.APIView继承了View

2.豁免了csrf

3.重新封装了request

4.request新的属性

request._request == View.request

request.query_params == View.request.GET

request.data == request.POST/PUT (除了GET请求的其他请求)

使用序列化组件前的准备

# models.py
class Book(models.Model):
title = models.CharField(max_length=32)
CHOICES = ((1,"python"),(2,"linux"),(3,"go"))
category = models.IntegerField(choices=CHOICES)
pub_time = models.DateField()
publisher = models.ForeignKey(to='Publisher')
authors = models.ManyToManyField(to="Author") class Meta:
verbose_name = '图书' # 模型类的名字
verbose_name_plural = verbose_name # 模型复数形式的名字 def __str__(self):
return self.title class Publisher(models.Model):
title = models.CharField(max_length=32) class Meta:
verbose_name = '出版社'
verbose_name_plural = verbose_name class Author(models.Model):
name = models.CharField(max_length=32) class Meta:
verbose_name = '作者'
verbose_name_plural = verbose_name

序列化组件

'''
根据模型构建序列化器
'''
# serializers.py
from rest_framework import serializers # 导入框架的序列化器 # 外键字段的序列化器
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)
category = serializers.CharField(source='get_category_display') # source通过ORM操作获得CHOICES的值
pub_time = serializers.DateField() # 外键字段,先声明外键字段的序列化器再实例化
publisher = PublisherSerializer() # 多对多字段,先声明多对多字段的序列化器再实例化
authors = AuthorSerializer(many=True) # 多个模型对象使用many=True

正序列化(GET请求)

1.声明序列化器

2.将每个模型对象放到序列化器进行序列化化,多个对象必须指定many=True

3.序列化器进行字段匹配,匹配上的进行序列化,匹配不上的丢弃,且必须满足序列化的所有字段要求

4.序列化后返回序列化对象

5.数据都在序列化对象.data

6.通过Response返回

class Search_book(APIView):
# 查询数据,GET请求
def get(self,request):
book_queryset = Book.objects.all() # 使用序列化器进行序列化,返回序列化对象
ser_obj = BookSerializer(book_queryset,many=True) # 多个queryset对象使用many=True # 返回数据
return Response(ser_obj.data) # 序列化好的数据都在 序列化对象.data

序列化组件的方法

  反序列化不验证:required=False
  仅在正序列化验证:read_only=True
  仅在反序列化验证:write_only=True
  序列化多个对象:many=True

反序列化(POST请求)

1.序列化器对校验字段进行过滤

2.获取前端的数据,传入到序列化器,返回序列化器对象

3.对序列化器进行校验,不通过返回错误信息

4.校验通过调用save()方法,其内部会调用create()方法

5.序列化器自定义create()方法新增模型对象并返回

6.通过Response返回数据

'''
根据模型构建序列化器
'''
# serializers.py
from rest_framework import serializers # 导入框架的序列化器
from SerDemo.models import Book # 外键字段的序列化器
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(required=False) # 反序列化不匹配该字段
title = serializers.CharField(max_length=32)
category = serializers.CharField(source='get_category_display',read_only=True) # source通过ORM操作获得CHOICES的值
category_post = serializers.IntegerField(write_only=True) # 用于反序列化的字段
pub_time = serializers.DateField() # 外键字段,先声明外键字段的序列化器再实例化
publisher = PublisherSerializer(read_only=True) # 仅在正序列化匹配该字段
publisher_id = serializers.IntegerField(write_only=True) # 仅在反序列化匹配该字段 # 多对多字段,先声明多对多字段的序列化器再实例化
authors = AuthorSerializer(read_only=True,many=True) # 多个模型对象使用many=True,正序列化匹配该字段
authors_list = serializers.ListField(write_only=True) # 反序列化匹配该字段 # 新增对象调用create方法
def create(self, validated_data):
# validated_data 是数据的字典 # 创建对象
book_obj = Book.objects.create(
title=validated_data.get('title'),
category=validated_data.get('category_post'),
pub_time = validated_data.get('pub_time'),
publisher_id = validated_data.get('publisher_id'),
)
book_obj.authors.add(*validated_data['authors_list']) # 多对多字段使用add
book_obj.save()
return book_obj
# 新增数据,POST请求
def post(self,request): # 对提交的数据进行反序列化,返回一个序列化对象
ser_obj = BookSerializer(data=request.data) # 对序列化对象进行校验
if ser_obj.is_valid():
# 校验通过,新增数据
ser_obj.save() # 调用序列化器的create()方法
return Response(ser_obj.data) # 返回新增的数据 else:
# 校验不通过
return Response(ser_obj.errors)

源码流程

# 2.1、开始初始化,执行PubliserView.as_view()
class APIView(View):
@classmethod
def as_view(cls, **initkwargs):
# 1.2、开始调用父类的as_view方法
view = super(APIView, cls).as_view(**initkwargs) # view
view.cls = cls
view.initkwargs = initkwargs
return csrf_exempt(view) class View(object):
# 2.2、返回View.view方法名
@classonlymethod
def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
return view # 3、url初始化后:
url(r'^publishers/$',View.view) # 4、用户开始url,则开始执行View.view()方法,传入原始的request对象,并调用PubliserView的dispatch方法
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs) # step 5:PubliserView的父类有dispatch方法
class PubliserView(APIView):
pass class ApiView(View):
def dispatch(self, request, *args, **kwargs):
pass # step 6:构建新的request对象
class ApiView(View):
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 6.1
request = self.initialize_request(request, *args, **kwargs) # 6.2
def initialize_request(self, request, *args, **kwargs):
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
) # 6.3
class Request(object): def __init__(...):
self._request = request
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty @property
def data(self):
if not _hasattr(self, '_full_data'):
# 开始封装self._request._post、self._request._file、self._full_data
self._load_data_and_files()
return self._full_data @property
def query_params(self):
return self._request.GET @property
def POST(self):
# Ensure that request.POST uses our request parsing.
if not _hasattr(self, '_data'):
self._load_data_and_files()
if is_form_media_type(self.content_type):
return self._data
return QueryDict('', encoding=self._request._encoding) @property
def FILES(self):
if not _hasattr(self, '_files'):
self._load_data_and_files()
return self._files # 6.3.1
def _load_data_and_files(self):
if not _hasattr(self, '_data'):
self._data, self._files = self._parse()
if self._files:
self._full_data = self._data.copy()
self._full_data.update(self._files)
else:
self._full_data = self._data if is_form_media_type(self.content_type):
self._request._post = self.POST
self._request._files = self.FILES # 6.3.2
def is_form_media_type(media_type):
"""
Return True if the media type is a valid form media type.
"""
base_media_type, params = parse_header(media_type.encode(HTTP_HEADER_ENCODING))
return (base_media_type == 'application/x-www-form-urlencoded' or
base_media_type == 'multipart/form-data')

【DRF框架】序列化组件的更多相关文章

  1. 第三章、drf框架 - 序列化组件 | Serializer

    目录 第三章.drf框架 - 序列化组件 | Serializer 序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer( ...

  2. drf框架 - 序列化组件 | ModelSerializer (查,增,删,改)

    ModelSerializer 序列化准备: 配置 settings.py # 注册rest_framework框架 INSTALLED_APPS = [ ... 'rest_framework' ] ...

  3. drf框架 - 序列化组件 | Serializer

    序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 ...

  4. drf框架序列化和返序列化

    0903自我总结 drf框架序列化和反序列化 from rest_framework import serializers 一.自己对于序列化和反序列化使用的分类 前后端交互主要有get,post,p ...

  5. DRF的序列化组件

    目录 DRF的序列化组件 Serializer组件 序列化 反序列化 ModelSerializer组件 序列化和反序列化 自定义Response方法 基表相关 DRF中ORM的多表关联操作 外键设计 ...

  6. Django框架(十八)—— drf:序列化组件(serializer)

    序列化组件 # 模型层 from django.db import models class Book(models.Model): nid = models.AutoField(primary_ke ...

  7. Django框架(十九)—— drf:序列化组件(serializer)

    目录 序列化组件 一.利用for循环来实现序列化(繁琐) 二.利用Django提供的序列化组件(不可控需要的字段) 三.利用drf提供的序列化组件 1.基于Serializer类实现序列化--基本语法 ...

  8. drf框架 - 过滤组件 | 分页组件 | 过滤器插件

    drf框架 接口过滤条件 群查接口各种筛选组件数据准备 models.py class Car(models.Model): name = models.CharField(max_length=16 ...

  9. Django框架 --序列化组件(serializer)

    一 .Django自带序列化组件 Django内置的serializers(把对象序列化成json字符串) from django.core import serializers from djang ...

  10. drf 之序列化组件

    序列化 把Python中对象转换为json格式字符串 反序列化 把json格式转为为Python对象. 用orm查回来的数据都是都是一个一个的对象, 但是前端要的是json格式字符串. 序列化两大功能 ...

随机推荐

  1. intellij maven配置与使用

    目录 intellij maven配置与使用 Maven 常用设置介绍 Maven 骨架创建 Java Web 项目 Maven 组件来管理项目 @(目录) intellij maven配置与使用 M ...

  2. python 求交集、并集、差集

    需要用到set类型 交集,两种方法 retA = [i for i in listA if i in listB] retB = setA.intersection(setB) 并集 retC = s ...

  3. linux和windows换行符的^M问题

    起源 在windows中写的脚本执行完全没问题,代码一模一样,切换到linux中执行报错.利用命令 “vi/vim -b 文件名”查看文件发现每行结尾多了“^M”这样的结尾. 根源 通过查询得知,其问 ...

  4. AWS 基础设施即代码(五)

    基础设施即代码 概述 手动配置的挑战:可能因为人为错误导致缺乏可靠性,环境无法完全再现,同时需要额外文档 基础设施即代码,是软件开发中用于创建可重用.可维护.可扩展及可测试基础设施的技术.实践和工具, ...

  5. 微服务Consul系列之服务部署、搭建、使用

    使用Consul解决了哪些问题 是否在为不同环境来维护不同项目配置而发愁 是否有因为配置的更改导致代码还要进行修改.发布因为客流量大了还要规避开高峰期等到半夜来发布 微服务架构下应用的分解业务系统与服 ...

  6. uinxSocket 与 tcpSocket

    $tpc = stream_socket_client('unix:///tmp/php-cgi.sock');nginx配置中可以用uninx:/tmp/php-.....这种格式,也可用直接uin ...

  7. 6.2.3 reginst中的yzm

    @RequestMapping("/reginst/{yzm}") public Object reginst(User user,@PathVariable String yzm ...

  8. Java后台面试之java基础

    经典类概念性问题 1.java支持的数据类型有哪些?什么是自动拆装箱? 12.Java有哪些特性,举个多态的例子. 14.请列举你所知道的Object类的方法. 15.重载和重写的区别?相同参数不同返 ...

  9. Python21之内嵌函数和闭包

    一.内嵌函数 内嵌函数指的是在一个函数体内部定义的函数,可以称它为函数的函数,也就是子函数,外部的函数称之为母函数,就类似局部变量和全局变量 子函数体内定义的变量只在其函数内部有效,但其内部可以调用母 ...

  10. python 之 并发编程(开启子进程的两种方式,进程对象的属性)

    第九章并发编程 同一个程序执行多次是多个进程 import time import os ​ print('爹是:',os.getppid()) #父进程PID,(pycharm) print('me ...