DRF之初识

目录

一、序列化和反序列化

【1】序列化

【2】反序列化

【3】小结

二、DRF的安装和快速使用

(1) 安装DRF:

(2) 配置DRF:

(3) 创建序列化器(Serializer):

(4) 创建视图(View):

(5) 配置URL路由:

【补充】下载兼容性问题

【补充】JSON可以序列化和反序列化的类型

【补充】回顾CBV执行流程

三、APIView执行流程分析

【总结】

【补充】回顾装饰器

【补充】APIView再回顾

四、Request对象分析

【总结】


一、序列化和反序列化

  • api接口开发,最核心最常见的一个过程就是序列化

【1】序列化

  • 把我们能识别的数据结构(python的字典,列表,对象)转换成其他语言(程序)能识别的数据结构。
  • 例如:
    • 我们在django中获取到的数据默认是模型对象(queryset)
    • 但是模型对象数据无法直接提供给前端或别的平台使用
    • 所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。

【2】反序列化

  • 把别人提供的数据转换/还原成我们需要的格式。
  • 例如:
    • 前端js提供过来的json数据
    • 对于python而言就是字符串
    • 我们需要进行反序列化换成模型类对象
    • 这样我们才能把数据保存到数据库中

【3】小结

  • 序列化:
    • drf称为 read(读取数据)
    • 序列化
    • queryset --- > json
    • 返给前端
  • 反序列化:
    • drf称为 write(写入数据)
    • 反序列化
    • 字符串 --- > json
    • 接收前端的数据

二、DRF的安装和快速使用

DRF(Django REST Framework)是一个强大且灵活的开发工具包,用于构建基于Django的Web API。

它提供了许多内置的功能和工具,使得编写高质量的API变得更加容易和高效。

(1) 安装DRF:

使用pip包管理器,在终端中运行以下命令来安装DRF:

pip install djangorestframework

(2) 配置DRF:

在你的Django项目的settings.py文件中,确保将DRF添加到INSTALLED_APPS列表中:

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config','rest_framework',  # 注册drf
]

(3) 创建序列化器(Serializer):

序列化器是DRF中一个重要的概念,它将Python对象转换为JSON等可被传输的格式,并可以反序列化接收到的数据。
在你的应用程序中创建一个名为serializers.py的文件,并定义你的序列化器类。
一个示例:

from rest_framework import serializersclass MyModelSerializer(serializers.ModelSerializer):class Meta:model = MyModelfields = '__all__'

在这个示例中,我们使用ModelSerializer来自动创建序列化器类。

(4) 创建视图(View):

在你的应用程序中创建一个名为views.py的文件,并定义视图类。
一个示例:

from rest_framework import generics
from .serializers import MyModelSerializer
from .models import MyModelclass MyModelListView(generics.ListCreateAPIView):queryset = MyModel.objects.all()serializer_class = MyModelSerializer

在这个示例中,我们使用ListCreateAPIView来创建一个支持列表和创建操作的通用视图。

(5) 配置URL路由:

在你的应用程序的urls.py文件中,定义DRF的URL路由。
一个示例:

from django.urls import path
from .views import MyModelListViewurlpatterns = [path('mymodels/', MyModelListView.as_view(), name='mymodel-list'),
]

通过上述配置,当访问/mymodels/时,将会调用MyModelListView视图。

  • 以上是使用DRF进行快速开发的简要步骤。
  • 当然,DRF还提供了许多其他功能,如认证、权限控制、过滤器、分页等,可以根据自己的需求进一步学习和定制。
  • 也可以参考官方文档以获得更详细的信息:
    • Home - Django REST framework

【补充】下载兼容性问题

  • 安装命令
pip install djangorestframework
  • 如果你是django2
    • 直接这样装,装最新drf,他们不匹配
    • ---> pip会自动把django卸载,安装最新django,安装最新drf
  • django3 ,这样没有任何问题
  • 强制更新
    • pip3 install djangorestframework --upgrade

【补充】JSON可以序列化和反序列化的类型

【补充】回顾CBV执行流程

1 请求来了---> 执行 ---> views.BookView.as_view()(request) ---> 执行View类中as_view类方法中的闭包函数view

@classonlymethod
def as_view(cls, **initkwargs):def view(request, *args, **kwargs):self = cls(**initkwargs) # BookView类实例化得到对象self.dispatch(request, *args, **kwargs) # BookView类的dispatch

2 BookView类的dispatch没有 --> View的dispatch

通过反射去self【BookView的对象】中找到 跟请求方式同名的方法  get --> get方法

def dispatch(self, request, *args, **kwargs):if request.method.lower() in self.http_method_names:handler = getattr(self, request.method.lower(), self.http_method_not_allowed)else:handler = self.http_method_not_allowedreturn handler(request, *args, **kwargs) # 真正的执行视图类中跟请求方式同名的方法

