FastAPI 教程翻译 - 用户指南 25 - 依赖项
FastAPI Tutorial - User Guide - Dependencies
First Steps
第一步
FastAPI has a very powerful but intuitive Dependency Injection system.
FastAPI 具有非常强大而且直观的依赖注入系统。
It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with FastAPI.
它的设计使用起来非常简单,并使任何开发人员都可以非常轻松地将其他组件与 FastAPI 集成在一起。
What is “Dependency Injection”
什么是『依赖注入』
"Dependency Injection" means, in programming, that there is a way for your code (in this case, your path operation functions) to declare things that it requires to work and use: “dependencies”.
『依赖注入』在编程中表示您的代码(在这种情况下,表示您的路径操作函数)有一种方法可以声明其需要工作和使用的东西:『依赖』。
And then, that system (in this case FastAPI) will take care of doing whatever is needed to provide your code with those needed dependencies (“inject” the dependencies).
然后,该系统(在本例中为 FastAPI)将负责完成为代码提供所需依赖项的所有操作(『注入』依赖项)。
This is very useful when you need to:
当您需要:
-
Have shared logic (the same code logic again and again).
具有共享逻辑(一次又一次相同的代码逻辑)。
-
Share database connections.
共享数据库连接。
-
Enforce security, authentication, role requirements, etc.
强制执行安全性、身份验证、角色要求等。
-
And many other things…
还有很多其他事情……
All these, while minimizing code repetition.
所有这些,同时最大限度地减少了代码重复。
First Steps
第一步
Let’s see a very simple example. It will be so simple that it is not very useful, for now.
让我们看一个非常简单的例子。它将是如此简单,以至于目前它还不是很有用。
But this way we can focus on how the Dependency Injection system works.
但是通过这种方式,我们可以专注于依赖注入系统的工作方式。
Create a dependency, or “dependable”
创建一个依赖项,或『被依赖项』
Let’s first focus on the dependency.
让我们首先关注依赖项。
It is just a function that can take all the same parameters that a path operation function can take:
它只是一个函数,可以采用路径操作函数可以采用的所有相同参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from fastapi import Depends, FastAPI app = FastAPI() async def common_parameters(q: str = 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)): return commons @app.get("/users/") async def read_users(commons: dict = Depends(common_parameters)): return commons |
That’s it.
仅仅需要。
2 lines.
两行。
And it has the same shape and structure that all your path operation functions.
它具有与所有路径操作函数相同的形状和结构。
You can think of it as a path operation function without the “decorator” (without the
您可以将其视为没有『装饰器』(没有
And it can return anything you want.
它可以返回您想要的任何东西。
In this case, this dependency expects:
在这种情况下,此依赖项期望如下:
-
An optional query parameter
q that is astr .可选查询参数
q 为str 。 -
An optional query parameter
skip that is anint , and by default is0 .可选查询参数
skip 为int ,默认值0 。 -
An optional query parameter
limit that is anint , and by default is100 .可选查询参数
limit 为int ,默认值100 。
And then it just returns a
然后,它仅返回包含这些值的
Import Depends
导入 Depends
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from fastapi import Depends, FastAPI app = FastAPI() async def common_parameters(q: str = 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)): return commons @app.get("/users/") async def read_users(commons: dict = Depends(common_parameters)): return commons |
Declare the dependency, in the “dependant”
在『需依赖项』中声明依赖项
The same way you use
与将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from fastapi import Depends, FastAPI app = FastAPI() async def common_parameters(q: str = 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)): return commons @app.get("/users/") async def read_users(commons: dict = Depends(common_parameters)): return commons |
Although you use
尽管您在函数的参数中使用
You only give
您只需给
This parameter must be something like a function.
此参数必须类似于函数。
And that function takes parameters in the same way that path operation functions do.
该函数采用与路径操作函数相同的方式获取参数。
Tip
提示
You’ll see what other “things”, apart from functions, can be used as dependencies in the next chapter.
在下一章中,您将看到除函数之外,还有哪些其他『事物』可用作依赖项。
Whenever a new request arrives, FastAPI will take care of:
每当有新请求到达时,FastAPI 就会处理:
-
Calling your dependency (“dependable”) function with the correct parameters.
使用正确的参数调用依赖项(『被依赖项』)函数。
-
Get the result from your function.
从函数中获取结果。
-
Assign that result to the parameter in your path operation function.
将结果分配给路径操作函数中的参数。

