【Python开发】FastAPI 07:Depends 依赖注入

news2024/11/27 21:00:27

FastAPI 中,Depends 是一个依赖注入系统,用于注入应用程序中所需的依赖项,通过 Depends,我们可以轻松地将依赖项注入到 FastAPI 路由函数中。简单来说,Depends 依赖注入的目的就是将代码重复最小!

目录

1 Depends 使用

1.1 依赖注入介绍

1.2 demo

1.3 OpenAPI 集成

2 不同依赖项

2.1 类作为依赖项

① 可调用对象

② Python 类依赖注入

2.2 嵌套依赖项

2.3 dependencies 参数

2.4 全局依赖项


📌源码地址:

FastAPI_Study_Yinyu: FastAPI学习路径,CSDN专栏:http://t.csdn.cn/JRtrk

1 Depends 使用

FastAPI 提供了简单易用,但功能强大的依赖注入系统,这可以让开发人员轻松地把组件集成至 FastAPI

1.1 依赖注入介绍

依赖注入是一种设计模式,用于降低程序组件之间的耦合度。它通过将组件之间的依赖关系从代码中分离出来,使得组件可以更加灵活地被替换、修改或重用。

假设有一个类 需要使用类B的功能,如果在 类中直接实例化 B 类,那么 A 类和 B 类之间的依赖关系就会很紧密,难以达到解耦的目的。而使用依赖注入的方式,A 类不再直接实例化 B 类,而是将 B 类的实例通过构造函数、属性、或者接口等方式注入到 A 类中。

依赖注入常用于以下场景:

  • 共享业务逻辑(复用相同的代码逻辑)
  • 共享数据库连接
  • 实现安全、验证、角色权限
  • 等……

上述场景均可以使用依赖注入,将代码重复最小化。

1.2 demo

这是一个非常简单的例子,通过这个例子,您可以初步了解「依赖注入」的工作机制。

from typing import Union
from fastapi import Depends, FastAPI #2导入 Depends

app = FastAPI()

#1创建依赖项
async def common_parameters(
    q: Union[str, None] = None, skip: int = 0, limit: int = 100
):
    return {"q": q, "skip": skip, "limit": limit}

@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)): #3声明依赖项
    return commons

@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)): #3声明依赖项
    return commons

此时访问 127.0.0.1:8000/users/?q=yinyu&skip=1&limit=10 ,响应正常:

📌依赖项

依赖项 common_parameters 预期接收如下参数:

  • 类型为 str 的可选查询参数 q
  • 类型为 int 的可选查询参数 skip,默认值是 0
  • 类型为 int 的可选查询参数 limit,默认值是 100

然后,依赖项函数将返回包含这些值的 dict

声明依赖项时,这里只能传给 Depends 一个参数,且该参数必须是可调用对象。比如函数,该函数接收的参数等于路径操作函数的参数

