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. ABAP函数篇1 日期函数

    1. 日期格式字段检查 data:l_date type ekko-bedat. l_date = '20080901'. CALL FUNCTION 'DATE_CHECK_PLAUSIBILITY ...

  2. lombok 插件安装使用

    Lombok是一个Java库,它自动插入编辑器并构建工具,为Java添加香料.永远不要再编写另一个getter或Eques方法,您的类有一个功能齐全的构建器,可以自动化您的日志变量以及更多的注释. 官 ...

  3. 【pip升级导致错误】 多个pip导致明明已经安装了包但是报no module错误

    原来一直用apt install 默认安装的pip 8.01版本,今天因为一些原因,将pip升级到了19.01.升级后就导致了错误. 直接pip installl --upgrade pip,发现报权 ...

  4. LODOP指定window默认打印机和临时默认打印机

    通过以下语句,可指定windows默认打印机LODOP.SET_PRINT_MODE("WINDOW_DEFPRINTER",某打印机名或序号);这种默认打印机是指的windows ...

  5. 【Leetcode_easy】993. Cousins in Binary Tree

    problem 993. Cousins in Binary Tree 参考 1. Leetcode_easy_993. Cousins in Binary Tree; 完

  6. Xmanager教程

    简介 Xmanager是市场上领先的PC X服务器,可将X应用程序的强大功能带入Windows环境. 提供了强大的会话管理控制台,易于使用的X应用程序启动器,X服务器配置文件管理工具,SSH模块和高性 ...

  7. 【计算机视觉】目标检测之ECCV2016 - SSD Single Shot MultiBox Detector

    本文转载自: http://www.cnblogs.com/lillylin/p/6207292.html SSD论文阅读(Wei Liu--[ECCV2016]SSD Single Shot Mul ...

  8. linux编程 新建一个进程的方法

    学习到一种,直接调用系统函数,在类的构造函数中直接启动一个线程,例如,某个类是用来监听串口的,可以直接在其构造函数中调用系统函数,开辟一个进程,在该进程对应的函数中不断while(1){....} h ...

  9. .NET Core 配置文件

    老一代配置系统 1,XML格式 格式单一. 2,配置信息Kye,只能一维化配置 3,框架信息和应用程序信息混合到一起 应用程序中是 App.config web项目中           web.co ...

  10. Springmvc在项目启动时查询数据库并初始化静态变量

    private static List<ResourceEntity> resourceList = null; //初始化的全局静态变量 @Autowired private Resou ...