This way you write shared code once and FastAPI takes care of calling it for your path operations.
这样,您只需编写一次共享代码,并且 FastAPI 可以为您的路径操作进行调用。
Check
检查
Notice that you don’t have to create a special class and pass it somewhere to FastAPI to “register” it or anything similar.
请注意,您不必创建特殊类并将其传递到 FastAPI 来『注册』它或类似的东西。
You just pass it to
Depends and FastAPI knows how to do the rest.您只需将其传递给
Depends ,FastAPI 就知道如何进行其余操作。
To async or not to async async
还是不async
As dependencies will also be called by FastAPI (the same as your path operation functions), the same rules apply while defining your functions.
由于依赖项还将由 FastAPI 调用(与路径操作函数相同),因此在定义函数时将应用相同的规则。
You can use
您可以使用
And you can declare dependencies with
您可以在普通的
It doesn’t matter. FastAPI will know what to do.
没关系 FastAPI 会知道该怎么做。
Note
注意
If you don’t know, check the Async: “In a hurry?” section about
async andawait in the docs.如果您不知道,请在文档中查看 Async: “In a hurry?” 部分,有关
async 和await 。
Integrated with OpenAPI
与 OpenAPI 集成
All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
您的依赖项(和子依赖项)的所有请求声明、验证和要求都将集成在同一 OpenAPI 架构中。
So, the interactive docs will have all the information from these dependencies too:
因此,交互式文档也将从这些依赖项中获取所有信息:

Simple usage
简单用法
If you look at it, path operation functions are declared to be used whenever a path and operation matches, and then FastAPI takes care of calling the function with the correct parameters and use the response.
如果您看一看,只要路径和操作匹配,就会声明使用路径操作函数,然后 FastAPI 会使用正确的参数来调用该函数并使用响应。
Actually, all (or most) of the web frameworks work in this same way.
实际上,所有(或大多数)Web框架都以相同的方式工作。
You never call those functions directly. They are called by your framework (in this case, FastAPI).
您永远不会直接调用这些函数。它们由您的框架调用(在本例中为 FastAPI)。
With the Dependency Injection system, you can also tell FastAPI that your path operation function also “depends” on something else that should be executed before your path operation function, and FastAPI will take care of executing it and “injecting” the results.
使用依赖注入系统,您还可以告诉 FastAPI,您的路径操作函数也『依赖』在您的路径操作函数之前应执行的其他操作,并且 FastAPI 会注意执行并『注入』结果中。
Other common terms for this same idea of “dependency injection” are:
相同的『依赖注入』概念的其他通用术语是:
-
resources
资源
-
providers
提供者
-
services
服务
-
injectables
可注入的
-
components
组件
FastAPI plug-ins
FastAPI 插件
Integrations and "plug-in"s can be built using the Dependency Injection system. But in fact, there is actually no need to create “plug-ins”, as by using dependencies it’s possible to declare an infinite number of integrations and interactions that become available to your path operation functions.
可以使用依赖注入系统来构建集成和『插件』。但实际上,无需创建『插件』,因为通过使用依赖项,可以声明无限数量的集成和交互,这些集成和交互可用于路径操作函数。
And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, literally.
并且可以以非常简单直观的方式创建依赖项,从而使您可以导入所需的 Python 包,并将它们与 API 函数集成为几行代码,即字面意思。
You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
在下一章中,您将看到有关关系型数据库和 NoSQL 数据库、安全性等的示例。
FastAPI compatibility
FastAPI 兼容性
The simplicity of the dependency injection system makes FastAPI compatible with:
依赖注入系统的简单性使 **FastAPI **兼容如下:
-
all the relational databases
所有关系型数据库
-
NoSQL databases
NoSQL 数据库
-
external packages
外部包
-
external APIs
外部 API
-
authentication and authorization systems
认证和授权系统
-
API usage monitoring systems
API 使用情况监控系统
-
response data injection systems
响应数据注入系统
-
etc.
等等
Simple and Powerful
简单而强大
Although the hierarchical dependency injection system is very simple to define and use, it’s still very powerful.
尽管分层依赖注入系统的定义和使用非常简单,但它仍然非常强大。
You can define dependencies that in turn can define dependencies themselves.
您可以定义依赖项,而依赖项又可以自己定义依赖项。
In the end, a hierarchical tree of dependencies is built, and the Dependency Injection system takes care of solving all these dependencies for you (and their sub-dependencies) and providing (injecting) the results at each step.
最后,构建了层次结构的依赖项树,依赖注入系统会为您解决所有这些依赖项(及其子依赖项),并在每个步骤中提供(注入)结果。
For example, let’s say you have 4 API endpoints (path operations):
例如,假设您有 4 个 API 端点(路径操作):
/items/public/ /items/private/ /users/{user_id}/activate /items/pro/
then you could add different permission requirements for each of them just with dependencies and sub-dependencies:
那么您可以为每个依赖项和子依赖项添加不同的权限要求:

