Update all

This commit is contained in:
Yurii Motov
2026-02-13 13:40:51 +01:00
parent fdbbf74908
commit 2ecbf4b31f
81 changed files with 385 additions and 527 deletions

View File

@@ -26,7 +26,7 @@
例如,要声明另一个状态码为 `404` 且具有 Pydantic 模型 `Message` 的响应,你可以这样写:
{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *}
/// note | 注意
@@ -203,7 +203,7 @@
以及一个状态码为 `200` 的响应,它使用你的 `response_model`,但包含自定义的 `example`
{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *}
所有这些都会被合并并包含到你的 OpenAPI 中,并显示在 API 文档里:

View File

@@ -16,7 +16,7 @@
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
/// warning
/// warning | 警告
当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。
@@ -26,7 +26,7 @@
///
/// note | 技术细节
/// note | 注意
你也可以使用 `from starlette.responses import JSONResponse`。 

View File

@@ -18,7 +18,7 @@
为此,声明一个 `__call__` 方法:
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *}
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *}
在这种情况下,**FastAPI** 会使用这个 `__call__` 来检查附加参数和子依赖,并且稍后会调用它,把返回值传递给你的*路径操作函数*中的参数。
@@ -26,7 +26,7 @@
现在,我们可以用 `__init__` 声明实例的参数,用来“参数化”这个依赖项:
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *}
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *}
在本例中,**FastAPI** 不会接触或关心 `__init__`,我们会在自己的代码中直接使用它。
@@ -34,7 +34,7 @@
我们可以这样创建该类的实例:
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *}
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *}
这样就把依赖项“参数化”了,现在它内部带有属性 `checker.fixed_content` 的值 `"bar"`
@@ -50,7 +50,7 @@ checker(q="somequery")
...并将其返回值作为依赖项的值,传给我们的*路径操作函数*中的参数 `fixed_content_included`
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *}
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *}
/// tip | 提示

View File

@@ -32,11 +32,11 @@
文件 `main.py` 将包含:
{* ../../docs_src/async_tests/app_a_py39/main.py *}
{* ../../docs_src/async_tests/app_a_py310/main.py *}
文件 `test_main.py` 将包含针对 `main.py` 的测试,现在它可能看起来如下:
{* ../../docs_src/async_tests/app_a_py39/test_main.py *}
{* ../../docs_src/async_tests/app_a_py310/test_main.py *}
## 运行测试 { #run-it }
@@ -56,7 +56,7 @@ $ pytest
这个标记 `@pytest.mark.anyio` 会告诉 pytest 该测试函数应该被异步调用:
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *}
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *}
/// tip | 提示
@@ -66,7 +66,7 @@ $ pytest
我们现在可以使用应用程序创建一个 `AsyncClient` ,并使用 `await` 向其发送异步请求。
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *}
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *}
这相当于:
@@ -74,7 +74,7 @@ $ pytest
response = client.get('/')
```
我们曾经通过它向 `TestClient` 发出请求。
...我们曾经通过它向 `TestClient` 发出请求。
/// tip | 提示

View File

@@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*"
例如,假设你定义了一个*路径操作* `/items/`
{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *}
{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *}
如果客户端尝试访问 `/items`,默认会被重定向到 `/items/`
@@ -115,7 +115,7 @@ sequenceDiagram
即使你的所有代码都假设只有 `/app`
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *}
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *}
代理会在将请求传递给应用服务器(可能是通过 FastAPI CLI 运行的 Uvicorn之前实时**“移除”**这个**路径前缀**,让你的应用认为它是在 `/app` 被服务,这样你就不需要更新所有代码去包含 `/api/v1` 前缀。
@@ -193,7 +193,7 @@ ASGI 规范为这种用例定义了 `root_path`。
这里我们把它包含在响应消息中仅用于演示。
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *}
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *}
然后,如果你这样启动 Uvicorn
@@ -220,7 +220,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
或者,如果你无法提供类似 `--root-path` 的命令行选项,你可以在创建 FastAPI 应用时设置参数 `root_path`
{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *}
{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *}
把 `root_path` 传给 `FastAPI` 等同于把命令行选项 `--root-path` 传给 Uvicorn 或 Hypercorn。
@@ -400,7 +400,7 @@ $ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
例如:
{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *}
{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *}
会生成如下的 OpenAPI 模式:
@@ -455,7 +455,7 @@ OpenAPI 规范中的 `servers` 属性是可选的。
如果你不希望 **FastAPI** 包含一个使用 `root_path` 的自动服务器,可以使用参数 `root_path_in_servers=False`
{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *}
{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *}
这样它就不会被包含到 OpenAPI 模式中。

View File

@@ -30,7 +30,7 @@
但如果你确定你返回的内容是「可以用 JSON 序列化」的,你可以将它直接传给响应类,从而避免在传给响应类之前先通过 `jsonable_encoder` 带来的额外开销。
{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *}
{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *}
/// info | 信息
@@ -55,7 +55,7 @@
* 导入 `HTMLResponse`
*`HTMLResponse` 作为你的 *路径操作*`response_class` 参数传入。
{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *}
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
/// info | 信息
@@ -73,7 +73,7 @@
和上面一样的例子,返回一个 `HTMLResponse` 看起来可能是这样:
{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *}
{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *}
/// warning | 警告
@@ -97,7 +97,7 @@
比如像这样:
{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *}
{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *}
在这个例子中,函数 `generate_html_response()` 已经生成并返回 `Response` 对象而不是在 `str` 中返回 HTML。
@@ -136,7 +136,7 @@
FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它还将包含一个基于 `media_type` 的 Content-Type 头,并为文本类型附加一个字符集。
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
### `HTMLResponse` { #htmlresponse }
@@ -146,7 +146,7 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
接受文本或字节并返回纯文本响应。
{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *}
{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *}
### `JSONResponse` { #jsonresponse }
@@ -180,7 +180,7 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
///
{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *}
{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *}
/// tip | 提示
@@ -194,13 +194,13 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
你可以直接返回一个 `RedirectResponse`
{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *}
{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *}
---
或者你可以把它用于 `response_class` 参数:
{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *}
{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *}
如果你这么做,那么你可以在 *路径操作* 函数中直接返回 URL。
@@ -210,13 +210,13 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
你也可以将 `status_code` 参数和 `response_class` 参数结合使用:
{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *}
{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *}
### `StreamingResponse` { #streamingresponse }
采用异步生成器或普通生成器/迭代器,然后流式传输响应主体。
{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *}
{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *}
#### 对类似文件的对象使用 `StreamingResponse` { #using-streamingresponse-with-file-like-objects }
@@ -226,7 +226,7 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
这也包括许多与云存储、视频处理等交互的库。
{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *}
{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *}
1. 这是生成器函数。之所以是「生成器函数」,是因为它内部包含 `yield` 语句。
2. 通过使用 `with` 代码块,我们可以确保在生成器函数完成后关闭类文件对象。因此,在它完成发送响应之后会被关闭。
@@ -255,11 +255,11 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
文件响应将包含适当的 `Content-Length``Last-Modified``ETag` 响应头。
{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *}
{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *}
你也可以使用 `response_class` 参数:
{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *}
{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *}
在这种情况下,你可以在 *路径操作* 函数中直接返回文件路径。
@@ -273,7 +273,7 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
你可以创建一个 `CustomORJSONResponse`。你需要做的主要事情是实现一个返回 `bytes``Response.render(content)` 方法:
{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *}
{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *}
现在,不再是返回:
@@ -281,7 +281,7 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
{"message": "Hello World"}
```
这个响应将返回:
...这个响应将返回:
```json
{
@@ -299,7 +299,7 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
在下面的示例中,**FastAPI** 会在所有 *路径操作* 中默认使用 `ORJSONResponse`,而不是 `JSONResponse`
{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *}
{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *}
/// tip | 提示

View File

@@ -59,7 +59,7 @@ FastAPI 基于 **Pydantic** 构建,我已经向你展示过如何使用 Pydant
在本例中,它是一个 `Item` 数据类列表。
6. 这里我们返回一个字典,里面的 `items` 是一个数据类列表。
FastAPI 仍然能够将数据<abbr title="把数据转换为可以传输的格式">序列化</abbr>为 JSON。
FastAPI 仍然能够将数据<dfn title="把数据转换为可以传输的格式">序列化</dfn>为 JSON。
7. 这里的 `response_model` 使用了 “`Author` 数据类列表” 的类型注解。
同样,你可以将 `dataclasses` 与标准类型注解组合使用。

View File

@@ -30,7 +30,7 @@
我们使用 `yield` 创建了一个异步函数 `lifespan()` 像这样:
{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *}
{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *}
在这里,我们在 `yield` 之前将(虚拟的)模型函数放入机器学习模型的字典中,以此模拟加载模型的耗时**启动**操作。这段代码将在应用程序**开始处理请求之前**执行,即**启动**期间。
@@ -48,7 +48,7 @@
首先要注意的是,我们定义了一个带有 `yield` 的异步函数。这与带有 `yield` 的依赖项非常相似。
{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *}
{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *}
这个函数在 `yield` 之前的部分,会在应用启动前执行。
@@ -60,7 +60,7 @@
它将函数转化为所谓的“**异步上下文管理器**”。
{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *}
{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *}
在 Python 中,**上下文管理器**是一个你可以在 `with` 语句中使用的东西,例如,`open()` 可以作为上下文管理器使用。
@@ -82,7 +82,7 @@ async with lifespan(app):
`FastAPI``lifespan` 参数接受一个**异步上下文管理器**,所以我们可以把我们新定义的异步上下文管理器 `lifespan` 传给它。
{* ../../docs_src/events/tutorial003_py39.py hl[22] *}
{* ../../docs_src/events/tutorial003_py310.py hl[22] *}
## 替代事件(弃用) { #alternative-events-deprecated }
@@ -104,7 +104,7 @@ async with lifespan(app):
使用事件 `"startup"` 声明一个在应用启动前运行的函数:
{* ../../docs_src/events/tutorial001_py39.py hl[8] *}
{* ../../docs_src/events/tutorial001_py310.py hl[8] *}
本例中,`startup` 事件处理器函数为项目“数据库”(只是一个 `dict`)提供了一些初始值。
@@ -116,7 +116,7 @@ async with lifespan(app):
使用事件 `"shutdown"` 声明一个在应用关闭时运行的函数:
{* ../../docs_src/events/tutorial002_py39.py hl[6] *}
{* ../../docs_src/events/tutorial002_py310.py hl[6] *}
此处,`shutdown` 事件处理器函数会向文件 `log.txt` 写入一行文本 `"Application shutdown"`

View File

@@ -40,7 +40,7 @@ FastAPI 会自动生成 **OpenAPI 3.1** 规范,因此你使用的任何工具
先从一个简单的 FastAPI 应用开始:
{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *}
请注意,这些*路径操作*使用 `Item``ResponseMessage` 模型来定义它们的请求载荷和响应载荷。
@@ -98,7 +98,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
例如,你可以有一个 **items** 相关的部分和另一个 **users** 相关的部分,它们可以用标签来分隔:
{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *}
### 生成带标签的 TypeScript 客户端 { #generate-a-typescript-client-with-tags }
@@ -121,7 +121,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
```
……这是因为客户端生成器会把每个*路径操作*的 OpenAPI 内部**操作 IDoperation ID**用作方法名的一部分。
...这是因为客户端生成器会把每个*路径操作*的 OpenAPI 内部**操作 IDoperation ID**用作方法名的一部分。
OpenAPI 要求每个操作 ID 在所有*路径操作*中都是唯一的,因此 FastAPI 会使用**函数名**、**路径**和**HTTP 方法/操作**来生成操作 ID以确保其唯一性。
@@ -145,7 +145,7 @@ FastAPI 为每个*路径操作*使用一个**唯一 ID**,它既用于**操作
然后你可以把这个自定义函数通过 `generate_unique_id_function` 参数传给 **FastAPI**
{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *}
### 使用自定义操作 ID 生成 TypeScript 客户端 { #generate-a-typescript-client-with-custom-operation-ids }
@@ -167,7 +167,7 @@ FastAPI 为每个*路径操作*使用一个**唯一 ID**,它既用于**操作
我们可以把 OpenAPI JSON 下载到 `openapi.json` 文件中,然后用如下脚本**移除这个标签前缀**
{* ../../docs_src/generate_clients/tutorial004_py39.py *}
{* ../../docs_src/generate_clients/tutorial004_py310.py *}
//// tab | Node.js

View File

@@ -43,7 +43,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
**FastAPI** 为常见用例提供了一些中间件,下面介绍怎么使用这些中间件。
/// note | 注意
/// note | 技术细节
以下几个示例中也可以使用 `from starlette.middleware.something import SomethingMiddleware`
@@ -57,13 +57,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
任何传向 `http``ws` 的请求都会被重定向至安全方案。
{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *}
{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *}
## `TrustedHostMiddleware` { #trustedhostmiddleware }
强制所有传入请求都必须正确设置 `Host` 请求头,以防 HTTP 主机头攻击。
{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *}
{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *}
支持以下参数:
@@ -78,7 +78,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
中间件会处理标准响应与流响应。
{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *}
{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *}
支持以下参数:

View File

@@ -179,7 +179,7 @@ JSON 请求体包含如下内容:
### 查看文档 { #check-the-docs }
现在,使用 Uvicorn 启动应用打开 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
现在,启动应用打开 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
就能看到文档的*路径操作*已经包含了**回调**的内容以及*外部 API*

