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

这篇具有很好参考价值的文章主要介绍了【Python开发】FastAPI 07:Depends 依赖注入。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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 ,响应正常:

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

📌依赖项

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

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

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

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

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

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

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

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

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

1.3 OpenAPI 集成

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

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

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

依赖注入系统如此简洁的特性,让 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 ,响应正常:

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

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 返回的结果。类似下边的路径图:

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

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

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

📌 依赖项缓存

如果多次声明了同一个依赖项,例如多个依赖项共用一个子依赖项,那么 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 函数,类似于过滤器。文章来源地址https://www.toymoban.com/news/detail-474710.html

到了这里,关于【Python开发】FastAPI 07:Depends 依赖注入的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FastAPI 5 - 依赖、安全

    学习自:FastAPI教程第二季(三):依赖+安全(最快python异步并发web框架之一) https://www.bilibili.com/video/BV1p7411Z736 官方说明

    2024年02月14日
    浏览(32)
  • DAY07_Maven高级——分模块开发与设计&依赖管理&聚合与继承&属性管理&多环境配置与应用&私服

    问题导入 分模块开发对工程有什么好处? 模块拆分原则 目的:项目的扩展性变强了,方便其他项目引用相同的功能。 将原始模块按照功能拆分成若干个子模块,方便模块间的相互调用,接口共享 问题导入 一个完整的工程依据什么来进行模块的拆分? 2.1 创建Maven模块 2.2 书

    2024年02月09日
    浏览(35)
  • Spring-2-深入理解Spring 注解依赖注入(DI):简化Java应用程序开发

      掌握纯注解开发依赖注入(DI)模式 学习使用纯注解进行第三方Bean注入 问题导入 思考:如何使用注解方式将Bean对象注入到类中 1.1 使用@Autowired注解开启自动装配模式(按类型) 说明:不管是使用配置文件还是配置类,都必须进行对应的Spring注解包扫描才可以使用。@Autowired默

    2024年02月14日
    浏览(47)
  • 【Python开发】FastAPI 11:构建多文件应用

    以往的文件都是将对外接口写在一个文件里边,而作为应用来说,接口是不可避免分散到多个文件中的,比如某文件负责注册登录模块,某文件负责内管模块,某文件负责业务模块等。FastAPI 也提供了APIRouter 这一工具来进行灵活构建应用,本文将是它的示例。 目录 1 APIRout

    2024年02月10日
    浏览(31)
  • 【Python开发】FastAPI 10:SQL 数据库操作

    在 FastAPI 中使用 SQL 数据库可以使用多个 ORM 工具,例如 SQLAlchemy、Tortoise ORM 等,类似 Java 的 Mybatis 。这些 ORM 工具可以帮助我们方便地与关系型数据库进行交互,如 MySQL 、PostgreSQL等。本篇文章将介绍如何使用 SQLAlchemy 来完成数据库操作,以便让我们在 FastAPI 项目中方便地进

    2024年02月14日
    浏览(34)
  • Spring-1-深入理解Spring XML中的依赖注入(DI):简化Java应用程序开发

    前两篇文章我们介绍了什么是Spring,以及Spring的一些核心概念,并且快速快发一个Spring项目,以及详细讲解IOC,今天详细介绍一些DI(依赖注入) 能够配置setter方式注入属性值 能够配置构造方式注入属性值 能够理解什么是自动装配 思考:向一个类中传递数据的方式有几种?(给类

    2024年02月13日
    浏览(40)
  • python三大开发框架django、 flask 和 fastapi 对比

    本文讲述了什么启发了 FastAPI 的诞生,它与其他替代框架的对比,以及从中汲取的经验。 如果不是基于前人的成果,FastAPI 将不会存在。在 FastAPI 之前,前人已经创建了许多工具 。 几年来,我一直在避免创建新框架。首先,我尝试使用许多不同的框架,插件和工具来解决

    2024年02月10日
    浏览(48)
  • 【Python开发】FastAPI 09:middleware 中间件及跨域

    FastAPI 提供了一些中间件来增强它的功能,类似于 Spring 的切面编程,中间件可以在请求处理前或处理后执行一些操作,例如记录日志、添加请求头、鉴权等,跨域也是 FastAPI 中间件的一部分。 目录 1 中间件 1.1 创建中间件 1.2 使用中间件  2 跨域 2.1 跨域详解 2.2 使用 CORSM

    2024年02月09日
    浏览(53)
  • ChatGPT Plugin开发setup - Java(Spring Boot) Python(fastapi)

    记录一下快速模板,整体很简单,如果不接auth,只需要以下: 提供一个 /.well-known/ai-plugin.json 接口,返回openAI所需要的格式 提供openAPI规范的文档 CORS设置 其他的和普通的web开发类似. 本地开发就直接使用localhost即可,前几天官方localhost无法联通,最近应该修复了. 要让GPT更好理解接口

    2024年02月04日
    浏览(35)
  • 【Spring教程十】Spring框架实战:全面深入详解IOC/DI之--纯注解开发模式下的依赖注入&&注解读取properties配置文件

    欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 全面深入详解IOC/DI注解开发》 Spring为了使用注解简化开发,并没有提供

    2024年02月04日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包