📌实际请求时,FastAPI 执行如下操作:

  • 用正确的参数调用依赖项函数(「可依赖项」
  • 获取函数返回的结果
  • 把函数返回的结果赋值给路径操作函数的请求参数,例如 commons

 如此,只编写一次代码,FastAPI 就可以为多个路径操作/请求接口共享这段代码 。

注意,无需创建专门的类,并将之传递给 FastAPI 以进行「注册」或执行类似的操作。 只要把它传递给 DependsFastAPI 就知道该如何执行后续操作。

1.3 OpenAPI 集成

依赖项及子依赖项的所有请求声明、验证和需求都可以集成至同一个 OpenAPI 概图。

因此,交互文档里也会显示依赖项的所有信息:

依赖注入系统如此简洁的特性,让 FastAPI 可以与下列系统兼容:

  • 关系型数据库
  • NoSQL 数据库
  • 外部支持库
  • 外部 API
  • 认证和鉴权系统
  • API 使用监控系统
  • 响应数据注入系统
  • 等等……

2 不同依赖项

在前面的例子中, 我们从依赖项中返回了一个 dict,但是我们知道编辑器不能为 dict 提供很多支持(比如补全),因为编辑器不知道 dict 的键和值类型, 因此接下来将介绍更好用的方式~

依赖项不只是函数,只要是 "可调用对象" 就可以,Python 中的 "可调用对象" 是指任何 Python 可以像函数一样 "调用" 的对象。 

2.1 类作为依赖项

① 可调用对象

创建一个 Python 类的实例,您可以使用和依赖注入相同的语法,比如:

class Cat:
    def __init__(self, name: str):
        self.name = name

fluffy = Cat(name="Mr Fluffy")

在这个例子中,fluffy 是一个 Cat 类的实例。 为了创建 fluffy,调用了 Cat 。 所以,Python 类也是 可调用对象。

因此,在 FastAPI 中,你可以使用一个 Python 类作为一个依赖项。

② Python 类依赖注入

因此我们可以将 demo 里的依赖项  common_parameters 更改为类 CommonQueryParams:

class CommonQueryParams:
    def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit

它与我们 demo 里的 common_parameters 具有相同的参数。

📌声明依赖项

@app.get("/items2/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
    return commons

FastAPI 调用 CommonQueryParams 类。这将创建该类的一个 "实例",该实例将作为参数 commons 被传递给你的函数。

📌简化

注意,我们在上面的代码中编写了两次 CommonQueryParams

commons: CommonQueryParams = Depends(CommonQueryParams)

FastAPI 对此做了简化,你可以写成:

commons=Depends(CommonQueryParams) 或 commons: CommonQueryParams = Depends()

📌完整代码

from typing import Union
from fastapi import Depends, FastAPI

app = FastAPI()

class CommonQueryParams:
    def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit

@app.get("/items2/")
async def read_items(commons = Depends(CommonQueryParams)):
    return commons

此时访问 127.0.0.1:8000/items2/?q=yinyu&skip=2&limit=10 ,响应正常:

2.2 嵌套依赖项

FastAPI 支持创建含子依赖项的依赖项,并且可以按需声明任意深度的子依赖项嵌套层级。

📌 第一层依赖项

def query_extractor(q: Union[str, None] = None):
    return q

这段代码声明了类型为 str 的可选查询参数 q,然后返回这个查询参数, 这个函数很简单。

📌 第二层依赖项

接下来,创建另一个依赖项函数,并同时用该依赖项自身再声明一个依赖项:

def query_or_cookie_extractor(
    q: str = Depends(query_extractor),
    last_query: Union[str, None] = Cookie(default=None),
):
    if not q:
        return last_query
    return q

这里重点说明一下声明的参数:

  • 尽管该函数自身是依赖项,但还声明了另一个依赖项
    • 该函数依赖 query_extractor, 并把 query_extractor 的返回值赋给参数 q
  • 同时,该函数还声明了类型是 str 的可选 cookie
    • 用户未提供查询参数 q 时,则使用上次使用后保存在 cookie 中的查询

📌 使用嵌套依赖项

...

def query_extractor(q: Union[str, None] = None):
    return q

def query_or_cookie_extractor(
    q: str = Depends(query_extractor),
    last_query: Union[str, None] = Cookie(default=None),
):
    if not q:
        return last_query
    return q

@app.get("/items3/")
async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
    return {"q_or_cookie": query_or_default}

注意,这里在路径操作函数中只声明了一个依赖项,即 query_or_cookie_extractor

FastAPI 必须先处理 query_extractor,以便在调用 query_or_cookie_extractor 时使用 query_extractor 返回的结果。类似下边的路径图:

此时访问 127.0.0.1:8000/items3/?q=yinyu ,响应正常:

📌 依赖项缓存

如果多次声明了同一个依赖项,例如多个依赖项共用一个子依赖项,那么 FastAPI 在处理同一请求时,只调用一次该子依赖项。

FastAPI 默认不会为同一个请求多次调用同一个依赖项,而是把依赖项的返回值进行「缓存」,并把它传递给同一请求中所有需要使用该返回值的「依赖项」

如果不想使用「缓存」值,而是为需要在同一请求的每一步操作(多次)中都实际调用依赖项,可以把 Depends 的参数 use_cache 的值设置为 False :

async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
    return {"fresh_value": fresh_value}

2.3 dependencies 参数

有时,我们并不需要在路径操作函数中使用依赖项的返回值,有些依赖项也不返回值,或者说接口根本用不上这些返回值~

对于这种情况,不必在声明路径操作函数的参数时使用 Depends,而是可以在路径操作装饰器中添加一个由 dependencies 组成的 list

路径操作装饰器支持可选参数 ~ dependencies, 该参数的值是由 Depends() 组成的 list

from fastapi import Depends, FastAPI, Header, HTTPException

app = FastAPI()

#路径装饰器依赖项可以声明请求的需求项(比如响应头)或其他子依赖项
async def verify_token(x_token: str = Header()):
    if x_token != "fake-super-secret-token":
        #路径装饰器依赖项与正常的依赖项一样,可以 raise 异常:
        raise HTTPException(status_code=400, detail="X-Token header invalid")

async def verify_key(x_key: str = Header()):
    if x_key != "fake-super-secret-key":
        raise HTTPException(status_code=400, detail="X-Key header invalid")
    return x_key

@app.get("/items4/", dependencies=[Depends(verify_token), Depends(verify_key)])
async def read_items():
    return [{"item": "Foo"}, {"item": "Bar"}]

路径操作装饰器依赖项(以下简称为“路径装饰器依赖项”)的执行或解析方式和普通依赖项一样,但就算这些依赖项会返回值,它们的值也不会传递给路径操作函数

2.4 全局依赖项

有时,我们要为整个应用添加依赖项。 通过与定义路径装饰器依赖项类似的方式,可以把依赖项添加至整个 FastAPI 应用:

from fastapi import Depends, FastAPI, Header, HTTPException


async def verify_token(x_token: str = Header()):
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="X-Token header invalid")

async def verify_key(x_key: str = Header()):
    if x_key != "fake-super-secret-key":
        raise HTTPException(status_code=400, detail="X-Key header invalid")
    return x_key

app1 = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])

