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. PAT 甲级 1069 The Black Hole of Numbers (20 分)(内含别人string处理的精简代码)

    1069 The Black Hole of Numbers (20 分)   For any 4-digit integer except the ones with all the digits ...

  2. NETTY keeplive 参数,心跳检测

    当设置为true的时候,TCP会实现监控连接是否有效,当连接处于空闲状态的时候,超过了2个小时,本地的TCP实现会发送一个数据包给远程的 socket,如果远程没有发回响应,TCP会持续尝试11分钟, ...

  3. ubuntu18.04安装golang

    首先我们通过如下命令安装golang: sudo add-apt-repository ppa:longsleep/golang-backports sudo apt-get update sudo ...

  4. Selenium WebDriver原理

    WebDriver原理 WebDriver是按照Server-Client的经典设计模式设计的. Server端就是RemoteServer,可以是任意的浏览器,当我们的脚本启动浏览器后,该浏览器就是 ...

  5. Teaset-React Native UI 组件库

    GitHub地址 https://github.com/rilyu/teaset/blob/master/docs/cn/README.md React Native UI 组件库, 超过 20 个纯 ...

  6. 什么是netty--通俗易懂

      一.Netty介绍 1.什么是netty Netty 是由 JBOSS 提供的一个 Java 开源框架.Netty 提供异步的.基于事件驱动的网络应用程序框架,用以快速开发高性能.高可靠性的网络 ...

  7. 使用RestTemplate进行服务调用的几种方式

    首先我们在名为MSG的服务中定义一个简单的方法 @RestController public class ServerController { @GetMapping("/msg" ...

  8. jdbc连接oracle的三种方法

    jdbc连接oracle的三种方法 使用service_name,配置方式:jdbc:oracle:thin:@//<host>:<port>/<service_name ...

  9. 关于python的一次性能调优过程

    问题 这两天在公司帮老大写一个程序功能,要求抓取从elasticsearch和kibana服务器上返回的数据,统计所有hits的数据字段ret_code为0的hit,并计算其占有率等一些功能. 功能倒 ...

  10. MRR,BKA,ICP相关

    MRR Multi-Range Read,多范围读,5.6以上版本开始支持 工作原理&优化效果: 将查询到的辅助索引结果放在一个缓冲(read_rnd_buffer_size = 4M)中 将 ...