DRF——请求的封装与版本管理

文章目录

    • [django restframework](#django restframework)
      • [1. 快速上手](#1. 快速上手)
      • [2. 请求数据的封装](#2. 请求数据的封装)
      • [3. 版本管理](#3. 版本管理)
        • [3.1 URL的GET参数传递(*)](#3.1 URL的GET参数传递(*))
        • [3.2 URL路径传递(*)](#3.2 URL路径传递(*))
        • [3.3 请求头传递](#3.3 请求头传递)
        • [3.4 二级域名传递](#3.4 二级域名传递)
        • [3.5 路由的namespace传递](#3.5 路由的namespace传递)
      • 小结

django restframework

  • 快速上手
  • 请求的封装
  • 版本管理
  • 认证
  • 权限
  • 限流
  • 序列化
  • 视图
  • 条件搜索
  • 分页
  • 路由
  • 解析器

1. 快速上手

  • 安装

    复制代码
    pip install djangorestframework==3.12.4
    python 复制代码
    版本要求:djangorestframework==3.12.4
    	Python (3.5, 3.6, 3.7, 3.8, 3.9)
    	Django (2.2, 3.0, 3.1)
        
    版本要求:djangorestframework==3.11.2
    	Python (3.5, 3.6, 3.7, 3.8)
    	Django (1.11, 2.0, 2.1, 2.2, 3.0)
  • 配置,在settings.py中添加配置

    python 复制代码
    INSTALLED_APPS = [
        ...
        # 注册rest_framework(drf)
        'rest_framework',
    ]
    
    # drf相关配置以后编写在这里 
    REST_FRAMEWORK = {
       
    }
  • URL和视图

    python 复制代码
    # urls.py
    
    from django.urls import path
    from app01 import views
    
    urlpatterns = [
        path('users/', views.UserView.as_view()),
    ]
    python 复制代码
    # views.py
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    
    class UserView(APIView):
        def get(self, request, *args, **kwargs):
            return Response({"code": 1000, "data": "xxx"})
    
        def post(self, request, *args, **kwargs):
            return Response({"code": 1000, "data": "xxx"})

其实drf框架是在django基础进行的扩展,所以上述执行过得底层实现流程(同django的CBV):

drf中重写了 as_viewdispatch方法,其实就是在原来django的功能基础上添加了一些功能,例如:

  • as_view,免除了csrf 验证,一般前后端分离不会使用csrf token认证(后期会使用jwt认证)。
  • dispatch,内部添加了 版本处理、认证、权限、访问频率限制等诸多功能(后期逐一讲解)。

在前后端不分离项目中要解决post,put,delete的crsf问题时:通常会在表单中加入{% csrf_token %}


而如果是在前后端分离项目中就不可行了,此时就需要csrf_exempt装饰器:

2. 请求数据的封装

drf的request是 原来django的request与认证,解析等对象一起封装后的对象。

以前我们通过django开发项目时,视图中的request是 django.core.handlers.wsgi.WSGIRequest 类的对象,其中包含了请求相关的所有数据。

python 复制代码
# Django FBV
def index(request):
	request.method
	request.POST
	request.GET
	request.body

# Django CBV
from django.views import View
class UserView(View):
	def get(self,request):
        request.method
        request.POST
        request.GET
        request.body

而在使用drf框架时,视图中的request是rest_framework.request.Request类的对象,其是又对django的request进行了一次封装,包含了除django原request对象以外,还包含其他后期会使用的其他对象。

python 复制代码
from rest_framework.views import APIView
from rest_framework.response import Response


class UserView(APIView):
    def get(self, request, *args, **kwargs):
        # request,不再是django中的request,而是又被封装了一层,内部包含:django的request、认证、解析器等。
        return Response({"code": 1000, "data": "xxx"})

    def post(self, request, *args, **kwargs):
        return Response({"code": 1000, "data": "xxx"})
python 复制代码
对象 = (request, 其他数据)
python 复制代码
# rest_framework.request.Request 类

class Request:
    """
    Wrapper allowing to enhance a standard `HttpRequest` instance.
    Kwargs:
        - request(HttpRequest). The original request instance. (django中的request)
        - parsers(list/tuple). The parsers to use for parsing the
          request content.
        - authenticators(list/tuple). The authenticators used to try
          authenticating the request's user.
    """

    def __init__(self, request, parsers=None, authenticators=None,negotiator=None, parser_context=None):
    	self._request = request
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        ...
	
    @property
    def query_params(self):
        """
        More semantically correct name for request.GET.
        """
        return self._request.GET

    @property
    def data(self):
        if not _hasattr(self, '_full_data'):
            self._load_data_and_files()
        return self._full_data
    
	def __getattr__(self, attr):
        try:
            return getattr(self._request, attr) # self._request.method
        except AttributeError:
            return self.__getattribute__(attr)

所以,在使用drf框架开发时,视图中的request对象与原来的有些不同,例如:

python 复制代码
from rest_framework.views import APIView
from rest_framework.response import Response
from django.views import View
from rest_framework.request import Request


class UserView(APIView):
    def get(self, request, *args, **kwargs):
        
        # 通过对象的嵌套直接找到原request,读取相关值
        request._request.method
        request._request.GET
        request._request.POST
        request._request.body
        
        # 举例:
        	content-type: url-form-encoded
        	v1=123&v2=456&v3=999
            django一旦读取到这个请求头之后,就会按照 {"v1":123,"v2":456,"v3":999}
            
            content-type: application/json
            {"v1":123,"v2":456}
            request._request.POST
            request._request.body
        
        # 直接读取新request对象中的值,一般此处会对原始的数据进行一些处理,方便开发者在视图中使用。
        request.query_params  # 内部本质上就是 request._request.GET
        request.data # 内部读取请求体中的数据,并进行处理,例如:请求者发来JSON格式,他的内部会对json字符串进行反序列化。
        
        # 通过 __getattr__ 去访问 request._request 中的值
        request.method
        
        

底层源码实现:

3. 版本管理

在restful规范中要去,后端的API中需要体现版本。

drf框架中支持5种版本的设置。(重点是前两种:参数传递,URL路径传递)

3.1 URL的GET参数传递(*)
python 复制代码
# settings.py

REST_FRAMEWORK = {
    "VERSION_PARAM": "v",
    "DEFAULT_VERSION": "v1",
    "ALLOWED_VERSIONS": ["v1", "v2", "v3"],
    "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.QueryParameterVersioning"
}

源码执行流程:

3.2 URL路径传递(*)
3.3 请求头传递
3.4 二级域名传递

在使用二级域名这种模式时需要先做两个配置:

  • 域名需解析至IP,本地可以在hosts文件中添加

    复制代码
    127.0.0.1       v1.wupeiqi.com
    127.0.0.1       v2.wupeiqi.com
  • 在django的settings.py配置文件中添加允许域名访问

    复制代码
    ALLOWED_HOSTS = ["*"]
3.5 路由的namespace传递

以上就是drf中支持的5种版本管理的类的使用和配置。

全局配置

上述示例中,如果想要应用某种 版本 的形式,需要在每个视图类中定义类变量:

python 复制代码
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import QueryParameterVersioning


class UserView(APIView):
    versioning_class = QueryParameterVersioning
    ...

如果你项目比较大,需要些很多的视图类,在每一个类中都写一遍会比较麻烦,所有drf中也支持了全局配置。

python 复制代码
# settings.py

REST_FRAMEWORK = {
    "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.QueryParameterVersioning",  # 处理版本的类的路径
    "VERSION_PARAM": "version",  # URL参数传参时的key,例如:xxxx?version=v1
    "ALLOWED_VERSIONS": ["v1", "v2", "v3"],  # 限制支持的版本,None表示无限制
    "DEFAULT_VERSION": "v1",  # 默认版本
}

底层源码实现

反向生成URL

使用drf是可以通过request.versioning_scheme.reverse(viewname, args, kwargs, request)来反向生成URL

在每个版本处理的类中还定义了reverse方法,他是用来反向生成URL并携带相关的的版本信息用的,例如:

小结

以后使用drf开发后端API接口时:

  1. 创建django程序
  2. 安装drf框架
  3. 创建一个app专门来处理用户的请求
  4. 注册APP
  5. 设置版本
  6. 编写视图类

若有错误与不足请指出,关注DPT一起进步吧!!!

相关推荐
逢生博客25 分钟前
使用 Python 项目管理工具 uv 快速创建 MCP 服务(Cherry Studio、Trae 添加 MCP 服务)
python·sqlite·uv·deepseek·trae·cherry studio·mcp服务
堕落似梦32 分钟前
Pydantic增强SQLALchemy序列化(FastAPI直接输出SQLALchemy查询集)
python
坐吃山猪1 小时前
Python-Agent调用多个Server-FastAPI版本
开发语言·python·fastapi
懵逼的小黑子2 小时前
django.db.utils.OperationalError: (1050, “Table ‘你的表名‘ already exists“)
django
Bruce-li__2 小时前
使用Django REST Framework快速开发API接口
python·django·sqlite
小兜全糖(xdqt)2 小时前
python 脚本引用django中的数据库model
python·django
シ風箏2 小时前
Django【应用 01】django-plotly-dash安装及使用
plotly·django·dash
Arenaschi2 小时前
SQLite 是什么?
开发语言·网络·python·网络协议·tcp/ip
纪元A梦2 小时前
华为OD机试真题——推荐多样性(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
仙人掌_lz2 小时前
人工智能与机器学习:Python从零实现性回归模型
人工智能·python·机器学习·线性回归