DRF之初识

目录

一、序列化和反序列化

【1】序列化

【2】反序列化

【3】小结

二、DRF的安装和快速使用

[(1) 安装DRF:](#(1) 安装DRF:)

[(2) 配置DRF:](#(2) 配置DRF:)

[(3) 创建序列化器(Serializer):](#(3) 创建序列化器(Serializer):)

[(4) 创建视图(View):](#(4) 创建视图(View):)

[(5) 配置URL路由:](#(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:

python 复制代码
pip install djangorestframework

(2) 配置DRF:

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

python 复制代码
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的文件,并定义你的序列化器类。

一个示例:

python 复制代码
from rest_framework import serializers
 
class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'

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

(4) 创建视图(View):

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

一个示例:

python 复制代码
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路由。

一个示例:

python 复制代码
from django.urls import path
from .views import MyModelListView
 
urlpatterns = [
    path('mymodels/', MyModelListView.as_view(), name='mymodel-list'),
]

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

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

【补充】下载兼容性问题

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

    python 复制代码
    pip3 install djangorestframework --upgrade

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

【补充】回顾CBV执行流程

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

python 复制代码
@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方法

python 复制代码
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认证

python 复制代码
@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,核心代码如下

python 复制代码
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的

python 复制代码
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认证

【补充】回顾装饰器

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

python 复制代码
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

#####上述是原理####
python 复制代码
# 总结,以后写他
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的对象

python 复制代码
from rest_framework.request import Request

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

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

python 复制代码
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

python 复制代码
# 逻辑肯定是:从老的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
相关推荐
青 春 记 忆5 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO35 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO8 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白8 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲9 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)11 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机11 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69211 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy12 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽13 小时前
真实即粗糙,光滑是伪造
人工智能·python