View File

@@ -32,7 +32,7 @@
当您创建一个 **FastAPI** 应用程序时,有一个 `webhooks` 属性可以用来定义网络钩子,方式与您定义*路径操作*的时候相同,例如使用 `@app.webhooks.post()`
{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *}
{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *}
您定义的网络钩子将被包含在 `OpenAPI` 的架构中,并出现在自动生成的**文档 UI** 中。

View File

@@ -12,7 +12,7 @@
务必确保每个操作的 `operation_id` 都是唯一的。
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *}
### 使用 *路径操作函数* 的函数名作为 operationId { #using-the-path-operation-function-name-as-the-operationid }
@@ -20,7 +20,7 @@
你应该在添加了所有 *路径操作* 之后执行此操作。
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *}
/// tip
@@ -40,7 +40,7 @@
使用参数 `include_in_schema` 并将其设置为 `False`,来从生成的 OpenAPI 方案中排除一个 *路径操作*(这样一来,就从自动化文档系统中排除掉了):
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *}
## 来自 docstring 的高级描述 { #advanced-description-from-docstring }
@@ -92,7 +92,7 @@
例如,这个 `openapi_extra` 可用于声明 [OpenAPI 扩展](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions)
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *}
当你打开自动 API 文档时,你的扩展会显示在该 *路径操作* 的底部。
@@ -139,9 +139,9 @@
你可以用 `openapi_extra` 来做到:
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *}
在这个示例中,我们没有声明任何 Pydantic 模型。事实上,请求体甚至没有被 <abbr title="从某种纯文本格式(如字节)转换为 Python 对象">解析</abbr> 为 JSON而是直接以 `bytes` 读取,并由函数 `magic_data_reader()` 以某种方式负责解析。
在这个示例中,我们没有声明任何 Pydantic 模型。事实上,请求体甚至没有被 <dfn title="从某种纯文本格式(如字节)转换为 Python 对象">解析</dfn> 为 JSON而是直接以 `bytes` 读取,并由函数 `magic_data_reader()` 以某种方式负责解析。
尽管如此,我们仍然可以声明请求体的预期方案。
@@ -153,7 +153,7 @@
例如,在这个应用中我们不使用 FastAPI 集成的从 Pydantic 模型提取 JSON Schema 的功能,也不使用对 JSON 的自动校验。实际上,我们将请求的内容类型声明为 YAML而不是 JSON
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *}
尽管我们没有使用默认的集成功能,我们仍然使用 Pydantic 模型手动生成我们想以 YAML 接收的数据的 JSON Schema。
@@ -161,7 +161,7 @@
接着在我们的代码中,我们直接解析该 YAML 内容,然后再次使用同一个 Pydantic 模型来验证该 YAML 内容:
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *}
/// tip

View File

@@ -20,9 +20,11 @@
然后你可以在这个*临时*响应对象中设置`status_code`
{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *}
{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *}
然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。
如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
**FastAPI**将使用这个*临时*响应来提取状态码也包括cookies和头部并将它们放入包含你返回的值的最终响应中该响应由任何`response_model`过滤。

View File

@@ -4,7 +4,7 @@
你可以在 *路径操作函数* 中定义一个类型为 `Response` 的参数这样你就可以在这个临时响应对象中设置cookie了。
{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *}
{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *}
而且你还可以根据你的需要响应不同的对象,比如常用的 `dict`数据库model等。
@@ -22,9 +22,9 @@
然后设置Cookies并返回
{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *}
{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *}
/// tip
/// tip | 提示
需要注意如果你直接反馈一个response对象而不是使用`Response`入参FastAPI则会直接反馈你封装的response对象。

View File

@@ -36,7 +36,7 @@
{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *}
/// note | 注意
/// note | 技术细节
你也可以使用 `from starlette.responses import JSONResponse`
@@ -54,7 +54,7 @@
你可以把你的 XML 内容放到一个字符串中,放到一个 `Response` 中,然后返回:
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
## 说明 { #notes }

View File

@@ -6,13 +6,13 @@
然后你可以在这个*临时*响应对象中设置头部。
{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *}
{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *}
然后你可以像平常一样返回任何你需要的对象(例如一个 `dict` 或者一个数据库模型)。
如果你声明了一个 `response_model`,它仍然会被用来过滤和转换你返回的对象。
**FastAPI** 将使用这个临时响应来提取头部(也包括 cookies 和状态码),并将它们放入包含你返回的值的最终响应中,该响应由任何 `response_model` 过滤。
**FastAPI** 将使用这个*临时*响应来提取头部(也包括 cookies 和状态码),并将它们放入包含你返回的值的最终响应中,该响应由任何 `response_model` 过滤。
你也可以在依赖项中声明 `Response` 参数,并在其中设置头部(和 cookies
@@ -22,7 +22,7 @@
按照[直接返回响应](response-directly.md){.internal-link target=_blank}中所述创建响应,并将头部作为附加参数传递:
{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *}
{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *}
/// note | 技术细节

View File

@@ -20,7 +20,7 @@ HTTP 基础授权让浏览器显示内置的用户名与密码提示。
* 返回类型为 `HTTPBasicCredentials` 的对象:
* 包含发送的 `username``password`
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *}
第一次打开 URL或在 API 文档中点击 **Execute** 按钮)时,浏览器要求输入用户名与密码:
@@ -40,7 +40,7 @@ HTTP 基础授权让浏览器显示内置的用户名与密码提示。
然后我们可以使用 `secrets.compare_digest()` 来确保 `credentials.username``"stanleyjobson"`,且 `credentials.password``"swordfish"`
{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *}
这类似于:
@@ -104,4 +104,4 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
检测到凭证不正确后,返回 `HTTPException` 及状态码 401与无凭证时返回的内容一样并添加响应头 `WWW-Authenticate`,让浏览器再次显示登录提示:
{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *}

View File

@@ -54,7 +54,7 @@ $ pip install "fastapi[all]"
你可以使用与 Pydantic 模型相同的验证功能和工具,例如不同的数据类型,以及使用 `Field()` 进行附加验证。
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *}
/// tip | 提示
@@ -70,7 +70,7 @@ $ pip install "fastapi[all]"
然后你可以在应用中使用新的 `settings` 对象:
{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *}
{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *}
### 运行服务器 { #run-the-server }
@@ -100,19 +100,19 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
## 在另一个模块中放置设置 { #settings-in-another-module }
你可以把这些设置放在另一个模块文件中,就像你在[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。
你可以把这些设置放在另一个模块文件中,就像你在[更大的应用 - 多个文件](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。
例如,可以有一个 `config.py` 文件:
{* ../../docs_src/settings/app01_py39/config.py *}
{* ../../docs_src/settings/app01_py310/config.py *}
然后在 `main.py` 文件中使用它:
{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *}
{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *}
/// tip | 提示
你还需要一个 `__init__.py` 文件,就像你在[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。
你还需要一个 `__init__.py` 文件,就像你在[更大的应用 - 多个文件](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。
///
@@ -126,7 +126,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
延续上一个示例,你的 `config.py` 文件可能如下所示:
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *}
{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *}
注意,现在我们不再创建默认实例 `settings = Settings()`
@@ -134,7 +134,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
现在我们创建一个依赖项,返回一个新的 `config.Settings()`
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *}
/// tip | 提示
@@ -144,15 +144,15 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
///
然后我们可以在路径操作函数中将其作为依赖项引入,并在需要的任何地方使用它。
然后我们可以在路径操作函数中将其作为依赖项引入,并在需要的任何地方使用它。
{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *}
### 设置与测试 { #settings-and-testing }
接着,在测试期间,通过为 `get_settings` 创建依赖项覆盖,就可以很容易地提供一个不同的设置对象:
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *}
{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *}
在依赖项覆盖中,我们在创建新的 `Settings` 对象时为 `admin_email` 设置了一个新值,然后返回该新对象。
@@ -193,7 +193,7 @@ APP_NAME="ChimichangApp"
然后更新 `config.py`
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *}
/// tip | 提示
@@ -226,7 +226,7 @@ def get_settings():
但由于我们在顶部使用了 `@lru_cache` 装饰器,`Settings` 对象只会在第一次调用时创建一次。 ✔️
{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *}
接着,对于后续请求中依赖项里对 `get_settings()` 的任何调用,它不会再次执行 `get_settings()` 的内部代码并创建新的 `Settings` 对象,而是会一遍又一遍地返回第一次调用时返回的那个相同对象。

View File

@@ -10,7 +10,7 @@
首先,创建主(顶层)**FastAPI** 应用及其*路径操作*
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *}
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *}
### 子应用 { #sub-application }
@@ -18,7 +18,7 @@
子应用只是另一个标准 FastAPI 应用,但这个应用是被**挂载**的应用:
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *}
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *}
### 挂载子应用 { #mount-the-sub-application }
@@ -26,7 +26,7 @@
本例的子应用挂载在 `/subapi` 路径下:
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *}
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *}
### 查看自动 API 文档 { #check-the-automatic-api-docs }

View File

@@ -27,7 +27,7 @@ $ pip install jinja2
* 在返回模板的*路径操作*中声明 `Request` 参数
* 使用 `templates` 渲染并返回 `TemplateResponse`传递模板的名称、request 对象以及一个包含多个键值对(用于 Jinja2 模板)的 "context" 字典。
{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *}
{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *}
/// note

View File