3 以什么请求方式访问 ---> 就会执行视图类中 跟请求方式同名的方法

比如:http://127.0.0.1:8000/books/  get请求

执行BookView类中get方法

三、APIView执行流程分析

1 在路由中:path('books/', views.BookView.as_view()),请求来了

2 先看 as_view()---->APIView的 as_view---> as_view执行结果跟之前一样,去除了csrf认证

@classmethod
def as_view(cls, **initkwargs):view = super().as_view(**initkwargs) # 调用父类的 as_view,view还是View的as_view# 以后所有请求,都不会做csrf认证了return csrf_exempt(view)

3 请求来了执行 views.BookView.as_view()(request)--->view(request)--->csrf_exempt(view)(request)---> 内部核心 ---> return self.dispatch(request)

4 self 是 APIView类的对象 ---> APIView没有dispatch ---> APIView的dispatch,核心代码如下

def dispatch(self, request, *args, **kwargs):# 后续的request都是 initialize_request 返回结果--> 新的request--> drf的Requet类的对象request = self.initialize_request(request, *args, **kwargs)# 新的request放到了 self.request中---> self是BookView类的对象# 后续视图类的方法中 可以直接 self.request取出 当次请求的request对象self.request = requesttry:# 执行了三大认证:'''self.perform_authentication(request)self.check_permissions(request)self.check_throttles(request)'''self.initial(request, *args, **kwargs)###### 通过反射,去视图类中:BookView中执行跟请求方式同名的方法 ###### if request.method.lower() in self.http_method_names:handler = getattr(self, request.method.lower(),self.http_method_not_allowed)else:handler = self.http_method_not_allowed# request是新的Request类的对象了  get方法的第一个参数request也是新的response = handler(request, *args, **kwargs)################# 执行视图类的方法结束 #################except Exception as exc:# 如果在执行三大认证或视图类方法中,出了错,都会被异常捕获,统一处理response = self.handle_exception(exc)self.response = self.finalize_response(request, response, *args, **kwargs)return self.response

5 看self.initialize_request 是APIView的

def initialize_request(self, request, *args, **kwargs):# 类实例化得到对象,传入一些参数# Request类--> drf提供的类from rest_framework.request import Requestreturn Request(request,parsers=self.get_parsers(),authenticators=self.get_authenticators(),negotiator=self.get_content_negotiator(),parser_context=parser_context)

只要继承APIView,以后方法中得request都变了,成了 rest_framework.request.Request 的对象了但是用起来,跟之前的一模一样。

原来的是:django.core.handlers.wsgi.WSGIRequest 类的对象。

【总结】

  1. 以后视图类方法中得request对象,变成了新的request,它rest_framework.request.Request 的对象了,但是用起来跟之前一样
  2. 把新的request对象,同时放到了 视图类的对象中  self.request = request  后续从视图类中可以直接通过 self.request取出来
  3. 在执行视图类的方法之前,执行了三大认证
  4. 如果三大认证或视图类的方法执行出错,会有全局异常处理
  5. 以后所有的接口都去除了csrf认证

【补充】回顾装饰器

装饰器作用:在不改变原函数源代码和调用方式的基础上,为他增加新功能

import timedef add(a, b):time.sleep(1)return a + b# 统计add的运行时间
# start_time = time.time()
# add(3, 4)
# end_time = time.time()
# print('运行时间是:', end_time - start_time)# 写一个通用的,以后只要统计任意函数运行时间,都使用通用的--->改变了调用方式,不行
# def outer(func):
#     start_time = time.time()
#     func(3, 4)
#     end_time = time.time()
#     print('运行时间是:', end_time - start_time)
#
# outer(add)def outer(func):def inner(*args, **kwargs):start_time = time.time()res = func(*args, **kwargs)end_time = time.time()print('运行时间是:', end_time - start_time)return resreturn inner# inner=outer(add)
# 调用inner,就是执行,inner内部包了 add函数,inner叫闭包函数
# inner() # 改变了调用方式# 继续优化
add = outer(add)res = add(3, 4)  # add现在本质调用 inner,参数传给 inner,inner要能接收a,b 并且有返回结果
print(res)# 以后想装饰哪个函数 得按如下操作,麻烦
# def ee():
#     print('ee')
#
# ee=outer(ee)
# ee()# python提供了一个语法糖 @ ,以后只要按如下方式编写代码,就能实现上述功能
@outer  # 等同于  ee=outer(ee)   该语法糖会把被装饰器的函数ee,当做参数,传入outer,并且把outer的执行结果,返回赋值给ee
def ee():print('ee')# 以后ee其实已经不是ee了,是inner了,执行ee本质在执行inner#####上述是原理####
# 总结,以后写他
def outer(func):def inner(*args, **kwargs):# 被装饰器函数,执行之前干事res = func(*args, **kwargs)# 被装饰函数,执行之后干事情return resreturn inner# 装饰某个函数
@outer
def add(a,b):time.sleep(1)return a+b

