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. Django models中的meta选项

    通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样: class Foo(models.Model): bar = models.CharFi ...

  2. Java Audio : Playing PCM amplitude Array

    转载自:http://ganeshtiwaridotcomdotnp.blogspot.com/2011/12/java-audio-playing-pcm-amplitude-array.html ...

  3. 【warning】set the environment variable MXNET_CUDNN_AUTOTUNE_DEFAULT to 0 to disable

    前言 运行mxnet程序的时候出现这个warning信息,但是不影响整个程序的运行,不过宝宝喜欢将warning信息尽量也clear,强迫症嘛?!哈哈哈哈 问题描述 [::] src/operator ...

  4. python logging模块日志输出

    import logging logger = logging.getLogger(__name__) logger.setLevel(level = logging.INFO) handler = ...

  5. 机器学习之径向基神经网络(RBF NN)

    本文基于台大机器学习技法系列课程进行的笔记总结. 主要内容如下图所示: 首先介绍一下径向基函数网络的Hypothesis和网络的结构,然后介绍径向基神经网络学习算法,以及利用K-means进行的学习, ...

  6. 编译Cython代码时遇到的问题: fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'X86'

    使用python setup.py build_ext --inplace命令编译cython代码, 出现以下错误: Compiling cython_example.pyx because it c ...

  7. 遨游TypeScript海洋之定义变量和数据类型

    变量和数据类型 熟悉JavaScript的小伙伴都知道,typescript是JavaScript的超集,也就是说它包含JavaScript.所以我觉得,只要你想拥有更佳的模块管理,让你的开发更佳严谨 ...

  8. 烽火传递【单调队列优化dp】

    题目大意: 1.给出长度为n的数组,要求每m个连续的元素之间必须选一个值作为代价,求该数组的最小代价. 题解思路: 1.显然是线性dp,dp[i]表示选择第 i 个元素时的最小总代价.很明显状态转移方 ...

  9. Action<T>和Func<T>委托事例

    Action<T>和Func<T>委托事例 using System; //除了为每个参数和返回类型定义一个新委托类型之外,还可以使用Action<T>和Func& ...

  10. 自己实现CountDownLatch

    自己实现的CountDownLatch ,只是模拟他的功能而已.jdk中的实现采用的是AQS public class MyCountDownLatch { private final int tot ...