@@ -46,7 +46,6 @@ FastAPI 可以覆盖这些位置的依赖项。
app.dependency_overrides = {}
```
/// tip | 提示
如果只在某些测试时覆盖依赖项,您可以在测试开始时(在测试函数内)设置覆盖依赖项,并在结束时(在测试函数结尾)重置覆盖依赖项。

View File

@@ -2,10 +2,10 @@
当你需要在测试中运行 `lifespan` 时,可以将 `TestClient``with` 语句一起使用:
{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *}
{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *}
你可以在[官方 Starlette 文档站点的“在测试中运行 lifespan”](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)阅读更多细节。
对于已弃用的 `startup``shutdown` 事件,可以按如下方式使用 `TestClient`
{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *}
{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *}

View File

@@ -4,7 +4,7 @@
为此,在 `with` 语句中使用 `TestClient` 连接到 WebSocket
{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *}
{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *}
/// note | 注意

View File

@@ -29,7 +29,7 @@
此时,需要直接访问请求。
{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *}
{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *}
把*路径操作函数*的参数类型声明为 `Request`**FastAPI** 就能把 `Request` 传递到参数里。

View File

@@ -38,13 +38,13 @@ $ pip install websockets
但这是一种专注于 WebSockets 的服务器端并提供一个工作示例的最简单方式:
{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *}
{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *}
## 创建 `websocket` { #create-a-websocket }
在您的 **FastAPI** 应用程序中,创建一个 `websocket`
{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *}
{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *}
/// note | 技术细节
@@ -58,7 +58,7 @@ $ pip install websockets
在您的 WebSocket 路由中,您可以使用 `await` 等待消息并发送消息。
{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *}
{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *}
您可以接收和发送二进制、文本和 JSON 数据。
@@ -154,7 +154,7 @@ $ fastapi dev main.py
当 WebSocket 连接关闭时,`await websocket.receive_text()` 将引发 `WebSocketDisconnect` 异常,您可以捕获并处理该异常,就像本示例中的示例一样。
{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *}
{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *}
尝试以下操作:

View File

@@ -18,7 +18,7 @@
之后将其挂载到某一个路径下。
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *}
/// note | 注意

View File

@@ -298,7 +298,7 @@ CPU 密集型操作的常见示例是需要复杂的数学处理。
这一点,再加上 Python 是**数据科学**、机器学习(尤其是深度学习)的主要语言这一简单事实,使得 **FastAPI** 与数据科学/机器学习 Web API 和应用程序(以及其他许多应用程序)非常匹配。
了解如何在生产环境中实现这种并行性,可查看此文 [Deployment](deployment/index.md){.internal-link target=_blank}。
了解如何在生产环境中实现这种并行性,可查看此文 [部署](deployment/index.md){.internal-link target=_blank}。
## `async` 和 `await` { #async-and-await }
@@ -369,7 +369,7 @@ Starlette (和 **FastAPI** 是基于 <a href="https://anyio.readthedocs.io/
即使你没有使用 **FastAPI**,你也可以使用 <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如, 结构化并发)。
(指原作者 —— 译者注)基于 AnyIO 新建了一个库,作为一个轻量级的封装层,用来优化类型注解,同时提供了更好的**自动补全**、**内联错误提示**等功能。这个库还附带了一个友好的入门指南和教程,能帮助你**理解**并编写**自己的异步代码**<a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>。如果你有**结合使用异步代码和常规**(阻塞/同步)代码的需求,这个库会特别有用。
我基于 AnyIO 新建了一个库,作为一个轻量级的封装层,用来优化类型注解,同时提供了更好的**自动补全**、**内联错误提示**等功能。这个库还附带了一个友好的入门指南和教程,能帮助你**理解**并编写**自己的异步代码**<a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>。如果你有**结合使用异步代码和常规**(阻塞/同步)代码的需求,这个库会特别有用。
### 其他形式的异步代码 { #other-forms-of-asynchronous-code }

View File

@@ -23,7 +23,7 @@
* 你不会直接在 Uvicorn 中编写应用程序。这意味着你的代码至少必须包含 Starlette**FastAPI**)提供的代码。如果你这样做了(即直接在 Uvicorn 中编写应用程序),最终的应用程序会和使用了框架并且最小化了应用代码和 bug 的情况具有相同的性能损耗。
* 如果你要对比 Uvicorn请将其与 DaphneHypercornuWSGI 等应用服务器进行比较。
* **Starlette**:
* Uvicorn 后使用 Starlette性能会略有下降。实际上Starlette 使用 Uvicorn 运行。因此,由于必须执行更多的代码,它只会比 Uvicorn 更慢。
* 性能仅次于 Uvicorn。实际上Starlette 使用 Uvicorn 运行。因此,由于必须执行更多的代码,它只会比 Uvicorn 更慢。
* 但它为你提供了构建简单的网络程序的工具,并具有基于路径的路由等功能。
* 如果想对比与 Starlette 对标的开发框架,请将其与 SanicFlaskDjango 等网络框架(或微框架)进行比较。
* **FastAPI**:

View File

@@ -190,7 +190,7 @@
### 工作进程和端口 { #worker-processes-and-ports }
还记得文档 [About HTTPS](https.md){.internal-link target=_blank} 中只有一个进程可以侦听服务器中的端口和 IP 地址的一种组合吗?
还记得文档 [关于 HTTPS](https.md){.internal-link target=_blank} 中只有一个进程可以侦听服务器中的端口和 IP 地址的一种组合吗?
现在仍然是对的。

View File

@@ -14,7 +14,7 @@
<summary>Dockerfile 预览 👀</summary>
```Dockerfile
FROM python:3.9
FROM python:3.14
WORKDIR /code
@@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None):
```{ .dockerfile .annotate }
# (1)!
FROM python:3.9
FROM python:3.14
# (2)!
WORKDIR /code
@@ -390,7 +390,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage
然后你只需要在 `Dockerfile` 中修改相应路径来复制该文件:
```{ .dockerfile .annotate hl_lines="10 13" }
FROM python:3.9
FROM python:3.14
WORKDIR /code
@@ -454,7 +454,7 @@ Traefik 与 Docker、Kubernetes 等都有集成,因此为容器设置和配置
## 复制 - 进程数 { #replication-number-of-processes }
如果你有一个由 **Kubernetes**、Docker Swarm Mode、Nomad 或其他类似的复杂系统管理的、在多台机器上运行的分布式容器<abbr title="被配置为以某种方式连接并协同工作的多台机器">集群</abbr>,那么你很可能会希望在**集群层面**来**处理复制**,而不是在每个容器中使用**进程管理**(比如让 Uvicorn 运行多个 workers
如果你有一个由 **Kubernetes**、Docker Swarm Mode、Nomad 或其他类似的复杂系统管理的、在多台机器上运行的分布式容器<dfn title="被配置为以某种方式连接并协同工作的多台机器">集群</dfn>,那么你很可能会希望在**集群层面**来**处理复制**,而不是在每个容器中使用**进程管理**(比如让 Uvicorn 运行多个 workers
像 Kubernetes 这样的分布式容器管理系统通常都有某种内置方式来处理**容器复制**,同时对传入请求进行**负载均衡**。这一切都在**集群层面**完成。
@@ -499,7 +499,7 @@ Traefik 与 Docker、Kubernetes 等都有集成,因此为容器设置和配置
在这些情况下,你可以使用 `--workers` 命令行选项来设置要运行的 worker 数量:
```{ .dockerfile .annotate }
FROM python:3.9
FROM python:3.14
WORKDIR /code

View File

@@ -65,13 +65,13 @@
第一步我们要先**获取**一些**域名(Domain Name)**。 然后可以在 DNS 服务器(可能是你的同一家云服务商提供的)中配置它。
你可能拥有一个云服务器(虚拟机)或类似的东西,并且它会有一个<abbr title="不会改变">固定</abbr> **公共IP地址**
你可能拥有一个云服务器(虚拟机)或类似的东西,并且它会有一个<dfn title="不会随时间改变。非动态的。">固定</dfn> **公共IP地址**
在 DNS 服务器中你可以配置一条记录“A 记录”)以将 **你的域名** 指向你服务器的公共 **IP 地址**
这个操作一般只需要在最开始执行一次。
/// tip
/// tip | 提示
域名这部分发生在 HTTPS 之前,由于这一切都依赖于域名和 IP 地址,所以先在这里提一下。
@@ -121,7 +121,7 @@ TLS 终止代理可以访问一个或多个 **TLS 证书**HTTPS 证书)。
这就是 **HTTPS**,它只是 **安全 TLS 连接** 内的普通 **HTTP**而不是纯粹的未加密的TCP 连接。
/// tip
/// tip | 提示
请注意,通信加密发生在 **TCP 层**,而不是 HTTP 层。
@@ -217,7 +217,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**
这在需要正确处理重定向等场景时很有用。
/// tip
/// tip | 提示
你可以在文档中了解更多:[在代理之后 - 启用代理转发请求头](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank}

View File

@@ -90,7 +90,7 @@ $ pip install "uvicorn[standard]"
类似的流程也适用于任何其他 ASGI 服务器程序。
/// tip
/// tip | 提示
通过添加 `standard` 选项Uvicorn 将安装并使用一些推荐的额外依赖项。
@@ -114,7 +114,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 80
</div>
/// note
/// note | 注意
命令 `uvicorn main:app` 的含义如下:
@@ -131,7 +131,7 @@ from main import app
每种 ASGI 服务器程序通常都会有类似的命令,您可以在它们的官方文档中找到更多信息。
/// warning
/// warning | 警告
Uvicorn 和其他服务器支持 `--reload` 选项,该选项在开发过程中非常有用。

View File

@@ -60,16 +60,16 @@ $ <font color="#4E9A06">fastapi</font> run --workers 4 <u style="text-decoration
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000</u></font> <b>(</b>Press CTRL+C to
quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started parent process <b>[</b><font color="#34E2E2"><b>27365</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27368</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27369</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27370</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27367</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Started parent process <b>[</b><font color="#34E2E2"><b>27365</b></font><b>]</b>
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27368</b></font><b>]</b>
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27369</b></font><b>]</b>
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27370</b></font><b>]</b>
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27367</b></font><b>]</b>
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.

View File

@@ -6,7 +6,7 @@
### 基于开放标准 { #based-on-open-standards }
* 用于创建 API 的 <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a>,包含对<abbr title="也被叫做: endpoints, routes">路径</abbr> <abbr title="也叫做 HTTP 方法,如 POST、GET、PUT、DELETE">操作</abbr>、参数、请求体、安全等的声明。
* 用于创建 API 的 <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a>,包含对<dfn title="也称为:端点、路由">路径</dfn> <dfn title="也称为 HTTP 方法,如 POST、GET、PUT、DELETE">操作</dfn>、参数、请求体、安全等的声明。
* 使用 <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> 自动生成数据模型文档(因为 OpenAPI 本身就是基于 JSON Schema 的)。
* 经过了缜密的研究后围绕这些标准而设计。并非狗尾续貂。
* 这也允许了在很多语言中自动**生成客户端代码**。
@@ -137,7 +137,7 @@ OpenAPI 中定义的安全模式,包括:
### 依赖注入 { #dependency-injection }
FastAPI 有一个使用非常简单,但是非常强大的<abbr title='也叫做 "components", "resources", "services", "providers"'><strong>依赖注入</strong></abbr>系统。
FastAPI 有一个使用非常简单,但是非常强大的<dfn title='也称为 "components""resources""services""providers"'><strong>依赖注入</strong></dfn>系统。
* 甚至依赖也可以有依赖,创建一个层级或者**“图”依赖**。
* 所有**自动化处理**都由框架完成。
@@ -154,8 +154,8 @@ FastAPI 有一个使用非常简单,但是非常强大的<abbr title='也叫
### 测试 { #tested }
* 100% <abbr title="自动测试的代码量">测试覆盖</abbr>。
* 代码库100% <abbr title="Python类型注解有了这个你的编辑器和外部工具可以给你更好的支持">类型注释</abbr>。
* 100% <dfn title="自动测试的代码量">测试覆盖</dfn>。
* 代码库100% <dfn title="Python 类型注解,有了这个你的编辑器和外部工具可以给你更好的支持">类型注释</dfn>。
* 用于生产应用。
## Starlette 特性 { #starlette-features }
@@ -186,10 +186,10 @@ FastAPI 有一个使用非常简单,但是非常强大的<abbr title='也叫
通过 **FastAPI** 你可以获得所有 **Pydantic**FastAPI 基于 Pydantic 做了所有的数据处理):
* **更简单**
* **不烧脑**
* 没有新的模式定义 micro-language 需要学习。
* 如果你知道 Python types你就知道如何使用 Pydantic。
* 和你 **<abbr title="集成开发环境,和代码编辑器类似">IDE</abbr>/<abbr title="一个检查代码错误的程序">linter</abbr>/brain** 适配:
* 和你 **<abbr title="Integrated Development Environment - 集成开发环境: 类似于代码编辑器">IDE</abbr>/<dfn title="一个检查代码错误的程序">linter</dfn>/brain** 适配:
* 因为 pydantic 数据结构仅仅是你定义的类的实例自动补全lintingmypy 以及你的直觉应该可以和你验证的数据一起正常工作。
* 验证**复杂结构**:
* 使用分层的 Pydantic 模型Python `typing``List``Dict` 等等。

View File

@@ -59,7 +59,7 @@
## 发推谈谈 **FastAPI** { #tweet-about-fastapi }
<a href="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">Tweet about **FastAPI**</a>,告诉我和大家你为什么喜欢它。🎉
<a href="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">发推谈谈 **FastAPI**</a>,告诉我和大家你为什么喜欢它。🎉
我很高兴听到 **FastAPI** 的使用情况、你喜欢它的哪些点、你在哪个项目/公司使用它,等等。

View File

@@ -18,7 +18,7 @@ FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因
但是你可以通过设置 `syntaxHighlight``False` 来禁用 Swagger UI 中的语法高亮:
{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *}
{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *}
...在此之后Swagger UI 将不会高亮代码:
@@ -28,7 +28,7 @@ FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因
同样地,你也可以通过设置键 `"syntaxHighlight.theme"` 来设置语法高亮主题(注意中间有一个点):
{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *}
{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *}
这个配置会改变语法高亮主题:
@@ -46,7 +46,7 @@ FastAPI 包含了一些默认配置参数,适用于大多数用例。
比如,如果要禁用 `deepLinking`,你可以像这样传递设置到 `swagger_ui_parameters` 中:
{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *}
{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *}
## 其他 Swagger UI 参数 { #other-swagger-ui-parameters }

View File

@@ -36,4 +36,4 @@
## OpenAPI 文档 URL { #openapi-docs-urls }
要更改用于自动生成文档的 URL请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}。
要更改自动生成文档用户界面所使用的 URL请阅读 [教程 - 元数据和文档 URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}。

View File

@@ -40,7 +40,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框
* **快速**:极高性能,可与 **NodeJS****Go** 并肩(归功于 Starlette 和 Pydantic。[最快的 Python 框架之一](#performance)。
* **高效编码**:功能开发速度提升约 200% 300%。*
* **更少 bug**:人为(开发者)错误减少约 40%。*
* **直观**:极佳的编辑器支持。处处皆可<abbr title="也被称为自动完成、自动补全、IntelliSense">自动补全</abbr>。更少的调试时间。
* **直观**:极佳的编辑器支持。处处皆可<dfn title="也被称为自动完成、自动补全、IntelliSense">自动补全</dfn>。更少的调试时间。
* **易用**:为易用和易学而设计。更少的文档阅读时间。
* **简短**:最小化代码重复。一次参数声明即可获得多种功能。更少的 bug。
* **健壮**:生产可用级代码。并带有自动生成的交互式文档。
@@ -368,7 +368,7 @@ item: Item
* 数据校验:
* 当数据无效时自动生成清晰的错误信息。
* 即便是多层嵌套的 JSON 对象也会进行校验。
* 输入数据的<abbr title="也被称为:序列化、解析、编组">转换</abbr>:从网络读取到 Python 数据和类型。读取来源:
* <dfn title="也被称为:序列化、解析、编组">转换</dfn>输入数据:从网络读取到 Python 数据和类型。读取来源:
* JSON。
* 路径参数。
* 查询参数。
@@ -376,7 +376,7 @@ item: Item
* Headers。
* Forms。
* Files。
* 输出数据的<abbr title="也被称为:序列化、解析、编组">转换</abbr>:从 Python 数据和类型转换为网络数据JSON
* <dfn title="也被称为:序列化、解析、编组">转换</dfn>输出数据:从 Python 数据和类型转换为网络数据JSON
* 转换 Python 类型(`str`、`int`、`float`、`bool`、`list` 等)。
* `datetime` 对象。
* `UUID` 对象。
@@ -439,7 +439,7 @@ item: Item
* 来自不同位置的**参数**声明:**headers**、**cookies**、**form 字段**和**文件**。
* 如何设置**校验约束**,如 `maximum_length` 或 `regex`。
* 功能强大且易用的 **<abbr title="也被称为 components、resources、providers、services、injectables">依赖注入</abbr>** 系统。
* 功能强大且易用的 **<dfn title="也被称为:组件、资源、提供者、服务、可注入项">依赖注入</dfn>** 系统。
* 安全与认证,包括对 **OAuth2**、**JWT tokens** 和 **HTTP Basic** 认证的支持。
* 更高级(但同样简单)的 **多层嵌套 JSON 模型** 声明技巧(得益于 Pydantic
* 通过 <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> 等库进行 **GraphQL** 集成。
@@ -524,7 +524,7 @@ Starlette 使用:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - 使用 `TestClient` 时需要。
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - 使用默认模板配置时需要。
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - 使用 `request.form()` 支持表单<abbr title="将 HTTP 请求中的字符串转换为 Python 数据">「解析」</abbr>时需要。
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - 使用 `request.form()` 支持表单<dfn title="将 HTTP 请求中的字符串转换为 Python 数据">「解析」</dfn>时需要。
FastAPI 使用:

View File

@@ -2,11 +2,11 @@
Python 支持可选的“类型提示”(也叫“类型注解”)。
这些“类型提示”或注解是一种特殊语法,用来声明变量的<abbr title="例如str、int、float、bool">类型</abbr>。
这些“类型提示”或注解是一种特殊语法,用来声明变量的<dfn title="例如str、int、float、bool">类型</dfn>。
通过为变量声明类型,编辑器和工具可以为你提供更好的支持。
这只是一个关于 Python 类型提示的快速入门/复习。它只涵盖与 **FastAPI** 一起使用所需的最少部分……实际上非常少。
这只是一个关于 Python 类型提示的快速入门/复习。它只涵盖与 **FastAPI** 一起使用所需的最少部分...实际上非常少。
**FastAPI** 完全基于这些类型提示构建,它们带来了许多优势和好处。
@@ -22,7 +22,7 @@ Python 支持可选的“类型提示”(也叫“类型注解”)。
让我们从一个简单的例子开始:
{* ../../docs_src/python_types/tutorial001_py39.py *}
{* ../../docs_src/python_types/tutorial001_py310.py *}
运行这个程序会输出:
@@ -34,9 +34,9 @@ John Doe
* 接收 `first_name``last_name`
* 通过 `title()` 将每个参数的第一个字母转换为大写。
* 用一个空格将它们<abbr title="把它们合在一起成为一个,内容一个接在另一个后面。">拼接</abbr>起来。
* 用一个空格将它们<dfn title="把它们合在一起成为一个,内容一个接在另一个后面。">拼接</dfn>起来。
{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *}
### 修改它 { #edit-it }
@@ -78,7 +78,7 @@ John Doe
这些就是“类型提示”:
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *}
这和声明默认值不同,比如:
@@ -106,7 +106,7 @@ John Doe
看这个已经带有类型提示的函数:
{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *}
因为编辑器知道变量的类型,你不仅能得到补全,还能获得错误检查:
@@ -114,7 +114,7 @@ John Doe
现在你知道需要修复它,用 `str(age)``age` 转成字符串:
{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *}
## 声明类型 { #declaring-types }
@@ -133,29 +133,32 @@ John Doe
* `bool`
* `bytes`
{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *}
### 带类型参数的泛型类型 { #generic-types-with-type-parameters }
### typing 模块 { #typing-module }
有些数据结构可以包含其他值,比如 `dict``list``set` `tuple`。而内部的值也会有自己的类型。
在一些额外的用例中,你可能需要从标准库的 `typing` 模块导入内容。比如当你想声明“任意类型”时,可以使用 `typing` 中的 `Any`
这些带有内部类型的类型称为“泛型”generic类型。可以把它们连同内部类型一起声明出来。
```python
from typing import Any
要声明这些类型以及内部类型,你可以使用 Python 标准库模块 `typing`。它就是为支持这些类型提示而存在的。
#### 更新的 Python 版本 { #newer-versions-of-python }
def some_function(data: Any):
print(data)
```
使用 `typing` 的语法与所有版本兼容,从 Python 3.6 到最新版本(包括 Python 3.9、Python 3.10 等)。
### 泛型类型 { #generic-types }
随着 Python 的发展,更新的版本对这些类型注解的支持更好,在很多情况下你甚至不需要导入和使用 `typing` 模块来声明类型注解
有些类型可以在方括号中接收“类型参数”type parameters用于声明其内部值的类型。比如“字符串列表”可以写为 `list[str]`
如果你可以为项目选择更高版本的 Python你将能享受到这种额外的简化
这些能接收类型参数的类型称为“泛型类型”Generic types或“泛型”Generics
在整个文档中,会根据不同 Python 版本提供相应的示例(当存在差异时)。
你可以把相同的内建类型作为泛型使用(带方括号和内部类型):
比如“Python 3.6+”表示兼容 Python 3.6 及以上(包括 3.7、3.8、3.9、3.10 等。而“Python 3.9+”表示兼容 Python 3.9 及以上(包括 3.10 等)。
如果你可以使用最新的 Python 版本请使用最新版本的示例它们将拥有最简洁的语法例如“Python 3.10+”。
* `list`
* `tuple`
* `set`
* `dict`
#### 列表 { #list }
@@ -167,7 +170,7 @@ John Doe
因为 list 是一种包含内部类型的类型,把内部类型写在方括号里:
{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *}
/// info | 信息
@@ -193,7 +196,7 @@ John Doe
声明 `tuple``set` 的方式类似:
{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *}
这表示:
@@ -208,7 +211,7 @@ John Doe
第二个类型参数用于字典的值:
{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *}
这表示:
@@ -220,44 +223,20 @@ John Doe
你可以声明一个变量可以是若干种类型中的任意一种,比如既可以是 `int` 也可以是 `str`
在 Python 3.6 及以上(包括 Python 3.10),你可以使用 `typing` 中的 `Union`,把可能的类型放到方括号里
定义时使用<dfn title='也叫“按位或运算符bitwise or operator但这里与该含义无关'>竖线(`|`</dfn>把两种类型分开
在 Python 3.10 中还有一种新的语法,可以用<abbr title='也叫“按位或运算符bitwise or operator但这里与该含义无关'>竖线(`|`</abbr>把可能的类型分隔开
//// tab | Python 3.10+
这称为“联合类型”union因为变量可以是这两类类型集合的并集中的任意一个
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
```
////
//// tab | Python 3.9+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008b_py39.py!}
```
////
两种方式的含义一致:`item` 可以是 `int` 或 `str`。
这表示 `item` 可以是 `int` 或 `str`。
#### 可能为 `None` { #possibly-none }
你可以声明一个值的类型是某种类型(比如 `str`),但它也可能是 `None`。
在 Python 3.6 及以上(包括 Python 3.10),你可以通过从 `typing` 模块导入并使用 `Optional` 来声明:
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial009_py39.py!}
```
使用 `Optional[str]` 而不是仅仅 `str`,可以让编辑器帮助你发现把值当成总是 `str` 的错误(实际上它也可能是 `None`)。
`Optional[Something]` 实际上是 `Union[Something, None]` 的简写,它们等价。
这也意味着在 Python 3.10 中,你可以使用 `Something | None`
//// tab | Python 3.10+
```Python hl_lines="1"
@@ -266,96 +245,7 @@ John Doe
////
//// tab | Python 3.9+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009_py39.py!}
```
////
//// tab | Python 3.9+ 另一种写法
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009b_py39.py!}
```
////
#### 使用 `Union` 或 `Optional` { #using-union-or-optional }
如果你使用的是 3.10 以下的 Python 版本,这里有个来自我非常主观的建议:
* 🚨 避免使用 `Optional[SomeType]`
* 改用 ✨**`Union[SomeType, None]`**✨
两者等价,底层相同,但我更推荐 `Union` 而不是 `Optional`因为“optional可选”这个词看起来像是在说“参数可选”而它实际上表示“它可以是 `None`”,即使它并不是可选的,仍然是必填的。
我认为 `Union[SomeType, None]` 更明确地表达了它的意思。
这只是关于词语和名字。但这些词会影响你和你的队友如何理解代码。
例如,看下面这个函数:
{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
参数 `name` 被定义为 `Optional[str]`,但它并不是“可选”的,你不能不传这个参数就调用函数:
```Python
say_hi() # 哦不,这会抛错!😱
```
参数 `name` 仍然是必填的(不是“可选”),因为它没有默认值。不过,`name` 接受 `None` 作为值:
```Python
say_hi(name=None) # 这样可以None 是有效值 🎉
```
好消息是,一旦你使用 Python 3.10,就无需再为此操心,因为你可以直接用 `|` 来定义类型联合:
{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
这样你就不必再考虑 `Optional` 和 `Union` 这些名字了。😎
#### 泛型类型 { #generic-types }
这些在方括号中接收类型参数的类型称为“泛型类型”Generic types或“泛型”Generics例如
//// tab | Python 3.10+
你可以把同样的内建类型作为泛型使用(带方括号和内部类型):
* `list`
* `tuple`
* `set`
* `dict`
以及与之前的 Python 版本一样,来自 `typing` 模块的:
* `Union`
* `Optional`
* ……以及其他。
在 Python 3.10 中,作为使用泛型 `Union` 和 `Optional` 的替代,你可以使用<abbr title='也叫“按位或运算符bitwise or operator但这里与该含义无关'>竖线(`|`</abbr>来声明类型联合,这更好也更简单。
////
//// tab | Python 3.9+
你可以把同样的内建类型作为泛型使用(带方括号和内部类型):
* `list`
* `tuple`
* `set`
* `dict`
以及来自 `typing` 模块的泛型:
* `Union`
* `Optional`
* ……以及其他。
////
使用 `str | None` 而不是仅仅 `str`,可以让编辑器帮助你发现把值当成总是 `str` 的错误(实际上它也可能是 `None`)。
### 类作为类型 { #classes-as-types }
@@ -363,11 +253,11 @@ say_hi(name=None) # 这样可以None 是有效值 🎉
假设你有一个名为 `Person` 的类,带有 name
{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *}
然后你可以声明一个变量是 `Person` 类型:
{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *}
接着,你会再次获得所有的编辑器支持:
@@ -403,19 +293,13 @@ say_hi(name=None) # 这样可以None 是有效值 🎉
你会在[教程 - 用户指南](tutorial/index.md){.internal-link target=_blank}中看到更多的实战示例。
/// tip | 提示
当你在没有默认值的情况下使用 `Optional` 或 `Union[Something, None]` 时Pydantic 有一个特殊行为,你可以在 Pydantic 文档的 <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">必填的 Optional 字段</a> 中了解更多。
///
## 带元数据注解的类型提示 { #type-hints-with-metadata-annotations }
Python 还提供了一个特性,可以使用 `Annotated` 在这些类型提示中放入额外的<abbr title="关于数据的数据,在这里是关于类型的信息,例如描述。">元数据</abbr>。
Python 还提供了一个特性,可以使用 `Annotated` 在这些类型提示中放入额外的<dfn title="关于数据的数据,此处指关于类型的信息,例如描述。">元数据</dfn>。
从 Python 3.9 起,`Annotated` 是标准库的一部分,因此可以从 `typing` 导入
你可以从 `typing` 导入 `Annotated`
{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *}
Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其他工具,类型仍然是 `str`。

View File

@@ -15,7 +15,7 @@
首先导入 `BackgroundTasks` 并在 *路径操作函数* 中使用类型声明 `BackgroundTasks` 定义一个参数:
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *}
**FastAPI** 会创建一个 `BackgroundTasks` 类型的对象并作为该参数传入。
@@ -31,13 +31,13 @@
由于写操作不使用 `async``await`,我们用普通的 `def` 定义函数:
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *}
## 添加后台任务 { #add-the-background-task }
在你的 *路径操作函数* 里,用 `.add_task()` 方法将任务函数传到 *后台任务* 对象中:
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *}
`.add_task()` 接收以下参数:
@@ -69,7 +69,7 @@
在FastAPI中仍然可以单独使用 `BackgroundTask`但您必须在代码中创建对象并返回包含它的Starlette `Response`
更多细节查看 <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">Starlette's official docs for Background Tasks</a>.
更多细节查看 <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">Starlette 后台任务的官方文档</a>.
## 告诫 { #caveat }

View File

@@ -85,7 +85,7 @@ from app.routers import items
你可以导入它并通过与 `FastAPI` 类相同的方式创建一个「实例」:
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *}
### 使用 `APIRouter` 的*路径操作* { #path-operations-with-apirouter }
@@ -93,7 +93,7 @@ from app.routers import items
使用方式与 `FastAPI` 类相同:
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
你可以将 `APIRouter` 视为一个「迷你 `FastAPI`」类。
@@ -117,7 +117,7 @@ from app.routers import items
现在我们将使用一个简单的依赖项来读取一个自定义的 `X-Token` 请求首部:
{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
/// tip | 提示
@@ -149,7 +149,7 @@ from app.routers import items
因此,我们可以将其添加到 `APIRouter` 中,而不是将其添加到每个路径操作中。
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
由于每个*路径操作*的路径都必须以 `/` 开头,例如:
@@ -208,7 +208,7 @@ async def read_item(item_id: str):
因此,我们通过 `..` 对依赖项使用了相对导入:
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *}
#### 相对导入如何工作 { #how-relative-imports-work }
@@ -279,11 +279,11 @@ from ...dependencies import get_token_header
但是我们仍然可以添加*更多*将会应用于特定的*路径操作*的 `tags`,以及一些特定于该*路径操作*的额外 `responses`
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *}
/// tip | 提示
最后的这个路径操作将包含标签的组合:`["items""custom"]`。
最后的这个路径操作将包含标签的组合:`["items", "custom"]`。
并且在文档中也会有两个响应,一个用于 `404`,一个用于 `403`。
@@ -305,13 +305,13 @@ from ...dependencies import get_token_header
我们甚至可以声明[全局依赖项](dependencies/global-dependencies.md){.internal-link target=_blank},它会和每个 `APIRouter` 的依赖项组合在一起:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *}
### 导入 `APIRouter` { #import-the-apirouter }
现在,我们导入具有 `APIRouter` 的其他子模块:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *}
由于文件 `app/routers/users.py` 和 `app/routers/items.py` 是同一 Python 包 `app` 一个部分的子模块,因此我们可以使用单个点 ` .` 通过「相对导入」来导入它们。
@@ -374,13 +374,13 @@ from .routers.users import router
因此,为了能够在同一个文件中使用它们,我们直接导入子模块:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *}
### 包含 `users` 和 `items` 的 `APIRouter` { #include-the-apirouters-for-users-and-items }
现在,让我们来包含来自 `users` 和 `items` 子模块的 `router`。
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *}
/// info | 信息
@@ -420,13 +420,13 @@ from .routers.users import router
对于此示例,它将非常简单。但是假设由于它是与组织中的其他项目所共享的,因此我们无法对其进行修改,以及直接在 `APIRouter` 中添加 `prefix`、`dependencies`、`tags` 等:
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *}
但是我们仍然希望在包含 `APIRouter` 时设置一个自定义的 `prefix`,以便其所有*路径操作*以 `/admin` 开头,我们希望使用本项目已经有的 `dependencies` 保护它,并且我们希望它包含自定义的 `tags` 和 `responses`。
我们可以通过将这些参数传递给 `app.include_router()` 来完成所有的声明,而不必修改原始的 `APIRouter`
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *}
这样,原始的 `APIRouter` 将保持不变,因此我们仍然可以与组织中的其他项目共享相同的 `app/internal/admin.py` 文件。
@@ -447,7 +447,7 @@ from .routers.users import router
这里我们这样做了...只是为了表明我们可以做到🤷:
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *}
它将与通过 `app.include_router()` 添加的所有其他*路径操作*一起正常运行。

View File

@@ -104,12 +104,6 @@
q: str | None = None
```
或者在 Python 3.9 中:
```Python
q: Union[str, None] = None
```
比如:
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}