@app1.get("/items5/")
async def read_items():
    return [{"item": "Portal Gun"}, {"item": "Plumbus"}]

那么所有 app 请求都将经过 verify_token 和 verify_key 函数,类似于过滤器。

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

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

相关文章

Vue学习3

文章目录 Vuex工作原理配置环境各种函数mapState对象写法数组写法 MapGetterMapMutations对象写法数组写法 Mapaction总结 模块化模块化1总结 Vuex 工作原理 那三个要通过store管理 配置环境 使用import时,回先执行Import中的代码,在后面的也会提前。 index.js…

Vscode利用ssh登录ubuntu开发环境下,代码不能跳转问题解决

0 开发环境 环境:VScode remote ssh 虚拟机Ubuntu22.04 1 问题记录 在win环境下,Vscode可以实现代码跳转。但是,在利用VScode的ssh登录Ubuntu下,代码不能进行跳转。 网上看到很多帖子,有的更改settings.json&…

【Ubuntu】保姆级图文介绍双系统win10卸载Ubuntu16.04

文章目录 删除Ubuntu分区数据删除Ubuntu启动项 这段时间想将前几年安装的Ubuntu16.04版本升级到Ubuntu20.04。 折腾了一番,升级失败了。想着还不如卸载了重新安装Ubuntu20.04。 由于Ubuntu16.04在升级过程中出现了一些问题,导致进不去Ubuntu系统。因此只…

tinkerCAD入门操作(2):移动、旋转和缩放对象

tinkerCAD入门操作:移动、旋转和缩放对象 介绍 现在您已经学会了如何在工作平面上旋转,是时候真正开始处理对象了。 在本课中,您将了解有关对象物理属性的更多信息。 放置一个盒子 我们需要一个对象来操作。让我们从一个盒子开始。在提示…

使用Druid数据源并查看监控页面