【补充】APIView再回顾

在执行视图类的方法之前干了一些事

  • 去除csrf
  • 包装新的requet
  • 在视图类中加入了 self.request
  • 执行三大认证

在执行视图类的方法之后干了一些事

  • 处理全局异常

本质就是做了装饰器的功能

四、Request对象分析

1 分析APIVIew时,分析出,以后request都是新的request了,是drf提供的Request的对象

from rest_framework.request import Request

2 源码解析之 __init__---> 老的request在新的内部---> request._request:

        先看 __init__--->类实例化得到对象时,对对象进行初始化,往对象中放数据

def __init__(self, request, parsers=None, authenticators=None,negotiator=None, parser_context=None):# 传入的request是老的,django原生的request# 放到了self._request,self 是新的request类的对象self._request = requestself._data = Emptyself._files = Empty# 什么时候调用的 __init__?新的                        老的-request = self.initialize_request(request, *args, **kwargs)老的return Request(request)

以后用新的跟用老的一样,为什么?

  • 新的   requet.method
  • 新的   request.path

【补充】魔法方法:

在类内部,以 __开头  __结尾的方法, 在某种情况下会自动调用,他们称之为魔法方法

学过:__init__:  类名() 自动触发
          __str__:   print(对象)  自动触发

还有哪些? 很多---> 所有类都继承object类---> 它都在object类中

今天要学的 __getattr__ 

        -对象.属性 ,属性不存在会触发     
3 回头看 新的 requet.method用的时候,如果method不存在就会触发 Request类的 __getattr__

源码解析之 __getattr__

# 逻辑肯定是:从老的request中取出,你想要的东西
def __getattr__(self, attr):try:# 通过反射,去老的中取,能取到就返回,取不到,执行except代码,再取不到就报错return getattr(self._request, attr)except AttributeError:return self.__getattribute__(attr)

4 以后新的request中多了个属性 data ---> 前端post,put提交的请求体中得数据,都会放在request.data中,无论何种编码格式,它都是字典

【总结】

1 老的request还在新的request内部  request._request

2 新的用起来跟老的一样:原因是---> 重写了魔法方法  __getattr__ 
    对象.属性 ---> 属性不存在会触发 __getattr__的执行---> 内部通过反射找到老的request中对应的属性
    request.POST
    request.GET
    request.method
    ....     
3 request.data 多了这个属性,以后无论何种编码,无论何种请求方式 --> 都能取出请求体携带的数据

  • post,put,get ---> 只要放在body体中 ---> 都能取出来 --> 当字典用
  • 如果是urlencoded,form-data编码:OrderedDict --> 原来的request.POST 对象
  • 如果是json编码:dict

4 如果form-data编码---> 取数据:request.data  ---> 取文件:request.FILES中取

5 请求地址栏中参数--> 从request.GET中取 ---> 以后还可以从:request.query_params 中取

  • query_params:查询参数
  • 请求地址中带查询参数---》query_params

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331154.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring(2)装配Bean

【0】README0)本文部分文字描述转自:“Spring In Action(中/英文版)”,旨在review spring(2)装配Bean 的相关知识;1)在spring中,对象无需自己查找或创建与其所关联的其他对象。相反…

restful和rest_HATEOAS的RESTful服务:JVM上的REST API和超媒体

restful和rest1.简介 到目前为止,我们已经花了很多时间谈论了相当数量的关于角色的的超媒体和HATEOAS在REST风格的 Web服务和API,扫视不同规格和可用性方面。 听起来好像支持超媒体和HATEOAS并不难,只需选择您的收藏夹就可以了! …

Spring中配置数据源的4种形式

【0】README 0.1)以下内容转自:http://blog.csdn.net/orclight/article/details/8616103 不管采用何种持久化技术,都需要定义数据源。Spring中提供了4种不同形式的数据源配置方式: spring自带的数据源(DriverManagerDataSource)&…

MavenSelenium测试自动化教程

在进行自动化测试项目时,您需要与之关联的所有Selenium依赖项。 通常,这些依赖项是在项目生命周期中手动下载和升级的,但是随着项目规模的扩大,管理依赖项可能会非常困难。 这就是为什么需要构建自动化工具(例如Maven&…

命令行执行Junit测试

【0】README 0.1)本文旨在给出如何在命令行中执行 Junit测试的steps: 【1】在命令行中执行Junit测试 1)problemsolution: 1.1)problem: 1.2)solution:导出 JUnitCore 类并且使用 …