View File

@@ -163,7 +163,7 @@ images: list[Image]
例如:
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *}
## 无处不在的编辑器支持 { #editor-support-everywhere }
@@ -193,7 +193,7 @@ images: list[Image]
在下面的例子中,你将接受任意键为 `int` 类型并且值为 `float` 类型的 `dict`
{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *}
/// tip | 提示

View File

@@ -153,7 +153,7 @@
FastAPI 会根据默认值 `= None` 知道 `q` 的值不是必填的。
`str | None`Python 3.10+)或 `Union[str, None]`Python 3.9+ 中的 `Union`并不是 FastAPI 用来判断是否必填的依据;是否必填由是否有默认值 `= None` 决定。
`str | None` 并不是 FastAPI 用来判断是否必填的依据;是否必填由是否有默认值 `= None` 决定。
但添加这些类型注解可以让你的编辑器提供更好的支持并检测错误。

View File

@@ -46,17 +46,17 @@
在某些特殊使用情况下(可能并不常见),您可能希望**限制**您想要接收的 cookie。
您的 API 现在可以控制自己的 <abbr title="顺带一提,这是一个笑话。它与 cookie 同意无关,但现在连API都能拒绝那些可怜的 cookie真是太有意思了。来,吃块小饼干cookie吧。🍪">cookie 同意</abbr>。🤪🍪
您的 API 现在可以控制自己的 <dfn title="只是个玩笑,别当真。和 cookie 同意无关,不过连 API 现在都能拒绝可怜的 cookie挺好玩的。来,吃块小饼干吧。🍪">cookie 同意</dfn>。🤪🍪
您可以使用 Pydantic 的模型配置来禁止( `forbid` )任何额外( `extra` )字段:
{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *}
如果客户尝试发送一些**额外的 cookie**,他们将收到**错误**响应。
如果客户尝试发送一些**额外的 cookie**,他们将收到**错误**响应。
可怜的 cookie 通知条,费尽心思为了获得您的同意,却被<abbr title="又是一个笑话别管我了给您的小饼干cookie配上点咖啡吧。☕">API 拒绝了</abbr>。🍪
可怜的 cookie 通知条,费尽心思为了获得您的同意,却被<dfn title="又是个玩笑,别理我。给你的小饼干配点咖啡吧。☕">API 拒绝了</dfn>。🍪
例如,如果客户端尝试发送一个值为 `good-list-please``santa_tracker` cookie客户端将收到一个**错误**响应,告知他们 `santa_tracker` <abbr title="圣诞老人Santa不赞成没有小饼干cookie。🎅 好吧,不会再开 cookie 的笑了。">cookie 是不允许的</abbr>
例如,如果客户端尝试发送一个值为 `good-list-please``santa_tracker` cookie客户端将收到一个**错误**响应,告知他们 `santa_tracker` <dfn title="圣诞老人不赞成没有小饼干。🎅 好吧,不再讲 cookie 的笑了。">cookie 是不允许的</dfn>
```json
{
@@ -73,4 +73,4 @@
## 总结 { #summary }
您可以使用 **Pydantic 模型**在 **FastAPI** 中声明 <abbr title="走之前再来块小饼干吧。 🍪">**cookie**</abbr>。😎
您可以使用 **Pydantic 模型**在 **FastAPI** 中声明 <dfn title="临走前再吃一块小饼干吧。🍪">**cookie**</dfn>。😎

View File

@@ -46,7 +46,7 @@
* 特定的 HTTP 方法(`POST``PUT`)或者使用通配符 `"*"` 允许所有方法。
* 特定的 HTTP 请求头或者使用通配符 `"*"` 允许所有请求头。
{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *}
默认情况下,这个 `CORSMiddleware` 实现所使用的默认参数较为保守,所以你需要显式地启用特定的源、方法或者 headers以便浏览器能够在跨域上下文中使用它们。
@@ -63,7 +63,7 @@
* `expose_headers` - 指示可以被浏览器访问的响应头。默认为 `[]`
* `max_age` - 设定浏览器缓存 CORS 响应的最长时间,单位是秒。默认为 `600`
中间件响应两种特定类型的 HTTP 请求……
中间件响应两种特定类型的 HTTP 请求...
### CORS 预检请求 { #cors-preflight-requests }

View File

@@ -6,7 +6,7 @@
在你的 FastAPI 应用中直接导入 `uvicorn` 并运行:
{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *}
### 关于 `__name__ == "__main__"` { #about-name-main }
@@ -68,7 +68,7 @@ from myapp import app
uvicorn.run(app, host="0.0.0.0", port=8000)
```
/// info
/// info | 信息
更多信息请检查 <a href="https://docs.python.org/3/library/__main__.html" class="external-link" target="_blank">Python 官方文档</a>.