💧 使 用 D r u i d 数 据 源 并 查 看 监 控 信 息 \color{#FF1493}{使用Druid数据源并查看监控信息} 使用Druid数据源并查看监控信息💧 🌷 仰望天空,妳我亦是行人.✨ 🦄 个人主页——微风撞见云的博客&…

百度狂问3小时,大厂offer到手,小伙真狠!(百度面试真题)

前言: 在40岁老架构师尼恩的(50)读者社群中,经常有小伙伴,需要面试 百度、头条、美团、阿里、京东等大厂。 下面是一个小伙伴成功拿到通过了百度三次技术面试,小伙伴通过三个多小时技术拷问,最…

Docker镜像存储

前言 在之前的文章中有说过容器目录的隔离机制. 今天来分析一下镜像的文件系统. Docker 已经用了很久了, 也知道镜像存储的时候是分层存储的(从docker pull时分层下载就能看出), 但是具体是如何将多层进行聚合并生成最终展示的文件, 这个过程从未深究过. 既然不知道, 又难掩好…

chatgpt赋能python:Python反向切片:介绍与例子

Python反向切片:介绍与例子 Python是一种高级编程语言,具有简单易懂的语法和高效的运行速度,以及丰富的标准库和第三方库。其中一项有趣的功能是Python反向切片,它能够用一种简单而有效的方式处理列表(list&#xff0…

大模型有什么用,从技术上看

一、大模型有什么用 目前为止,大模型主要是以NLP为主,因为NLP抛弃了RNN序列依赖的问题,采用了Attention is All you need的Transformer结构,使得NLP能够演变出更多大模型。图像领域也不甘示弱,CNN大模型也开始陆续涌现…

tcpdump命令抓取网络数据包并用wireshark软件分析

1、tcpdump命令部署 1.1、源码下载 (1)下载网址:http://www.tcpdump.org; (2)下载匹配的libpcap库和tcpdump库; (3)编译tcpdump命令依赖libpcap库,所以要先编译libpcap库再编译tcpdump命令; 1.2、源码编译 1.2.1、编…

chatgpt赋能python:Python如何去掉空值

Python如何去掉空值 数据处理过程中经常会出现空值,这些空值可以影响我们对数据的分析和处理。在Python中,有许多方法可以去除空值。本文将介绍常见的方法并提供实例说明。 什么是空值 在Python中,空值通常用None或NaN表示。None是Python内…

FutureTask简介

FutureTask简介 Future接口和实现Future接口的FutureTask类,代表异步计算的结果。FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给Executor执行,也可以由调用线程直接执行(FutureTask…

华为OD机试真题 Java 实现【矩阵最大值】【2023 B卷 100分】,附详细解题思路

一、题目描述 给定一个仅包含0和1的N*N的二维矩阵,请计算二维矩阵的最大值。 计算规则如下: 1、每行元素按下标顺序组成一个二进制数(下标越大越排在低位),二进制数的值就是该行的值。矩阵各行值之和为矩阵的值。 …

使用Windbg动态调试目标进程的一般步骤及相关要点详解

目录 1、概述 2、将Windbg附加到已经启动起来的目标进程上,或者用Windbg启动目标程序 2.1、将Windbg附加到已经启动起来的目标进程上 2.2、用Windbg启动目标程序 2.3、Windbg关联到目标进程上会中断下来,输入g命令将该中断跳过去 3、分析实例说明 …

ModuleNotFoundError: No module named ‘transformers_modules.chatglm-6b_v1‘的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

ggplot2、RMySQL、httpuv、shiny、miniUI、devtools、recharts安装问题

目录 ggplot2下载成功! RMySQL下载成功! automake-1.16.tar.gz下载成功! httpuv下载成功! shiny下载成功! miniUI下载成功! devtools下载成功! recharts下载成功! 首先的首先…

shiro 550 反序列化rce

Apach shiro 是一款开源安全框架,提供身份验证,授权,会话管理等。 shiro 550 反序列化漏洞rce 通关利用它反序列化的漏洞直接执行rce 加密的用户信息序列化后储存在名为remenber -me的cooike中。攻击者可以使用shiro默认密钥伪造cooike&am…

django连接mysql一些报错解决方法

1.AttributeError: str object has no attribute ‘decode’ 2.django.db.utils.OperationalError: (2003, "Can’t connect to MySQL server on ‘localhost’ ([WinError 10] 解决方法:仔细核对#数据库引擎和#数据库的主机地址 DATABASES { ‘default’:…

2023PS beta 官方注册安装教程

该教程为官方注册下载教程,无风险。 软件介绍 Adobe Photoshop 2023版(简称PS)是一款全球流行的专业图像处理软件及照片和设计软件。Adobe Photoshop中文版是Adobe Creative Cloud 创意云桌面程序中心的图形设计软件热门产品,它是平面设计领域和数字图象…

读改变未来的九大算法笔记03_纠错码

1. 真正根源 1.1. 在电报和电话等通信系统中出现的 1.2. 理查德汉明创造了第一批纠错码:一种近乎神奇的能侦测并纠正计算机数据中错误的算法 2. 信息理论学的一部分 2.1. Information Theory 2.2. 香农通过数学展示了有可能从根本上通过一个嘈杂的、引发错误的…