托管 非托管_如何在托管Kubernetes上还原Neo4J备份

托管 非托管在下面的视频中,我将解释如何将Neo4J实例的备份还原到在托管Kubernetes环境中运行的新实例。 备份内容将从先前写入备份的持久卷中获取。 在上一篇文章中,您可以首先了解如何进行备份。 自己尝试 同样,您将在以下GitHub存储库中…

spring(3)高级装配

【0】README0)本文部分文字描述转自:“Spring In Action(中/英文版)”,旨在review spring(3)高级装配 的相关知识;【1】环境与profile(考虑数据库配置)1)使用嵌入式数据…

jmc线程转储_查找线程转储中的异常和错误

jmc线程转储线程转储是解决生产问题/调试生产问题的重要工件。 在像过去我们已经讨论了几种有效的线程转储故障模式: 堵车 , 跑步机 , RSI , 一个 LL条条大路通罗马 .........。 在本文中,我们想介绍另一种线程转储故障…

命令模式的两种不同实现

转载自 命令模式(Command)的两种不同实现命令模式(Command):将一个请求封装成一个对象,使得你用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能…

tomcat(18)部署器

【0】README-1)先上干货:本文重点分析了tomcat 如何部署WAR文件的项目形式 以及 普通文件夹的项目形式;不管是WAR文件 还是 普通文件夹的项目形式,在tomcat中,它们都是Context容器;(Bingo&#…

装饰器模式和代理模式的区别

转载自 装饰器模式和代理模式的区别学习AOP时,教材上面都说使用的是动态代理,可是在印象中代理模式一直都是控制访问什么的,怎么又动态增加行为了,动态增加行为不是装饰器模式吗?于是找了很多资料,想弄清楚…

使用Java 8 Stream像操作SQL一样处理数据(上)

转载自 使用Java 8 Stream像操作SQL一样处理数据(上) 几乎每个Java应用都要创建和处理集合。集合对于很多编程任务来说是一个很基本的需求。举个例子,在银行交易系统中你需要创建一个集合来存储用户的交易请求,然后你需要遍历整个…

tomcat(19)Manager应用程序的servlet类

【0】README1)本文部分文字描述转自:“深入剖析tomcat”,旨在学习“tomcat(19)Manager应用程序的servlet类” 的相关知识;2)Manager应用程序用来管理已经部署的web 应用程序;在tomcat7中,manage…

使用Java 8 Stream像操作SQL一样处理数据(下)

转载自 使用Java 8 Stream像操作SQL一样处理数据(下) 在上一篇文章中,我们介绍了Stream可以像操作数据库一样来操作集合,但是我们没有介绍 flatMap 和 collect 操作。这两种操作对实现复杂的查询是非常有用的。比如你可以结果 fl…

spring(4)面向切面的Spring(AOP)

【0】README1)本文部分文字描述转自:“Spring In Action(中/英文版)”,旨在review “spring(4)面向切面的Spring(AOP)”的相关知识;2)在软件开发中,散布于应…

Mybatis-plus 思维导图,让 Mybatis-plus 不再难懂

转载自 Mybatis-plus 思维导图,让 Mybatis-plus 不再难懂 摘要: Mybatis-Plus(简称MP)是一个Mybatis的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。mybatis-plus与mybatis mybatis Mybat…

报错:The type javax.servlet.http.HttpServletRequest cannot be resolved

【0】README 0.1)以下内容转自: http://blog.csdn.net/vincent080928/article/details/5392891 problem)The type javax.servlet.http.HttpServletRequest cannot be resolved. It is indirectly referenced from required .class files. 这…

MyBatis 思维导图,让 MyBatis 不再难懂(一)

转载自 MyBatis 思维导图,让 MyBatis 不再难懂(一)写在前面与hibernate相比,我无疑更喜欢mybatis,就因为我觉得它真的好用,哈哈。它简单上手和掌握;sql语句和代码分开,方便统一管理和…

tomcat(20)基于JMX的管理

【0】README1)本文部分文字描述转自:“深入剖析tomcat”,旨在学习“tomcat(20)基于JMX的管理” 的相关知识;2)晚辈我在tomcat上部署web 项目以测试JMX管理 tomcat 容器bean的效果,结果运行不成功&#xff0…

mybatis思维导图,让mybatis不再难懂(二)

转载自 mybatis思维导图,让mybatis不再难懂(二) 写在前面 上一篇文章写了mybatis的基本原理和配置文件的基本使用,这一篇写mybatis的使用,主要包括与sping集成、动态sql、还有mapper的xml文件一下复杂配置等。值得注意…