View File

@@ -14,7 +14,7 @@
对此,我们可以做的更好...
## 什么构成了依赖项 { #what-makes-a-dependency }
## 什么构成了依赖项 { #what-makes-a-dependency }
到目前为止,你看到的依赖项都被声明为函数。
@@ -101,7 +101,7 @@ fluffy = Cat(name="Mr Fluffy")
注意,我们在上面的代码中编写了两次`CommonQueryParams`
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 未使用 Annotated
//// tab | Python 3.10+ 未使用 Annotated
/// tip | 提示
@@ -129,7 +129,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
... Depends(CommonQueryParams)
```
...实际上是 **Fastapi** 用来知道依赖项是什么的。
...实际上是 **FastAPI** 用来知道依赖项是什么的。
FastAPI 将从依赖项中提取声明的参数,这才是 FastAPI 实际调用的。
@@ -137,7 +137,7 @@ FastAPI 将从依赖项中提取声明的参数,这才是 FastAPI 实际调用
在本例中,第一个 `CommonQueryParams`
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, ...
@@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ...
////
//// tab | Python 3.9+ 未使用 Annotated
//// tab | Python 3.10+ 未使用 Annotated
/// tip | 提示
@@ -163,7 +163,7 @@ commons: CommonQueryParams ...
你实际上可以只这样编写:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
@@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 未使用 Annotated
//// tab | Python 3.10+ 未使用 Annotated
/// tip | 提示
@@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams)
但是你可以看到,我们在这里有一些代码重复了,编写了`CommonQueryParams`两次:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 未使用 Annotated
//// tab | Python 3.10+ 未使用 Annotated
/// tip | 提示
@@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
不是写成这样:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 未使用 Annotated
//// tab | Python 3.10+ 未使用 Annotated
/// tip | 提示
@@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
...而是这样写:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends()]
@@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()]
////
//// tab | Python 3.9+ 未使用 Annotated
//// tab | Python 3.10+ 未使用 Annotated
/// tip | 提示

View File

@@ -14,7 +14,7 @@
该参数的值是由 `Depends()` 组成的 `list`
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *}
路径操作装饰器依赖项的执行或解析方式和普通依赖项一样,但就算这些依赖项会返回值,它们的值也不会传递给*路径操作函数*。
@@ -22,13 +22,13 @@
有些编辑器会检查代码中没使用过的函数参数,并显示错误提示。
在*路径操作装饰器*中使用 `dependencies` 参数,可以确保在执行依赖项的同时,避免编辑器显示错误提示
在*路径操作装饰器*中使用 `dependencies` 参数,可以确保在执行依赖项的同时,避免编辑器/工具报错
使用路径装饰器依赖项还可以避免开发新人误会代码中包含无用的未使用参数。
///
/// info | 说明
/// info | 信息
本例中,使用的是自定义响应头 `X-Key``X-Token`
@@ -44,13 +44,13 @@
路径装饰器依赖项可以声明请求的需求项(比如响应头)或其他子依赖项:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *}
### 触发异常 { #raise-exceptions }
路径装饰器依赖项与正常的依赖项一样,可以 `raise` 异常:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *}
### 返回值 { #return-values }
@@ -58,7 +58,7 @@
因此,可以复用在其他位置使用过的、(能返回值的)普通依赖项,即使没有使用这个值,也会执行该依赖项:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *}
## 为一组路径操作定义依赖项 { #dependencies-for-a-group-of-path-operations }

View File

@@ -1,6 +1,6 @@
# 使用 yield 的依赖项 { #dependencies-with-yield }
FastAPI 支持那些在完成后执行一些<abbr title='有时也称为 "exit code"、"cleanup code"、"teardown code"、"closing code"、"context manager exit code" 等'>额外步骤</abbr>的依赖项。
FastAPI 支持那些在完成后执行一些<dfn title="有时也称为:“退出代码”、“清理代码”、“拆卸代码”、“关闭代码”、“上下文管理器退出代码”等">额外步骤</dfn>的依赖项。
为此,使用 `yield` 而不是 `return`,并把这些额外步骤(代码)写在后面。
@@ -29,15 +29,15 @@ FastAPI 支持那些在完成后执行一些<abbr title='有时也被称为 "exi
在创建响应之前,只会执行 `yield` 语句及其之前的代码:
{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *}
`yield` 产生的值会注入到 *路径操作* 和其他依赖项中:
{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *}
`yield` 语句后面的代码会在响应之后执行:
{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *}
/// tip | 提示
@@ -57,7 +57,7 @@ FastAPI 支持那些在完成后执行一些<abbr title='有时也被称为 "exi
同样地,你可以使用 `finally` 来确保退出步骤一定会被执行,无论是否发生异常。
{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *}
## 使用 `yield` 的子依赖项 { #sub-dependencies-with-yield }
@@ -67,7 +67,7 @@ FastAPI 支持那些在完成后执行一些<abbr title='有时也被称为 "exi
例如,`dependency_c` 可以依赖 `dependency_b`,而 `dependency_b` 则依赖 `dependency_a`
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *}
并且它们都可以使用 `yield`
@@ -75,7 +75,7 @@ FastAPI 支持那些在完成后执行一些<abbr title='有时也被称为 "exi
`dependency_b` 又需要 `dependency_a`(此处命名为 `dep_a`)的值在其退出代码中可用。
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *}
同样地,你可以将一些依赖用 `yield`,另一些用 `return`,并让其中一些依赖依赖于另一些。
@@ -109,7 +109,7 @@ FastAPI 支持那些在完成后执行一些<abbr title='有时也被称为 "exi
///
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *}
如果你想捕获异常并基于它创建一个自定义响应,请创建一个[自定义异常处理器](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}。
@@ -117,7 +117,7 @@ FastAPI 支持那些在完成后执行一些<abbr title='有时也被称为 "exi
如果你在带有 `yield` 的依赖中使用 `except` 捕获了一个异常并且你没有再次抛出它或抛出一个新异常FastAPI 将无法察觉发生过异常,就像普通的 Python 代码那样:
{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}
{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *}
在这种情况下,客户端会像预期那样看到一个 *HTTP 500 Internal Server Error* 响应,因为我们没有抛出 `HTTPException` 或类似异常,但服务器将**没有任何日志**或其他关于错误是什么的提示。😱
@@ -127,7 +127,7 @@ FastAPI 支持那些在完成后执行一些<abbr title='有时也被称为 "exi
你可以使用 `raise` 重新抛出同一个异常:
{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *}
现在客户端仍会得到同样的 *HTTP 500 Internal Server Error* 响应,但服务器日志中会有我们自定义的 `InternalError`。😎
@@ -190,7 +190,7 @@ participant tasks as Background tasks
但如果你知道在从 *路径操作函数* 返回之后不再需要使用该依赖,你可以使用 `Depends(scope="function")` 告诉 FastAPI应当在 *路径操作函数* 返回后、但在**响应发送之前**关闭该依赖。
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *}
`Depends()` 接收一个 `scope` 参数,可为:
@@ -269,7 +269,7 @@ with open("./somefile.txt") as f:
你也可以在 **FastAPI** 的带有 `yield` 的依赖中,使用依赖函数内部的 `with``async with` 语句来使用它们:
{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *}
{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *}
/// tip | 提示

View File

@@ -6,7 +6,7 @@
这样一来,就可以为所有*路径操作*应用该依赖项:
{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *}
{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *}
[将 `dependencies` 添加到*路径操作装饰器*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 一章的思路均适用于全局依赖项, 在本例中,这些依赖项可以用于应用中的所有*路径操作*。

View File

@@ -1,6 +1,6 @@
# 依赖项 { #dependencies }
**FastAPI** 提供了简单直观但功能强大的**<abbr title="也称为组件、资源、提供者、服务、可注入项">依赖注入</abbr>**系统。
**FastAPI** 提供了简单直观但功能强大的**<dfn title="也称为组件、资源、提供者、服务、可注入项">依赖注入</dfn>**系统。
它被设计得非常易用,能让任何开发者都能轻松把其他组件与 **FastAPI** 集成。
@@ -35,7 +35,7 @@
大功告成。
只用了**2 行**代码
**2 行**
它的形式和结构与所有*路径操作函数*相同。
@@ -203,7 +203,7 @@ commons: Annotated[dict, Depends(common_parameters)]
* 响应数据注入系统
* 等等...
## 单而强大 { #simple-and-powerful }
## 单而强大 { #simple-and-powerful }
虽然**层级式依赖注入系统**的定义与使用非常简单,但它依然非常强大。

View File

@@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query
如果在同一个*路径操作* 多次声明了同一个依赖项,例如,多个依赖项共用一个子依赖项,**FastAPI** 在处理同一请求时,只调用一次该子依赖项。
FastAPI 不会为同一个请求多次调用同一个依赖项,而是把依赖项的返回值进行<abbr title="一个实用程序/系统来存储计算/生成的值,以便重用它们,而不是再次计算它们。">「缓存」</abbr>,并把它传递给同一请求中所有需要使用该返回值的「依赖项」。
FastAPI 不会为同一个请求多次调用同一个依赖项,而是把依赖项的返回值进行<dfn title="用于存储计算/生成的值,以便复用而无需再次计算的实用工具/系统">「缓存」</dfn>,并把它传递给同一请求中所有需要使用该返回值的「依赖项」。
在高级使用场景中,如果不想使用「缓存」值,而是为需要在同一请求的每一步操作(多次)中都实际调用依赖项,可以把 `Depends` 的参数 `use_cache` 的值设置为 `False`:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python hl_lines="1"
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
@@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca
////
//// tab | Python 3.9+ 非 Annotated
//// tab | Python 3.10+ 非 Annotated
/// tip | 提示

View File

@@ -12,7 +12,7 @@
例如,它不接收`datetime`这类的对象因为这些对象与JSON不兼容。
因此,`datetime`对象必须转换为包含<a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO格式</a>的`str`类型对象。
因此,`datetime`对象必须转换为包含<a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO 格式</a>的`str`类型对象。
同样这个数据库也不会接收Pydantic模型带有属性的对象而只接收`dict`
@@ -30,6 +30,6 @@
/// note | 注意
`jsonable_encoder`实际上是FastAPI内部用来转换数据的。但是它在许多其他场景中也很有用。
`jsonable_encoder`实际上是**FastAPI**内部用来转换数据的。但是它在许多其他场景中也很有用。
///

View File

@@ -8,7 +8,7 @@
* **输出模型**不应含密码
* **数据库模型**可能需要包含哈希后的密码
/// danger
/// danger | 危险
不要存储用户的明文密码。始终只存储之后可用于校验的“安全哈希”。
@@ -132,7 +132,7 @@ UserInDB(
)
```
/// warning
/// warning | 警告
配套的辅助函数 `fake_password_hasher``fake_save_user` 仅用于演示可能的数据流,当然并不提供真实的安全性。
@@ -164,7 +164,7 @@ UserInDB(
为此,请使用 Python 标准类型提示 <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>
/// note
/// note | 注意
定义 <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a> 类型时,要把更具体的类型写在前面,然后是不太具体的类型。下例中,更具体的 `PlaneItem` 位于 `Union[PlaneItem, CarItem]` 中的 `CarItem` 之前。
@@ -190,9 +190,9 @@ some_variable: PlaneItem | CarItem
同样地,你可以声明由对象列表构成的响应。
为此,请使用标准的 Python `typing.List`(在 Python 3.9+ 中也可以直接用 `list`
为此,请使用标准的 Python `list`
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *}
## 任意 `dict` 的响应 { #response-with-arbitrary-dict }
@@ -200,9 +200,9 @@ some_variable: PlaneItem | CarItem
如果你事先不知道有效的字段/属性名Pydantic 模型需要预先知道字段)时,这很有用。
此时,可以使用 `typing.Dict`(在 Python 3.9+ 中也可以直接用 `dict`
此时,可以使用 `dict`
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *}
## 小结 { #recap }

