DRF之初识

news2024/9/26 5:17:05

目录

一、序列化和反序列化

【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 serializers
 
class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'

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

(4) 创建视图(View):

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

from rest_framework import generics
from .serializers import MyModelSerializer
from .models import MyModel
 
class 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 MyModelListView
 
urlpatterns = [
    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_allowed
    return 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 = request

    try:
        # 执行了三大认证:
        '''
        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 Request
    return 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 time


def 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 res

    return 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 res
    return 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 = request
    self._data = Empty
    self._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.coloradmin.cn/o/1334486.html

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

相关文章

使用Open3D实现3D激光雷达可视化:以自动驾驶的2DKITTI深度框架为例(下篇)

原创 | 文 BFT机器人 【原文链接】使用Open3D实现3D激光雷达可视化:以自动驾驶的2DKITTI深度框架为例(上篇) 05 Open3D可视化工具 多功能且高效的3D数据处理:Open3D是一个全面的开源库,为3D数据处理提供强大的解决方…

【LeetCode】链表精选12题

目录 快慢指针: 1. 相交链表(简单) 2. 环形链表(简单) 3. 快乐数(简单) 4. 环形链表 II(中等) 5. 删除链表的倒数第 N 个节点(中等) 递归迭…

WPF中数据绑定转换器Converter

使用场景:ViewModel中的数据如果跟View中的数据类型不匹配。 下面是以int类型调控是否可见为例子 步骤一:创建转换器类 在xaml中查看Converter的定义可以知道Converter是一个接口类型,因此转换器的类定义需要使用这个接口 internal class Vi…

【UML】第13篇 序列图(2/2)——建模的方法

目录 三、序列图建模 3.1 概述 3.2 建模的步骤 3.3 举例说明步骤 1.确定主要场景和流程 2.确定参与的对象 3.绘制序列图 4.注意事项 3.4 特殊的情况 序列图是我个人认为,UML中最重要的图之一。 而且序列图,对于业务建模,也有非常好…

echarts 柱状图

注意点 1.y轴显示的序号和名称需要在数据中拼接,而不是在y轴data中拼接, 数据过多会导致下拉的时候,触发y轴formatter,更新序号,序号会重新排列,不准确。 2.需用到堆叠效果,三个柱子。如果想…

PyTorch官网demo解读——第一个神经网络(3)

上一篇:PyTorch官网demo解读——第一个神经网络(2)-CSDN博客 上一篇文章我们讲解了第一个神经网络的模型,这一篇我们来聊聊梯度下降。 大佬说梯度下降是深度学习的灵魂;梯度是损失函数(代价函数&#xff…

百度百科词条编辑需要提供参考资料,那么如何找参考资料呢。

百度百科相信大家都不陌生,在查询一个概念、新事物,或者我们想要了解的企业和人物时,我们一般都会求助百度百科,因为百度百科上面的信息相较于其他平台更值得我们相信。从词条所属主体来说,百度百科平台也是向其他用户…

20231224解决outcommit_id.xml1 parser error Document is empty的问题

20231224解决outcommit_id.xml1 parser error Document is empty的问题 2023/12/24 18:13 在开发RK3399的Android10的时候,出现:rootrootrootroot-X99-Turbo:~/3TB/Rockchip_Android10.0_SDK_Release$ make installclean PLATFORM_VERSION_CODENAMEREL…

Ubuntu18.04安装GTSAM库(亲测可用)

在SLAM(Simultaneous Localization and Mapping)和SFM(Structure from Motion)这些复杂的估计问题中,因子图算法以其高效和灵活性而脱颖而出,成为图模型领域的核心技术。GTSAM(Georgia Tech Smo…

不用再找了,这就是 NLP 方向最全面试题库

大家好,本篇文章总结了自然语言处理(NLP)面试需要准备的学习笔记与资料,该资料目前包含自然语言处理各领域的面试题积累。 热门面试题(校招、社招)、公司级专项真题、大厂常考题等,在我们社群具有总结,喜欢…

DevC++ easyx实现视口编辑,在超过屏幕大小的地图上画点,与解决刮刮乐bug效果中理解C语言指针的意义

继上篇文案, DevC easyx实现地图拖动,超过屏幕大小的巨大地图的局部显示在屏幕的方法——用悬浮窗的原理来的实现一个视口-CSDN博客 实现了大地图拖动,但是当时野心不止,就想着一气能搓啥就继续搓啥,看着地图移动都搓…

转录组无参比对教程

写在前面 2023年将结束,小杜的生信笔记分享个人学习笔记也有2年的时间。在这2年的时间中,分享算是成为工作、学习和生活中的一部分。自己为了运行和维护社群也算花费大量的时间和精力,自己认为还算满意吧。对于个人来说,自己一直…

Docker介绍、常用命令与操作

Docker介绍、常用命令与操作 学习前言为什么要学习DockerDocker里的必要基础概念常用命令与操作1、基础操作a、查看docker相关信息b、启动或者关闭docker 2、容器操作a、启动一个镜像i、后台运行ii、前台运行 b、容器运行情况查看c、日志查看d、容器删除 3、镜像操作a、镜像拉取…

使用 Docker 部署企业培训系统 PlayEdu

1)PlayEdu 介绍 官网:https://www.playedu.xyz/ GitHub:https://github.com/PlayEdu/PlayEdu PlayEdu 是一款适用于搭建内部培训平台的开源系统,旨在为企业/机构打造自己品牌的内部培训平台。PlayEdu 基于 Java MySQL 开发&…

C语言--直接插入排序【排序算法|图文详解】

一.直接插入排序介绍🍗 直接插入排序又叫简单插入排序,是一种简单直观的排序算法,它通过构建有序序列,对于未排序的数据,在已排序序列中从后向前扫描,找到相应位置并插入。 算法描述: 假设要排序…

Golang实现JAVA虚拟机-运行时数据区

一、运行时数据区概述 JVM学习: JVM-运行时数据区 运行时数据区可以分为两类:一类是多线程共享的,另一类则是线程私有的。 多线程共享的运行时数据区需要在Java虚拟机启动时创建好,在Java虚拟机退出时销毁。对象实例存储在堆区类信…

2023.12.22 关于 Redis 数据类型 String 常用命令

目录 引言 String 类型基本概念 SET & GET SET 命令 GET 命令 MSET & MGET MSET 命令 MGET 命令 SETNX & SETEX & PSETEX SETNX 命令 SETEX 命令 PSETEX 命令 计数命令 INCR 命令 INCRBY 命令 DECR 命令 DECRBY 命令 INCRBYFLOAT 命令 总结…

【GoLang】Go语言几种标准库介绍(一)

你见过哪些令你膛目结舌的代码技巧? 文章目录 你见过哪些令你膛目结舌的代码技巧?前言几种库bufio(带缓冲的 I/O 操作)特性示例 bytes (实现字节操作)特性示例 总结专栏集锦写在最后 前言 随着计算机科学的迅猛发展,编…

复试情报准备

英语自我介绍,介绍完老师会根据你的回答用英语问你问题,比如介绍一下你的本科学校,或者家乡什么的。计网过一遍,会问两道题。接下来是重点,我当时是根据我成绩单,问了我本科学过的科目,比如pyth…

【Docker容器精解篇 】深入探索Docker技术的概念与容器思想

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《docker容器精解篇》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、Docker 的介绍1.1 Docker 的由来1.1.1 环境不一致1.1.2 隔离性1.1.3 弹性伸缩1.1.4 学习成本 1.2 Doc…