FastAPI有一个非常强大但直观的依赖注入系统。
它的设计使用起来非常简单,并使任何开发人员都可以非常轻松地将其他组件与FastAPI集成在一起。

什么是依赖注入?

“依赖注入”在编程中表示,您的代码(在这种情况下,您的路径操作函数)有一种方法可以声明它需要工作和使用的东西:“依赖”。
然后,该系统(在本例中为FastAPI)将完成为代码提供所需依赖项(“注入”依赖项)所需的一切。
当您需要进行以下操作时,这将非常有用:

  • 具有共享逻辑(一次又一次地使用相同的代码逻辑)。
  • 共享数据库连接。
  • 强制执行安全性,身份验证,角色要求等。
  • 还有许多其他…

所有这些,同时最大限度地减少了代码重复。

第一步

让我们看一个非常简单的例子。它将是如此简单,以至于目前它还不是很有用。
但是通过这种方式,我们可以专注于依赖注入系统的工作方式。

创建一个依赖项或“ dependable”

让我们首先关注依赖关系。
它只是一个函数,可以采用路径操作函数可以采用的所有相同参数:”

  1. from fastapi import Depends, FastAPI
  2. app = FastAPI()
  3. async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
  4. return {"q": q, "skip": skip, "limit": limit}
  5. @app.get("/items/")
  6. async def read_items(commons: dict = Depends(common_parameters)):
  7. return commons
  8. @app.get("/users/")
  9. async def read_users(commons: dict = Depends(common_parameters)):
  10. return commons

就是这样的
2 行
它具有与所有路径操作功能相同的形状和结构。
您可以将其视为没有“装饰器”的路径操作功能(不带@app.get("/some-path"))。
它可以返回您想要的任何东西。
在这种情况下,此依赖项期望:

  • 可选查询参数q是str。
  • 可选查询参数skip是一个int,默认值为0。
  • 可选查询参数limit是一个int,默认是100.

然后,它仅返回包含这些值的字典

导入Depends

  1. from fastapi import Depends, FastAPI

声明依赖项,在“依赖项”中

与将BodyQuery等与路径操作函数参数一起使用的方式相同,将Depends与新参数一起使用:

  1. from fastapi import Depends, FastAPI
  2. app = FastAPI()
  3. async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
  4. return {"q": q, "skip": skip, "limit": limit}
  5. @app.get("/items/")
  6. async def read_items(commons: dict = Depends(common_parameters)):
  7. return commons
  8. @app.get("/users/")
  9. async def read_users(commons: dict = Depends(common_parameters)):
  10. return commons

尽管在函数参数中使用Depends的方式与使用BodyQuery等的方式相同.但是Depends的工作方式略有不同。
您只给Depends一个参数。
此参数必须类似于函数。
并且该函数采用与路径操作函数相同的方式获取参数

:::info 在下一章中,您将看到除功能以外的其他“事物”还可以用作依赖项。 :::

每当有新请求到达时,FastAPI都会处理:

  • 用正确的参数调用依赖项(“dependable”)。
  • 从函数中获取结果。
  • 将该结果分配给路径操作函数中的参数。

这样,您只需编写一次共享代码,FastAPI便会为路径操作调用共享代码。

:::tips 请注意,您不必创建特殊的类并将其传递给FastAPI来“注册”它或类似的东西。
您只需将其传递给Depends,FastAPI就会知道如何进行其余的工作。 :::

为了async或者不是async

由于依赖项还将由FastAPI调用(与路径操作函数相同),因此在定义函数时将应用相同的规则。
您可以使用async def或普通def
而且,您可以在常规def路径操作函数内部使用async def声明依赖关系,也可以在async def路径操作函数内部使用def依赖声明,等等。
这没关系。 FastAPI将知道该怎么办。

:::tips 注意
如果你不知道,查看Async: “In a Hurry?”部分来了解asyncawait。 :::

与OpenAPI集成

您的依存关系(和子依存关系)的所有请求声明,验证和要求都将集成在同一OpenAPI架构中。
因此,交互式文档也将从这些依赖项中获取所有信息:
依赖 - 图1

简单的使用

如果您查看它,则将在路径和操作匹配时声明使用路径操作函数,然后FastAPI负责使用正确的参数调用该函数并使用响应。
实际上,所有(或大多数)Web框架都以相同的方式工作。
您永远不会直接调用这些函数。它们由您的框架(在本例中为FastAPI)调用。
使用Dependency Injection系统,您还可以告诉FastAPI您的路径操作函数还“依赖”在您的路径操作函数之前应执行的其他操作,FastAPI将负责执行它并“注入”结果。
相同的“依赖注入”概念的其他通用术语是:

  • resources
  • providers
  • services
  • injectables
  • components

    FastAPI 外挂程式(plug-ins)

    可以使用依赖注入系统来构建集成和“插件”。但是实际上,实际上并不需要创建“插件”,因为通过使用依赖关系,可以声明无限数量的集成和交互,这些集成和交互可用于您的路径操作功能。
    并且可以以非常简单直观的方式创建依赖关系,从而允许您仅导入所需的Python程序包,并将其与API函数集成为几行代码。
    在下一章中,您将看到有关关系和NoSQL数据库,安全性等的示例。

    FastAPI兼容性

    依赖注入系统的简单性使FastAPI兼容:

  • 所有关系数据库

  • NoSQL数据库
  • 外部软件包
  • 外部API
  • 身份验证和授权系统
  • API使用情况监视系统
  • 响应数据注入系统
  • 等等。

    简单有力的

    尽管分层依赖注入系统的定义和使用非常简单,但是它仍然非常强大。
    您可以定义依赖关系,而依赖关系又可以自己定义依赖关系。
    最后,构建了层次结构的依赖关系树,并且依赖关系注入系统将为您解决所有这些依赖关系(及其子依赖关系),并在每个步骤中提供(注入)结果。
    例如,假设您有4个API端点(路径操作):

  • /items/public/

  • /items/private/
  • /users/{user_id}/activate
  • /items/pro/

那么您可以为每个请求添加不同的权限要求,包括依赖性和子依赖性:
image.png

集成OpenAPI

所有这些依赖项在声明其要求的同时,还向路径操作添加参数,验证等。
FastAPI将负责将其全部添加到OpenAPI架构中,以便在交互式文档系统中显示它。