View File

@@ -2,7 +2,7 @@
最简单的 FastAPI 文件可能像下面这样:
{* ../../docs_src/first_steps/tutorial001_py39.py *}
{* ../../docs_src/first_steps/tutorial001_py310.py *}
将其复制到 `main.py` 文件中。
@@ -42,8 +42,8 @@ $ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid
to quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
@@ -110,7 +110,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送
如果你对原始的 OpenAPI 模式长什么样子感到好奇FastAPI 自动生成了包含所有 API 描述的 JSON模式
你可以直接在:<a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:800api.json</a> 看到它。
你可以直接在:<a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a> 看到它。
它将显示以如下内容开头的 JSON
@@ -183,7 +183,7 @@ Deploying to FastAPI Cloud...
### 步骤 1导入 `FastAPI` { #step-1-import-fastapi }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *}
`FastAPI` 是一个为你的 API 提供了所有功能的 Python 类。
@@ -197,7 +197,7 @@ Deploying to FastAPI Cloud...
### 步骤 2创建一个 `FastAPI`「实例」 { #step-2-create-a-fastapi-instance }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *}
这里的变量 `app` 会是 `FastAPI` 类的一个「实例」。
@@ -266,12 +266,12 @@ https://example.com/items/foo
#### 定义一个*路径操作装饰器* { #define-a-path-operation-decorator }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *}
`@app.get("/")` 告诉 **FastAPI** 在它下方的函数负责处理如下访问请求:
* 请求路径为 `/`
* 使用 <abbr title="HTTP GET 方法"><code>get</code> 操作</abbr>
* 使用 <dfn title="一种 HTTP GET 方法"><code>get</code> 操作</dfn>
/// info | `@decorator` Info
@@ -320,7 +320,7 @@ https://example.com/items/foo
* **操作**:是 `get`。
* **函数**:是位于「装饰器」下方的函数(位于 `@app.get("/")` 下方)。
{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *}
这是一个 Python 函数。
@@ -332,7 +332,7 @@ https://example.com/items/foo
你也可以将其定义为常规函数而不使用 `async def`:
{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *}
/// note
@@ -342,7 +342,7 @@ https://example.com/items/foo
### 步骤 5返回内容 { #step-5-return-the-content }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *}
你可以返回一个 `dict`、`list`,像 `str`、`int` 一样的单个值,等等。

View File

@@ -25,7 +25,7 @@
### 导入 `HTTPException` { #import-httpexception }
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *}
### 在代码中触发 `HTTPException` { #raise-an-httpexception-in-your-code }
@@ -39,7 +39,7 @@
本例中,客户端用不存在的 `ID` 请求 `item` 时,触发状态码为 `404` 的异常:
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *}
### 响应结果 { #the-resulting-response }
@@ -77,7 +77,7 @@
但在某些高级场景中需要时,你可以添加自定义响应头:
{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *}
## 安装自定义异常处理器 { #install-custom-exception-handlers }
@@ -89,7 +89,7 @@
此时,可以用 `@app.exception_handler()` 添加自定义异常处理器:
{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *}
这里,请求 `/unicorns/yolo` 时,路径操作会触发 `UnicornException`
@@ -127,7 +127,7 @@
异常处理器会接收 `Request` 和该异常。
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *}
现在,访问 `/items/foo` 时,默认的 JSON 错误为:
@@ -159,7 +159,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
例如,只为这些错误返回纯文本响应,而不是 JSON
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *}
/// note | 技术细节
@@ -183,7 +183,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
开发时,你可以用它来记录请求体、调试错误,或返回给用户等。
{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *}
现在试着发送一个无效的 `item`,例如:
@@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
如果你想在自定义处理后仍复用 **FastAPI** 的默认异常处理器,可以从 `fastapi.exception_handlers` 导入并复用这些默认处理器:
{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *}
虽然本例只是用非常夸张的信息打印了错误,但足以说明:你可以先处理异常,然后再复用默认的异常处理器。

View File

@@ -18,7 +18,7 @@
你可以按如下方式设置它们:
{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *}
/// tip | 提示
@@ -36,7 +36,7 @@
例如:
{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *}
## 标签元数据 { #metadata-for-tags }
@@ -58,7 +58,7 @@
创建标签元数据并把它传递给 `openapi_tags` 参数:
{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *}
注意你可以在描述内使用 Markdown例如「login」会显示为粗体**login**以及「fancy」会显示为斜体_fancy_
@@ -72,7 +72,7 @@
`tags` 参数和*路径操作*(以及 `APIRouter`)一起使用,将其分配给不同的标签:
{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *}
/// info | 信息
@@ -100,7 +100,7 @@
例如,将其设置为服务于 `/api/v1/openapi.json`
{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *}
如果你想完全禁用 OpenAPI 模式,可以将其设置为 `openapi_url=None`,这样也会禁用使用它的文档用户界面。
@@ -117,4 +117,4 @@
例如,设置 Swagger UI 服务于 `/documentation` 并禁用 ReDoc
{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *}

View File

@@ -31,7 +31,7 @@
* 然后它返回由相应*路径操作*生成的 `response`
* 在返回之前,你可以进一步修改 `response`
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *}
/// tip
@@ -57,7 +57,7 @@
例如,你可以添加一个自定义请求头 `X-Process-Time`,其值为处理请求并生成响应所花费的秒数:
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *}
/// tip

View File

@@ -46,7 +46,7 @@ OpenAPI 概图会自动添加标签,供 API 文档接口使用:
**FastAPI** 对此的支持与使用普通字符串相同:
{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *}
## 摘要和描述 { #summary-and-description }
@@ -56,13 +56,13 @@ OpenAPI 概图会自动添加标签,供 API 文档接口使用:
## 从 docstring 获取描述 { #description-from-docstring }
描述内容比较长且占用多行时,可以在函数的 <abbr title="作为函数内部的第一个表达式、用于文档用途的多行字符串(不赋给任何变量)">docstring</abbr> 中声明*路径操作*的描述,**FastAPI** 会从中读取。
描述内容比较长且占用多行时,可以在函数的 <dfn title="作为函数内部的第一个表达式(不赋给任何变量)的多行字符串,用于文档用途">docstring</dfn> 中声明*路径操作*的描述,**FastAPI** 会从中读取。
文档字符串支持 <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a>,能正确解析和显示 Markdown 的内容,但要注意文档字符串的缩进。
{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *}
下图为 Markdown 文本在 API 文档中的显示效果
它会在交互式文档中使用
<img src="/img/tutorial/path-operation-configuration/image02.png">
@@ -72,7 +72,7 @@ OpenAPI 概图会自动添加标签,供 API 文档接口使用:
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
/// info | 说明
/// info | 信息
注意,`response_description` 只用于描述响应,`description` 一般则用于描述*路径操作*。
@@ -90,9 +90,9 @@ OpenAPI 规定每个*路径操作*都要有响应描述。
## 弃用*路径操作* { #deprecate-a-path-operation }
`deprecated` 参数可以把*路径操作*标记为<abbr title="过时,建议不要使用">弃用</abbr>,无需直接删除
如果需要把*路径操作*标记为<dfn title="过时,建议不要使用">弃用</dfn>,但不删除它,可以传入 `deprecated` 参数
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *}
API 文档会把该路径操作标记为弃用:

View File