Integrated with OpenAPI
与 OpenAPI 集成
All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your path operations.
所有这些依赖项在声明其要求的同时,还向路径操作中添加了参数、验证等。
FastAPI will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.
FastAPI 将负责将其全部添加到 OpenAPI 架构中,以便在交互式文档系统中显示它。
Classes as Dependencies
类作为依赖项
Before diving deeper into the Dependency Injection system, let’s upgrade the previous example.
在深入研究依赖注入系统之前,让我们升级前面的示例。
A dict from the previous example
上例中的 dict
In the previous example, we were returning a
在前面的示例中,我们从依赖项(被依赖项)中返回一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from fastapi import Depends, FastAPI app = FastAPI() async def common_parameters(q: str = 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)): return commons @app.get("/users/") async def read_users(commons: dict = Depends(common_parameters)): return commons |
But then we get a
然后我们在路径操作函数的参数
And we know that editors can’t provide a lot of support (like completion) for
而且我们知道编辑器不能为
We can do better…
我们可以做得更好……
What makes a dependency
是什么导致依赖
Up to now you have seen dependencies declared as functions.
到目前为止,您已经看到依赖项声明为函数。
But that’s not the only way to declare dependencies (although it would probably be the more common).
但这不是声明依赖项的唯一方法(尽管可能更常见)。
The key factor is that a dependency should be a “callable”.
关键因素是依赖项应该是『可调用的』。
A “callable” in Python is anything that Python can “call” like a function.
Python 中的『可调用的』是可以像函数一样『调用』的任何东西。
So, if you have an object
因此,如果您有一个对象
1 | something() |
or
或者
1 | something(some_argument, some_keyword_argument="foo") |
then it is a “callable”.
那么它是一个『可调用的』。
Classes as dependencies
类作为依赖项
You might notice that to create an instance of a Python class, you use that same syntax.
您可能会注意到,使用相同的语法来创建 Python 类的实例。
For example:
例如:
1 2 3 4 5 6 | class Cat: def __init__(self, name: str): self.name = name fluffy = Cat(name="Mr Fluffy") |
In this case,
在这种情况下,
And to create
要创建
So, a Python class is also a callable.
因此,Python类也是 可调用的。
Then, in FastAPI, you could use a Python class as a dependency.
然后,在 FastAPI 中,您可以使用 Python 类作为依赖项。
What FastAPI actually checks is that it is a “callable” (function, class or anything else) and the parameters defined.
FastAPI 实际检查的是它是否为『可调用的』(函数、类或者其他任何东西),并且定义了参数。
If you pass a “callable” as a dependency in FastAPI, it will analyze the parameters for that “callable”, and process them in the same way as the parameters for a path operation function. Including sub-dependencies.
如果您在 FastAPI 中将『可调用的』作为依赖项传递,它将分析该『可调用的』参数,并以与路径操作函数的参数相同的方式处理它们。包括子依赖项。
That also applies to callables with no parameters at all. The same as it would be for path operation functions with no parameters.
这也适用于根本没有参数的可调用对象。与没有参数的路径操作函数相同。
Then, we can change the dependency “dependable”
然后,我们可以将依赖项『被依赖项』
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from fastapi import Depends, FastAPI app = FastAPI() fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] class CommonQueryParams: def __init__(self, q: str = None, skip: int = 0, limit: int = 100): self.q = q self.skip = skip self.limit = limit @app.get("/items/") async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)): response = {} if commons.q: response.update({"q": commons.q}) items = fake_items_db[commons.skip : commons.skip + commons.limit] response.update({"items": items}) return response |
Pay attention to the
注意用于创建类实例的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from fastapi import Depends, FastAPI app = FastAPI() fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] class CommonQueryParams: def __init__(self, q: str = None, skip: int = 0, limit: int = 100): self.q = q self.skip = skip self.limit = limit @app.get("/items/") async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)): response = {} if commons.q: response.update({"q": commons.q}) items = fake_items_db[commons.skip : commons.skip + commons.limit] response.update({"items": items}) return response |
…it has the same parameters as our previous
…… 具有与我们先前的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from fastapi import Depends, FastAPI app = FastAPI() async def common_parameters(q: str = 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)): return commons @app.get("/users/") async def read_users(commons: dict = Depends(common_parameters)): return commons |
Those parameters are what FastAPI will use to “solve” the dependency.
这些参数是 FastAPI 用来『解决』依赖项的参数。
In both cases, it will have:
在这两种情况下,它都将具有:
-
an optional
q query parameter.可选的
q 查询参数。 -
a
skip query parameter, with a default of0 .一个
skip 查询参数,默认值为0 。 -
a
limit query parameter, with a default of100 .一个
limit 查询参数,默认值为100 。
In both cases the data will be converted, validated, documented on the OpenAPI schema, etc.
在这两种情况下,数据都将在 OpenAPI 架构上进行转换、验证和记录等。
Use it
使用它
Now you can declare your dependency using this class.
现在,您可以使用此类声明依赖项。
And as when FastAPI calls that class the value that will be passed as
并且当 FastAPI 调用该类时,将作为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from fastapi import Depends, FastAPI app = FastAPI() fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] class CommonQueryParams: def __init__(self, q: str = None, skip: int = 0, limit: int = 100): self.q = q self.skip = skip self.limit = limit @app.get("/items/") async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)): response = {} if commons.q: response.update({"q": commons.q}) items = fake_items_db[commons.skip : commons.skip + commons.limit] response.update({"items": items}) return response |
Type annotation vs Depends
类型注释与 Depends
In the code above, you are declaring
在上面的代码中,您将
1 | commons: CommonQueryParams = Depends(CommonQueryParams) |
The last
最后一个
1 | ... = Depends(CommonQueryParams) |
…is what FastAPI will actually use to know what is the dependency.
…… 是 FastAPI 实际用于了解依赖项的内容。
From it is that FastAPI will extract the declared parameters and that is what FastAPI will actually call.
从那里开始,FastAPI 将提取声明的参数,而这正是 FastAPI 实际调用的参数。
In this case, the first
在这种情况下,第一个
1 | commons: CommonQueryParams ... |
…doesn’t have any special meaning for FastAPI. FastAPI won’t use it for data conversion, validation, etc. (as it is using the
…… 对于 FastAPI 没有任何特殊含义。FastAPI 不会将其用于数据转换、验证等(因为它正在使用
You could actually write just:
您实际上可以只写:
1 | commons = Depends(CommonQueryParams) |
…as in:
…… 位于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from fastapi import Depends, FastAPI app = FastAPI() fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] class CommonQueryParams: def __init__(self, q: str = None, skip: int = 0, limit: int = 100): self.q = q self.skip = skip self.limit = limit @app.get("/items/") async def read_items(commons=Depends(CommonQueryParams)): response = {} if commons.q: response.update({"q": commons.q}) items = fake_items_db[commons.skip : commons.skip + commons.limit] response.update({"items": items}) return response |
But declaring the type is encouraged as that way your editor will know what will be passed as the parameter
但是鼓励声明类型,因为这样您的编辑器将知道作为参数

Shortcut
捷径
But you see that we are having some code repetition here, writing
但是您会看到我们在这里有一些代码重复,写了两次
1 | commons: CommonQueryParams = Depends(CommonQueryParams) |
FastAPI provides a shortcut for these cases, in where the dependency is specifically a class that FastAPI will “call” to create an instance of the class itself.
FastAPI 为这些情况提供了一种捷径,在这些情况下,特定的依赖项是 FastAPI 将『调用』以创建类本身实例的类。
For those specific cases, you can do the following:
对于这些特定情况,您可以执行以下操作:
Instead of writing:
而不是写:
1 | commons: CommonQueryParams = Depends(CommonQueryParams) |
…you write:
…… 您可以写:
1 | commons: CommonQueryParams = Depends() |
So, you can declare the dependency as the type of the variable, and use
因此,您可以将依赖项声明为变量的类型,并使用
So, the same example would look like:
因此,相同的示例如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from fastapi import Depends, FastAPI app = FastAPI() fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] class CommonQueryParams: def __init__(self, q: str = None, skip: int = 0, limit: int = 100): self.q = q self.skip = skip self.limit = limit @app.get("/items/") async def read_items(commons: CommonQueryParams = Depends()): response = {} if commons.q: response.update({"q": commons.q}) items = fake_items_db[commons.skip : commons.skip + commons.limit] response.update({"items": items}) return response |
…and FastAPI will know what to do.
…… 并且 FastAPI 将知道该怎么做。
Tip
提示
If all that seems more confusing than helpful, disregard it, you don’t need it.
如果所有这些看起来比有用的都令人困惑,请无视它,您不需要它。
It is just a shortcut. Because FastAPI cares about helping you minimize code repetition.
这只是捷径。因为 FastAPI 希望帮助您最大程度地减少代码重复。
Sub-dependencies
子依赖项
You can create dependencies that have sub-dependencies.
您可以创建具有子依赖项的依赖项。
They can be as deep as you need them to be.
它们可以像您需要的一样深。
FastAPI will take care of solving them.
FastAPI 将负责解决它们。
First dependency “dependable”
第一个依赖项『被依赖项』
You could create a first dependency (“dependable”) like:
您可以创建第一个依赖项(『被依赖项』),例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from fastapi import Cookie, Depends, FastAPI app = FastAPI() def query_extractor(q: str = None): return q def query_or_cookie_extractor( q: str = Depends(query_extractor), last_query: str = Cookie(None) ): if not q: return last_query return q @app.get("/items/") async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)): return {"q_or_cookie": query_or_default} |
It declares an optional query parameter
它声明一个可选的查询参数
This is quite simple (not very useful), but will help us focus on how the sub-dependencies work.
这很简单(不是很有用),但是将帮助我们专注于子依赖项的工作方式。
Second dependency, “dependable” and “dependant”
第二个依赖项,『被依赖项』和『需依赖项』
Then you can create another dependency function (a “dependable”) that at the same time declares a dependency of its own (so it is a “dependant” too):
然后,您可以创建另一个依赖项函数(一个『被依赖项』),同时声明其自己的依赖项(因此它也是一个『需依赖项』):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from fastapi import Cookie, Depends, FastAPI app = FastAPI() def query_extractor(q: str = None): return q def query_or_cookie_extractor( q: str = Depends(query_extractor), last_query: str = Cookie(None) ): if not q: return last_query return q @app.get("/items/") async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)): return {"q_or_cookie": query_or_default} |
Let’s focus on the parameters declared:
让我们关注声明的参数:
-
Even though this function is a dependency (“dependable”) itself, it also declares another dependency (it “depends” on something else).
即使此函数本身是一个依赖项(『被依赖项』),它也声明了另一个依赖项(它『依赖』其他东西)。
-
It depends on the
query_extractor , and assigns the value returned by it to the parameterq .它取决于
query_extractor ,并将其返回的值分配给参数q 。
-
-
It also declares an optional
last_query cookie, as astr .它还声明了一个可选的
last_query cookie,作为str 。-
Let’s imagine that if the user didn’t provide any query
q , we just use the last query used, that we had saved to a cookie before.假设用户未提供任何查询
q ,我们将使用上次使用的查询,该查询之前已保存到 Cookie 中。
-
Use the dependency
使用依赖项
Then we can use the dependency with:
然后,我们可以将依赖项用于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from fastapi import Cookie, Depends, FastAPI app = FastAPI() def query_extractor(q: str = None): return q def query_or_cookie_extractor( q: str = Depends(query_extractor), last_query: str = Cookie(None) ): if not q: return last_query return q @app.get("/items/") async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)): return {"q_or_cookie": query_or_default} |
Info
信息
Notice that we are only declaring one dependency in the path operation function, the
query_or_cookie_extractor .请注意,我们仅在路径操作函数中声明了一个依赖项,即
query_or_cookie_extractor 。But FastAPI will know that it has to solve
query_extractor first, to pass the results of that toquery_or_cookie_extractor while calling it.但是,FastAPI 会知道它必须首先解决
query_extractor ,然后在调用它时将结果传递给query_or_cookie_extractor 。