@@ -54,11 +54,11 @@ FastAPI 在 0.95.0 版本添加了对 `Annotated` 的支持(并开始推荐使
因此,你可以将函数声明为:
{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *}
但请记住,如果你使用 `Annotated`,你就不会遇到这个问题,因为你没有使用 `Query()``Path()` 作为函数参数的默认值。
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *}
## 按需对参数排序的技巧 { #order-the-parameters-as-you-need-tricks }
@@ -83,13 +83,13 @@ FastAPI 在 0.95.0 版本添加了对 `Annotated` 的支持(并开始推荐使
Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数都应该作为关键字参数(键值对)来调用,也被称为 <abbr title="来自K-ey W-ord Arg-uments"><code>kwargs</code></abbr>。即使它们没有默认值。
{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *}
### 使用 `Annotated` 更好 { #better-with-annotated }
请记住,如果你使用 `Annotated`,因为你没有使用函数参数的默认值,所以你不会有这个问题,你大概率也不需要使用 `*`
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *}
## 数值校验:大于等于 { #number-validations-greater-than-or-equal }
@@ -97,7 +97,7 @@ Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数
在这里,使用 `ge=1` 后,`item_id` 必须是一个整数,值要「`g`reater than or `e`qual」1。
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *}
## 数值校验:大于和小于等于 { #number-validations-greater-than-and-less-than-or-equal }
@@ -106,7 +106,7 @@ Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数
* `gt`:大于(`g`reater `t`han
* `le`:小于等于(`l`ess than or `e`qual
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *}
## 数值校验:浮点数、大于和小于 { #number-validations-floats-greater-than-and-less-than }
@@ -118,7 +118,7 @@ Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数
对于 <abbr title="less than - 小于"><code>lt</code></abbr> 也是一样的。
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *}
## 总结 { #recap }

View File

@@ -2,7 +2,7 @@
你可以使用与 Python 字符串格式化相同的语法声明路径“参数”或“变量”:
{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *}
路径参数 `item_id` 的值会作为参数 `item_id` 传递给你的函数。
@@ -16,7 +16,7 @@
使用 Python 标准类型注解,声明路径操作函数中路径参数的类型:
{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *}
本例把 `item_id` 的类型声明为 `int`
@@ -26,7 +26,7 @@
///
## 数据<abbr title="也称为:序列化、解析、编组">转换</abbr> { #data-conversion }
## 数据<dfn title="也称为:序列化、解析、编组">转换</dfn> { #data-conversion }
运行示例并访问 <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>,返回的响应如下:
@@ -38,7 +38,7 @@
注意,函数接收并返回的值是 `3` `int`),不是 `"3"``str`)。
**FastAPI** 通过类型声明自动<abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">**解析**请求中的数据</abbr>。
**FastAPI** 通过类型声明自动进行请求的<dfn title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">解析</dfn>。
///
@@ -118,19 +118,19 @@ FastAPI 充分地利用了 <a href="https://docs.pydantic.dev/" class="external-
由于*路径操作*是按顺序依次运行的,因此,一定要在 `/users/{user_id}` 之前声明 `/users/me`
{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *}
否则,`/users/{user_id}` 将匹配 `/users/me`FastAPI 会**认为**正在接收值为 `"me"``user_id` 参数。
同样,你不能重复定义一个路径操作:
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *}
由于路径首先匹配,始终会使用第一个定义的。
## 预设值 { #predefined-values }
路径操作使用 Python 的 <abbr title="Enumeration">`Enum`</abbr> 类型接收预设的路径参数。
路径操作使用 Python 的 <abbr title="Enumeration - 枚举">`Enum`</abbr> 类型接收预设的路径参数。
### 创建 `Enum` 类 { #create-an-enum-class }
@@ -140,11 +140,11 @@ FastAPI 充分地利用了 <a href="https://docs.pydantic.dev/" class="external-
然后,创建包含固定值的类属性,这些固定值是可用的有效值:
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *}
/// tip | 提示
**AlexNet**、**ResNet**、**LeNet** 是机器学习<abbr title="技术上来说是深度学习模型架构">模型</abbr>的名字。
**AlexNet**、**ResNet**、**LeNet** 是机器学习<dfn title="技术上来说是深度学习模型架构">模型</dfn>的名字。
///
@@ -152,7 +152,7 @@ FastAPI 充分地利用了 <a href="https://docs.pydantic.dev/" class="external-
使用 Enum 类(`ModelName`)创建使用类型注解的路径参数:
{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
### 查看文档 { #check-the-docs }
@@ -168,13 +168,13 @@ API 文档会显示预定义路径参数的可用值:
可以将其与枚举类 `ModelName` 中的枚举成员进行比较:
{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *}
#### 获取枚举值 { #get-the-enumeration-value }
使用 `model_name.value` 或通用的 `your_enum_member.value` 获取实际的值(本例中为 `str`
{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *}
/// tip | 提示
@@ -188,7 +188,7 @@ API 文档会显示预定义路径参数的可用值:
返回给客户端之前,会把枚举成员转换为对应的值(本例中为字符串):
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *}
客户端中的 JSON 响应如下:
@@ -227,7 +227,7 @@ OpenAPI 不支持声明包含路径的路径参数,因为这会导致测试和
用法如下:
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *}
/// tip | 提示
@@ -242,7 +242,7 @@ OpenAPI 不支持声明包含路径的路径参数,因为这会导致测试和
通过简短、直观的 Python 标准类型声明,**FastAPI** 可以获得:
- 编辑器支持:错误检查,代码自动补全等
- 数据 "<abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">解析</abbr>"
- 数据 "<dfn title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">解析</dfn>"
- 数据校验
- API 注解和自动文档

View File

@@ -47,40 +47,16 @@ FastAPI 在 0.95.0 版本中添加了对 `Annotated` 的支持(并开始推荐
我们之前的类型标注是:
//// tab | Python 3.10+
```Python
q: str | None = None
```
////
//// tab | Python 3.9+
```Python
q: Union[str, None] = None
```
////
我们要做的是用 `Annotated` 把它包起来,变成:
//// tab | Python 3.10+
```Python
q: Annotated[str | None] = None
```
////
//// tab | Python 3.9+
```Python
q: Annotated[Union[str, None]] = None
```
////
这两种写法含义相同,`q` 是一个可以是 `str``None` 的参数,默认是 `None`
现在进入更有趣的部分。🎉
@@ -109,7 +85,7 @@ FastAPI 现在会:
## 另一种(旧的)方式:把 `Query` 作为默认值 { #alternative-old-query-as-the-default-value }
早期版本的 FastAPI<abbr title="早于 2023-03">0.95.0</abbr> 之前)要求你把 `Query` 作为参数的默认值,而不是放在 `Annotated` 里。你很可能会在别处看到这种写法,所以我也给你解释一下。
早期版本的 FastAPI<dfn title="早于 2023-03">0.95.0</dfn> 之前)要求你把 `Query` 作为参数的默认值,而不是放在 `Annotated` 里。你很可能会在别处看到这种写法,所以我也给你解释一下。
/// tip | 提示
@@ -191,7 +167,7 @@ q: str = Query(default="rick")
## 添加正则表达式 { #add-regular-expressions }
你可以定义一个参数必须匹配的 <abbr title="正则表达式regex 或 regexp是用于定义字符串搜索模式的字符序列。">正则表达式</abbr> `pattern`
你可以定义一个参数必须匹配的 <dfn title="正则表达式regex 或 regexp是用于定义字符串搜索模式的字符序列。">正则表达式</dfn> `pattern`
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
@@ -211,7 +187,7 @@ q: str = Query(default="rick")
假设你想要声明查询参数 `q``min_length``3`,并且默认值为 `"fixedquery"`
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *}
/// note | 注意
@@ -241,7 +217,7 @@ q: Annotated[str | None, Query(min_length=3)] = None
因此,在使用 `Query` 的同时需要把某个值声明为必填时,只需不声明默认值:
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *}
### 必填,但可以为 `None` { #required-can-be-none }
@@ -292,7 +268,7 @@ http://localhost:8000/items/?q=foo&q=bar
你还可以定义在没有给定值时的默认 `list`
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *}
如果你访问:
@@ -315,7 +291,7 @@ http://localhost:8000/items/
你也可以直接使用 `list`,而不是 `list[str]`
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *}
/// note | 注意
@@ -371,7 +347,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
现在假设你不再喜欢这个参数了。
由于还有客户端在使用它,你不得不保留一段时间,但你希望文档清楚地将其展示为<abbr title="已过时,不推荐使用">已弃用</abbr>。
由于还有客户端在使用它,你不得不保留一段时间,但你希望文档清楚地将其展示为<dfn title="已过时,不推荐使用">已弃用</dfn>。
那么将参数 `deprecated=True` 传给 `Query`
@@ -401,7 +377,7 @@ Pydantic 还有 <a href="https://docs.pydantic.dev/latest/concepts/validators/#f
///
例如,这个自定义校验器会检查条目 ID 是否以 `isbn-`(用于 <abbr title="ISBN 的含义是 International Standard Book Number国际标准书号">ISBN</abbr> 书号)或 `imdb-`(用于 <abbr title="IMDBInternet Movie Database)是一个包含电影信息的网站">IMDB</abbr> 电影 URL 的 ID开头
例如,这个自定义校验器会检查条目 ID 是否以 `isbn-`(用于 <abbr title="International Standard Book Number - 国际标准书号">ISBN</abbr> 书号)或 `imdb-`(用于 <abbr title="Internet Movie Database - 互联网电影数据库: 一个包含电影信息的网站">IMDB</abbr> 电影 URL 的 ID开头
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
@@ -435,7 +411,7 @@ Pydantic 还有 <a href="https://docs.pydantic.dev/latest/concepts/validators/#f
#### 一个随机条目 { #a-random-item }
使用 `data.items()` 我们会得到一个包含每个字典项键和值的元组的 <abbr title="可以用 for 循环迭代的对象,例如 list、set 等">可迭代对象</abbr>。
使用 `data.items()` 我们会得到一个包含每个字典项键和值的元组的 <dfn title="可以用 for 循环迭代的对象,例如 list、set 等">可迭代对象</dfn>。
我们用 `list(data.items())` 把这个可迭代对象转换成一个真正的 `list`

View File

@@ -2,7 +2,7 @@
声明的参数不是路径参数时,路径操作函数会把该参数自动解释为**查询**参数。
{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *}
查询字符串是键值对的集合,这些键值对位于 URL 的 `?` 之后,以 `&` 分隔。
@@ -12,7 +12,7 @@
http://127.0.0.1:8000/items/?skip=0&limit=10
```
……查询参数为:
...查询参数为:
* `skip`:值为 `0`
* `limit`:值为 `10`
@@ -24,7 +24,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10
所有应用于路径参数的流程也适用于查询参数:
* (显而易见的)编辑器支持
* 数据<abbr title="将来自 HTTP 请求的字符串转换为 Python 数据类型">**解析**</abbr>
* 数据<dfn title="将来自 HTTP 请求的字符串转换为 Python 数据">"解析"</dfn>
* 数据校验
* 自动文档
@@ -75,7 +75,6 @@ http://127.0.0.1:8000/items/?skip=20
参数还可以声明为 `bool` 类型FastAPI 会自动转换参数类型:
{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
本例中,访问:
@@ -129,7 +128,7 @@ FastAPI 通过参数名进行检测:
如果要把查询参数设置为**必选**,就不要声明默认值:
{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *}
这里的查询参数 `needy` 是类型为 `str` 的必选查询参数。
@@ -139,7 +138,7 @@ FastAPI 通过参数名进行检测:
http://127.0.0.1:8000/items/foo-item
```
……因为路径中没有必选参数 `needy`,返回的响应中会显示如下错误信息:
...因为路径中没有必选参数 `needy`,返回的响应中会显示如下错误信息:
```JSON
{
@@ -163,7 +162,7 @@ http://127.0.0.1:8000/items/foo-item
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
……这样就正常了:
...这样就正常了:
```JSON
{

View File

@@ -20,13 +20,13 @@ $ pip install python-multipart
`fastapi` 导入 `File``UploadFile`
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *}
## 定义 `File` 参数 { #define-file-parameters }
像为 `Body``Form` 一样创建文件参数:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
/// info | 信息
@@ -54,7 +54,7 @@ $ pip install python-multipart
将文件参数的类型声明为 `UploadFile`
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *}
`bytes` 相比,使用 `UploadFile` 有多项优势:
@@ -76,9 +76,9 @@ $ pip install python-multipart
`UploadFile` 具有以下 `async` 方法。它们都会在底层调用对应的文件方法(使用内部的 `SpooledTemporaryFile`)。
* `write(data)`:将 `data``str``bytes`写入文件。
* `read(size)`:读取文件中 `size``int`个字节/字符。
* `seek(offset)`:移动到文件中字节位置 `offset``int`
* `write(data)`:将 `data` (`str``bytes`) 写入文件。
* `read(size)`:读取文件中 `size` (`int`) 个字节/字符。
* `seek(offset)`:移动到文件中字节位置 `offset` (`int`)
* 例如,`await myfile.seek(0)` 会移动到文件开头。
* 如果你先运行过 `await myfile.read()`,然后需要再次读取内容时,这尤其有用。
* `close()`:关闭文件。
@@ -121,7 +121,7 @@ HTML 表单(`<form></form>`)向服务器发送数据的方式通常会对数
但当表单包含文件时,会编码为 `multipart/form-data`。如果你使用 `File`**FastAPI** 会知道需要从请求体的正确位置获取文件。
如果你想进一步了解这些编码和表单字段,请参阅 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network - Mozilla 开发者网络">MDN</abbr> web docs for <code>POST</code></a>。
如果你想进一步了解这些编码和表单字段,请参阅 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network - Mozilla 开发者网络">MDN</abbr> 关于 <code>POST</code> 的 Web 文档</a>。
///
@@ -135,7 +135,7 @@ HTML 表单(`<form></form>`)向服务器发送数据的方式通常会对数
## 可选文件上传 { #optional-file-upload }
您可以通过使用标准类型注解并将 None 作为默认值的方式将一个文件参数设为可选:
您可以通过使用标准类型注解并将 `None` 作为默认值的方式将一个文件参数设为可选:
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
@@ -143,7 +143,7 @@ HTML 表单(`<form></form>`)向服务器发送数据的方式通常会对数
您也可以将 `File()``UploadFile` 一起使用,例如,设置额外的元数据:
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *}
## 多文件上传 { #multiple-file-uploads }
@@ -153,7 +153,7 @@ FastAPI 支持同时上传多个文件。
要实现这一点,声明一个由 `bytes``UploadFile` 组成的列表(`List`
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *}
接收的也是含 `bytes``UploadFile` 的列表(`list`)。
@@ -169,7 +169,7 @@ FastAPI 支持同时上传多个文件。
和之前的方式一样,你可以为 `File()` 设置额外参数,即使是 `UploadFile`
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *}
## 小结 { #recap }