Using the same dependency multiple times
多次使用相同的依赖项
If one of your dependencies is declared multiple times for the same path operation, for example, multiple dependencies have a common sub-dependency, FastAPI will know to call that sub-dependency only once per request.
例如,如果为同一个路径操作多次声明您的一个依赖项,则多个依赖项具有一个公共的子依赖项,FastAPI 将知道每个请求仅调用一次该子依赖项。
And it will save the returned value in a “cache” and pass it to all the “dependants” that need it in that specific request, instead of calling the dependency multiple times for the same request.
并且它将返回的值保存在『缓存』中,并将其传递给该特定请求中需要它的所有『需依赖项』,而不是针对同一请求多次调用依赖项。
In an advanced scenario where you know you need the dependency to be called at every step (possibly multiple times) in the same request instead of using the “cached” value, you can set the parameter
在高级场景中,您知道需要在同一请求中的每个步骤(可能多次)上调用依赖项,而不是使用『缓存值』,因此可以在使用
1 2 | async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): return {"fresh_value": fresh_value} |
Recap
回顾
Apart from all the fancy words used here, the Dependency Injection system is quite simple.
除了这里使用的所有花哨的单词以外,依赖注入系统非常简单。
Just functions that look the same as the path operation functions.
看起来与路径操作函数相同的函数。
But still, it is very powerful, and allows you to declare arbitrarily deeply nested dependency “graphs” (trees).
但是,它非常强大,并且允许您声明任意深度嵌套的依赖项『图形』(树)。
Tip
提示
All this might not seem as useful with these simple examples.
这些简单的示例似乎对所有这些都没有用。
But you will see how useful it is in the chapters about security.
但您会在有关安全性的章节中看到它的用处。
And you will also see the amounts of code it will save you.
并且您还看到它将为您节省的代码量。
Dependencies in path operation decorators
路径操作修饰符中的依赖项
In some cases you don’t really need the return value of a dependency inside your path operation function.
在某些情况下,您实际上不需要路径操作函数中的依赖项的返回值。
Or the dependency doesn’t return a value.
或依赖项不返回值。
But you still need it to be executed/solved.
但是您仍然需要执行/解决它。
For those cases, instead of declaring a path operation function parameter with
在这种情况下,您可以在路径操作装饰器中添加
Add dependencies to the path operation decorator
在路径操作装饰器中添加 dependencies
The path operation decorator receives an optional argument
路径操作装饰器接收一个可选的参数
It should be a
它应该是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 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("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) async def read_items(): return [{"item": "Foo"}, {"item": "Bar"}] |
These dependencies will be executed/solved the same way normal dependencies. But their value (if they return any) won’t be passed to your path operation function.
这些依赖项将以与普通依赖项相同的方式执行/解决。但是,它们的值(如果它们返回任何值)将不会传递给您的路径操作函数。
Tip
提示
Some editors check for unused function parameters, and show them as errors.
有些编辑器会检查未使用的功能参数,并将它们显示为错误。
Using these
dependencies in the path operation decorator you can make sure they are executed while avoiding editor/tooling errors.在路径操作装饰器中使用这些
dependencies ,可以确保在避免编辑器/工具错误的情况下执行了它们。It might also help avoiding confusion for new developers that see an un-used parameter in your code and could think it’s unnecessary.
对于那些在代码中看到未使用的参数并且认为不必要的新开发人员,这也可能有助于避免混淆。
Dependencies errors and return values
依赖项错误和返回值
You can use the same dependency functions you use normally.
您可以使用与通常使用的相同的依赖项功能。
Dependency requirements
依赖性要求
They can declare request requirements (like headers) or other sub-dependencies:
他们可以声明请求要求(例如 headers)或其他子依赖项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 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("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) async def read_items(): return [{"item": "Foo"}, {"item": "Bar"}] |
Raise exceptions
触发异常
These dependencies can
这些依赖可以
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 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("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) async def read_items(): return [{"item": "Foo"}, {"item": "Bar"}] |
Return values
返回值
And they can return values or not, the values won’t be used.
而且它们可以返回值或不返回值,将不会使用这些值。
So, you can re-use a normal dependency (that returns a value) you already use somewhere else, and even though the value won’t be used, the dependency will be executed:
因此,您可以重复使用已经在其他地方使用的普通依赖项(返回一个值),即使不使用该值,该依赖项也将被执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 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("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) async def read_items(): return [{"item": "Foo"}, {"item": "Bar"}] |
Dependencies for a group of path operations
一组路径操作的依赖项
Later, when reading about how to structure bigger applications (Bigger Applications - Multiple Files), possibly with multiple files, you will learn how to declare a single
稍后,当阅读有关如何构造可能包含多个文件的更大应用程序(更大的应用程序 - 多个文件)时,您将学习如何声明一个一组路径操作的单个
Dependencies with yield
依赖项与yield
FastAPI supports dependencies that do some extra steps after finishing.
FastAPI 支持在完成后会执行一些额外步骤的依赖项。
To do this, use
为此,请使用
Tip
提示
Make sure to use
yield one single time.确保单次使用
yield 。
Info
信息
For this to work, you need to use Python 3.7 or above, or in Python 3.6, install the “backports”:
为此,您需要使用 Python 3.7 或更高版本,或者在 Python 3.6 中,安装『backports』:
1 pip install async-exit-stack async-generatorThis installs async-exit-stack and async-generator.
这会安装 async-exit-stack 和 async-generator。
Technical Details
技术细节
Any function that is valid to use with:
任何可与以下功能一起使用的有效功能:
@contextlib.contextmanager or@contextlib.asynccontextmanager would be valid to use as a FastAPI dependency.
可以有效地用作 FastAPI 依赖项。
In fact, FastAPI uses those two decorators internally.
实际上,FastAPI 在内部使用了这两个装饰器。
A database dependency with yield
具有 yield 的数据库依赖项
For example, you could use this to create a database session and close it after finishing.
例如,您可以使用它来创建数据库会话并在完成后关闭它。
Only the code prior to and including the
发送响应之前,仅执行
1 2 3 4 5 6 | async def get_db(): db = DBSession() try: yield db finally: db.close() |
The yielded value is what is injected into path operations and other dependencies:
产生的值是注入到路径操作和其他依赖项中的值:
1 2 3 4 5 6 | async def get_db(): db = DBSession() try: yield db finally: db.close() |
The code following the
传递响应后,将执行
1 2 3 4 5 6 | async def get_db(): db = DBSession() try: yield db finally: db.close() |
Tip
提示
You can use
async or normal functions.您可以使用
async 或普通函数。FastAPI will do the right thing with each, the same as with normal dependencies.
FastAPI 会对每种函数做正确的事情,与普通的依赖项相同。
A dependency with yield and try
依赖于 yield 和 try
If you use a
如果在具有
For example, if some code at some point in the middle, in another dependency or in a path operation, made a database transaction “rollback” or create any other error, you will receive the exception in your dependency.
例如,如果某个代码在中间,其他依赖项或路径操作中的某个点上使数据库事务『回滚』或创建任何其他错误,则您将在依赖项中收到异常。
So, you can look for that specific exception inside the dependency with
因此,您可以使用
In the same way, you can use
以同样的方式,无论是否存在异常,您都可以使用
1 2 3 4 5 6 | async def get_db(): db = DBSession() try: yield db finally: db.close() |
Sub-dependencies with yield
具有 yield 的子依赖项
You can have sub-dependencies and “trees” of sub-dependencies of any size and shape, and any or all of them can use
您可以拥有任何大小和形状的子依赖项的『树』,并且它们中的任何一个或全部都可以使用
FastAPI will make sure that the “exit code” in each dependency with
FastAPI 将确保每个带有
For example,
例如,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from fastapi import Depends async def dependency_a(): dep_a = generate_dep_a() try: yield dep_a finally: dep_a.close() async def dependency_b(dep_a=Depends(dependency_a)): dep_b = generate_dep_b() try: yield dep_b finally: dep_b.close(dep_a) async def dependency_c(dep_b=Depends(dependency_b)): dep_c = generate_dep_c() try: yield dep_c finally: dep_c.close(dep_b) |
And all of them can use
所有都可以使用
In this case
在这种情况下,
And, in turn,
并且,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from fastapi import Depends async def dependency_a(): dep_a = generate_dep_a() try: yield dep_a finally: dep_a.close() async def dependency_b(dep_a=Depends(dependency_a)): dep_b = generate_dep_b() try: yield dep_b finally: dep_b.close(dep_a) async def dependency_c(dep_b=Depends(dependency_b)): dep_c = generate_dep_c() try: yield dep_c finally: dep_c.close(dep_b) |
The same way, you could have dependencies with
用同样的方式,您可能会混用
And you could have a single dependency that requires several other dependencies with
而且您可能只有一个依赖项,需要其他一些依赖项,例如
You can have any combinations of dependencies that you want.
您可以拥有所需的依赖项的任意组合。
FastAPI will make sure everything is run in the correct order.
FastAPI 将确保一切均以正确的顺序运行。
Technical Details
技术细节
This works thanks to Python’s Context Managers.
这要归功于Python的 Context Managers。
FastAPI uses them internally to achieve this.
FastAPI 在内部使用它们来实现这一目标。
Dependencies with yield and HTTPException
具有 yield 和 HTTPException 的依赖项
You saw that you can use dependencies with
您已经看到可以将依赖项与
It might be tempting to raise an
在
The exit code in dependencies with
带有
There’s nothing catching exceptions thrown by your dependencies in the exit code (after the
在退出代码中(
So, if you raise an
因此,如果在
This is what allows anything set in the dependency (e.g. a DB session) to, for example, be used by background tasks.
这就是允许在依赖项(例如:数据库会话)中设置的任何内容供后台任务使用的方法。
Background tasks are run after the response has been sent. So there’s no way to raise an
发送响应后,将在之后运行后台任务。因此,没有办法触发
But if a background task creates a DB error, at least you can rollback or cleanly close the session in the dependency with
但是,如果后台任务创建了一个数据库错误,至少您可以回退或完全清除带有
If you have some code that you know could raise an exception, do the most normal/“Pythonic” thing and add a
如果您知道某些代码可能触发异常,请执行最正常 / 『Pythonic』的操作,并在该部分代码中添加一个
If you have custom exceptions that you would like to handle before returning the response and possibly modifying the response, maybe even raising an
如果在返回响应并可能修改响应之前(如果有)想要处理自定义异常,甚至可能触发 HTTPException,请创建一个 自定义异常处理程序。
Tip
提示
You can still raise exceptions including
HTTPException before theyield . But not after.您仍然可以在
yield 之前触发包括HTTPException 在内的异常。而不是之后。
The sequence of execution is more or less like this diagram. Time flows from top to bottom. And each column is one of the parts interacting or executing code.
执行顺序或多或少类似于此图。时间从上到下流动。每列都是交互或执行代码的一部分。


Info
信息
Only one response will be sent to the client. It might be one of the error responses or it will be the response from the path operation.
仅一个响应将发送到客户端。它可能是错误响应之一,也可能是路径操作的响应。
After one of those responses is sent, no other response can be sent.
发送这些响应之一后,将无法再发送其他响应。
Tip
提示
This diagram shows
HTTPException , but you could also raise any other exception for which you create a Custom Exception Handler. And that exception would be handled by that custom exception handler instead of the dependency exit code.此图显示了
HTTPException ,但是您也可以触发其他任何异常,以为其创建 自定义异常处理程序。而且该异常将由该自定义异常处理程序处理,而不是依赖项退出代码处理。But if you raise an exception that is not handled by the exception handlers, it will be handled by the exit code of the dependency.
但是,如果触发了异常处理程序未处理的异常,则该异常将由依赖项的退出代码处理。
Context Managers
上下文管理器
What are “Context Managers”
什么是『上下文管理器』
“Context Managers” are any of those Python objects that you can use in a
『上下文管理器』是可以在
For example, you can use
例如,您可以使用
1 2 3 | with open("./somefile.txt") as f: contents = f.read() print(contents) |
Underneath, the
在下面,
When the
当
When you create a dependency with
当使用
Using context managers in dependencies with yield
在具有 yield 的依赖项中使用上下文管理器
Warning
警告
This is, more or less, an “advanced” idea.
这或多或少是一个『先进』的想法。
If you are just starting with FastAPI you might want to skip it for now.
如果您只是从 FastAPI 开始,那么您可能现在要跳过它。
In Python, you can create Context Managers by creating a class with two methods:
在 Python 中,您可以通过 使用两种方法创建类:
You can also use them inside of FastAPI dependencies with
您还可以通过在依赖函数内部使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class MySuperContextManager: def __init__(self): self.db = DBSession() def __enter__(self): return self.db def __exit__(self, exc_type, exc_value, traceback): self.db.close() async def get_db(): with MySuperContextManager() as db: yield db |
Tip
提示
Another way to create a context manager is with:
创建上下文管理器的另一种方法是:
@contextlib.contextmanager or@contextlib.asynccontextmanager using them to decorate a function with a single
yield .使用它们来装饰具有一个
yield 的函数。That’s what FastAPI uses internally for dependencies with
yield .这就是 FastAPI 在内部用于
yield 的依赖项。But you don’t have to use the decorators for FastAPI dependencies (and you shouldn’t).
但是,您不必将装饰器用于 FastAPI 依赖项(也不应使用)。
FastAPI will do it for you internally.
FastAPI 将在内部为您完成。
ight want to skip it for now.如果您只是从 FastAPI 开始,那么您可能现在要跳过它。
In Python, you can create Context Managers by creating a class with two methods:
在 Python 中,您可以通过 使用两种方法创建类:
You can also use them inside of FastAPI dependencies with
您还可以通过在依赖函数内部使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class MySuperContextManager: def __init__(self): self.db = DBSession() def __enter__(self): return self.db def __exit__(self, exc_type, exc_value, traceback): self.db.close() async def get_db(): with MySuperContextManager() as db: yield db |
Tip
提示
Another way to create a context manager is with:
创建上下文管理器的另一种方法是:
@contextlib.contextmanager or@contextlib.asynccontextmanager using them to decorate a function with a single
yield .使用它们来装饰具有一个
yield 的函数。That’s what FastAPI uses internally for dependencies with
yield .这就是 FastAPI 在内部用于
yield 的依赖项。But you don’t have to use the decorators for FastAPI dependencies (and you shouldn’t).
但是,您不必将装饰器用于 FastAPI 依赖项(也不应使用)。
FastAPI will do it for you internally.
FastAPI 将在内部为您完成。