View File

@@ -24,7 +24,7 @@ $ pip install python-multipart
你只需声明一个 **Pydantic 模型**,其中包含你希望接收的**表单字段**,然后将参数声明为 `Form`
{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *}
**FastAPI** 将从请求中的**表单数据**中**提取**出**每个字段**的数据,并提供你定义的 Pydantic 模型。
@@ -48,7 +48,7 @@ $ pip install python-multipart
你可以使用 Pydantic 的模型配置来 `forbid` 任何 `extra` 字段:
{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *}
{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *}
如果客户端尝试发送一些额外的数据,他们将收到**错误**响应。

View File

@@ -16,17 +16,17 @@ $ pip install python-multipart
## 导入 `File` 与 `Form` { #import-file-and-form }
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *}
## 定义 `File` 与 `Form` 参数 { #define-file-and-form-parameters }
创建文件和表单参数的方式与 `Body``Query` 一样:
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *}
文件和表单字段作为表单数据上传与接收。
声明文件可以使用 `bytes` `UploadFile`
并且你可以将部分文件声明为 `bytes`,将部分文件声明为 `UploadFile`
/// warning | 警告

View File

@@ -18,17 +18,17 @@ $ pip install python-multipart
`fastapi` 导入 `Form`
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *}
## 定义 `Form` 参数 { #define-form-parameters }
创建表单参数的方式与 `Body``Query` 相同:
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *}
例如,在 OAuth2 规范的一种使用方式(称为“密码流”)中,要求将 `username``password` 作为表单字段发送。
<abbr title="specification - 规范">spec</abbr> 要求这些字段必须精确命名为 `username``password`,并且作为表单字段发送,而不是 JSON。
<dfn title="规范">规范</dfn> 要求这些字段必须精确命名为 `username``password`,并且作为表单字段发送,而不是 JSON。
使用 `Form` 可以像使用 `Body`(以及 `Query``Path``Cookie`)一样声明相同的配置,包括校验、示例、别名(例如将 `username` 写成 `user-name`)等。

View File

@@ -183,7 +183,7 @@ FastAPI 在内部配合 Pydantic 做了多项处理,确保不会把类继承
最常见的情况是[直接返回 Response详见进阶文档](../advanced/response-directly.md){.internal-link target=_blank}。
{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *}
这个简单场景 FastAPI 会自动处理,因为返回类型注解是 `Response`(或其子类)。
@@ -193,7 +193,7 @@ FastAPI 在内部配合 Pydantic 做了多项处理,确保不会把类继承
你也可以在类型注解中使用 `Response` 的子类:
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *}
这同样可行,因为 `RedirectResponse``Response` 的子类FastAPI 会自动处理这个简单场景。
@@ -201,7 +201,7 @@ FastAPI 在内部配合 Pydantic 做了多项处理,确保不会把类继承
但当你返回其他任意对象(如数据库对象)而它不是有效的 Pydantic 类型并在函数中按此进行了注解时FastAPI 会尝试基于该类型注解创建一个 Pydantic 响应模型,但会失败。
如果你有一个在多个类型之间的<abbr title="多个类型的联合表示“这些类型中的任意一个”">联合类型</abbr>,其中一个或多个不是有效的 Pydantic 类型,也会发生同样的情况,例如这个会失败 💥:
如果你有一个在多个类型之间的<dfn title="多个类型的联合表示“这些类型中的任意一个”">联合类型</dfn>,其中一个或多个不是有效的 Pydantic 类型,也会发生同样的情况,例如这个会失败 💥:
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}

View File

@@ -8,7 +8,7 @@
* `@app.delete()`
* 等...
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
/// note | 注意
@@ -74,7 +74,7 @@ FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。
再看下之前的例子:
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
`201` 表示“已创建”的状态码。
@@ -82,7 +82,7 @@ FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。
可以使用 `fastapi.status` 中的快捷变量。
{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *}
这只是一种快捷方式,具有相同的数字代码,但它可以使用编辑器的自动补全功能:

View File

@@ -74,7 +74,7 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持
这样做时,这些示例会成为该请求体数据内部 JSON Schema 的一部分。
不过,在<abbr title="2023-08-26">撰写本文时</abbr>,用于展示文档 UI 的 Swagger UI 并不支持显示 JSON Schema 中数据的多个示例。但请继续阅读,下面有一种变通方法。
不过,在<dfn title="2023-08-26">撰写本文时</dfn>,用于展示文档 UI 的 Swagger UI 并不支持显示 JSON Schema 中数据的多个示例。但请继续阅读,下面有一种变通方法。
### OpenAPI 特定的 `examples` { #openapi-specific-examples }

View File

@@ -20,7 +20,7 @@
把下面的示例代码复制到 `main.py`
{* ../../docs_src/security/tutorial001_an_py39.py *}
{* ../../docs_src/security/tutorial001_an_py310.py *}
## 运行 { #run-it }
@@ -132,7 +132,7 @@ OAuth2 的设计目标是让后端或 API 与负责用户认证的服务器解
创建 `OAuth2PasswordBearer` 类实例时,需要传入 `tokenUrl` 参数。该参数包含客户端(运行在用户浏览器中的前端)用来发送 `username``password` 以获取令牌的 URL。
{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *}
/// tip | 提示
@@ -170,7 +170,7 @@ oauth2_scheme(some, parameters)
现在你可以通过 `Depends``oauth2_scheme` 作为依赖传入。
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
该依赖会提供一个 `str`,赋值给*路径操作函数*的参数 `token`

View File

@@ -2,7 +2,7 @@
上一章中,(基于依赖注入系统的)安全系统向*路径操作函数*传递了 `str` 类型的 `token`
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
但这并不实用。

View File

@@ -10,7 +10,7 @@
但首先,让我们来看一些小的概念。
## 没有时间 { #in-a-hurry }
## 时间 { #in-a-hurry }
如果你不关心这些术语,而只需要*立即*通过基于用户名和密码的身份认证来增加安全性,请跳转到接下来的章节。

View File

@@ -116,7 +116,11 @@ pwdlib 也支持 bcrypt 哈希算法,但不包含遗留算法——如果需
再创建一个工具函数来进行身份验证并返回用户。
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *}
当使用一个在数据库中不存在的用户名调用 `authenticate_user` 时,我们仍然会针对一个虚拟哈希运行 `verify_password`
这可以确保无论用户名是否有效端点的响应时间大致相同从而防止可用于枚举已存在用户名的“时间攻击”timing attacks
/// note | 注意
@@ -152,7 +156,7 @@ $ openssl rand -hex 32
创建一个生成新访问令牌的工具函数。
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *}
## 更新依赖项 { #update-the-dependencies }
@@ -162,7 +166,7 @@ $ openssl rand -hex 32
如果令牌无效,立即返回一个 HTTP 错误。
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *}
## 更新 `/token` 路径操作 { #update-the-token-path-operation }
@@ -170,7 +174,7 @@ $ openssl rand -hex 32
创建一个真正的 JWT 访问令牌并返回它。
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *}
### 关于 JWT “主题” `sub` 的技术细节 { #technical-details-about-the-jwt-subject-sub }

View File

@@ -6,9 +6,9 @@
首先,使用 **FastAPI** 安全工具获取 `username``password`
OAuth2 规范要求使用**密码流**时,客户端或用户必须以表单数据形式发送 `username``password` 字段。
OAuth2 规范要求使用密码流时,客户端或用户必须以表单数据形式发送 `username``password` 字段。
并且,这两个字段必须命名为 `username``password` ,不能使用 `user-name``email` 等其它名称。
并且,这两个字段必须命名为 `username``password`,不能使用 `user-name``email` 等其它名称。
不过也不用担心,前端仍可以显示终端用户所需的名称。
@@ -74,7 +74,7 @@ OAuth2 中,**作用域**只是声明指定权限的字符串。
/// info | 信息
`OAuth2PasswordRequestForm` `OAuth2PasswordBearer` 一样,都不是 FastAPI 的特殊类。
`OAuth2PasswordRequestForm` 并不像 `OAuth2PasswordBearer` 那样是 **FastAPI** 的特殊类。
**FastAPI**`OAuth2PasswordBearer` 识别为安全方案。因此,可以通过这种方式把它添加至 OpenAPI。
@@ -200,7 +200,7 @@ UserInDB(
此处返回值为 `Bearer` 的响应头 `WWW-Authenticate` 也是规范的一部分。
任何 401**UNAUTHORIZED**HTTP错误状态码都应返回 `WWW-Authenticate` 响应头。
任何 401UNAUTHORIZEDHTTP错误状态码都应返回 `WWW-Authenticate` 响应头。
本例中,因为使用的是 Bearer Token该响应头的值应为 `Bearer`
@@ -220,7 +220,7 @@ UserInDB(
### 身份验证 { #authenticate }
点击**Authorize**按钮。
点击Authorize按钮。
使用以下凭证:
@@ -286,4 +286,4 @@ UserInDB(
唯一欠缺的是,它仍然不是真的**安全**。
下一章,介绍使用密码哈希支持库与 <abbr title="JSON Web Tokens - JSON Web 令牌">JWT</abbr> 令牌实现真正的安全机制
下一章你将看到如何使用安全的密码哈希库和 <abbr title="JSON Web Tokens - JSON Web 令牌">JWT</abbr> 令牌。

View File

@@ -216,7 +216,7 @@ $ fastapi dev main.py
它包含与 `HeroBase` 相同的字段,因此不会包括 `secret_name`
终于,我们英雄hero的身份得到了保护!🥷
终于,我们英雄的身份得到了保护!🥷
它还重新声明了 `id: int`。这样我们便与 API 客户端建立了一种**约定**,使他们始终可以期待 `id` 存在并且是一个整数 `int`(永远不会是 `None`)。

View File

@@ -7,9 +7,9 @@
* 导入 `StaticFiles`
* 将一个 `StaticFiles()` 实例“挂载”Mount到指定路径。
{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *}
/// note | 注意
/// note | 技术细节
你也可以用 `from starlette.staticfiles import StaticFiles`

View File

@@ -30,7 +30,7 @@ $ pip install httpx
为你需要检查的地方用标准的Python表达式写个简单的 `assert` 语句(重申,标准的`pytest`)。
{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *}
/// tip | 提示
@@ -76,7 +76,7 @@ $ pip install httpx
`main.py` 文件中你有一个 **FastAPI** app:
{* ../../docs_src/app_testing/app_a_py39/main.py *}
{* ../../docs_src/app_testing/app_a_py310/main.py *}
### 测试文件 { #testing-file }
@@ -92,7 +92,7 @@ $ pip install httpx
因为这文件在同一个包中,所以你可以通过相对导入从 `main` 模块(`main.py`)导入`app`对象:
{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *}
...然后测试代码和之前一样的。

View File

@@ -30,7 +30,7 @@
首先,为你的工程创建一个目录。
(指原作者 —— 译者注) 通常会在我的主目录下创建一个名为 `code` 的目录。
我通常会在我的主目录下创建一个名为 `code` 的目录。
在这个目录下,我再为每个工程创建一个目录。
@@ -53,7 +53,7 @@ $ cd awesome-project
## 创建一个虚拟环境 { #create-a-virtual-environment }
在开始一个 Python 工程的**第一时间****<abbr title="还有其他做法,此处仅作一个简单的指南">在你的工程内部</abbr>**创建一个虚拟环境。
在开始一个 Python 工程的**第一时间****<dfn title="还有其他做法,此处仅作一个简单的指南">在你的工程内部</dfn>**创建一个虚拟环境。
/// tip | 提示
@@ -316,7 +316,7 @@ $ echo "*" > .venv/.gitignore
### 直接安装包 { #install-packages-directly }
如果你急于安装,不想使用文件来声明工程的软件包依赖,可以直接安装它们。
如果你急于安装,不想使用文件来声明工程的软件包依赖,可以直接安装它们。
/// tip | 提示
@@ -412,7 +412,7 @@ Hello World
## 配置编辑器 { #configure-your-editor }
你可能会用到编辑器(即 IDE —— 译者注),请确保配置它使用与你创建的相同的虚拟环境(它可能会自动检测到),以便你可以获得自动补全和内联错误提示。
你可能会用到编辑器,请确保配置它使用与你创建的相同的虚拟环境(它可能会自动检测到),以便你可以获得自动补全和内联错误提示。
例如:
@@ -437,7 +437,7 @@ $ deactivate
</div>
这样,当你运行 `python` 时,它不会尝试从安装了软件包的虚拟环境中运行。(即,它将不再会尝试从虚拟环境中运行,也不会使用其中安装的软件包。—— 译者注)
这样,当你运行 `python` 时,它不会尝试从那个虚拟环境及其已安装的软件包中运行。
## 开始工作 { #ready-to-work }