From bd30c6b80916222ca95042fe9196e03a3ceada13 Mon Sep 17 00:00:00 2001 From: "pr-submit[bot]" <314742883+pr-submit[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2026 12:10:52 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20for=20zh?= =?UTF-8?q?=20(update-outdated)=20(#16644)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pr-submit[bot] Co-authored-by: pr-push[bot] --- .../zh/docs/advanced/advanced-python-types.md | 2 +- docs/zh/docs/advanced/async-tests.md | 2 +- docs/zh/docs/advanced/behind-a-proxy.md | 61 +++++-------------- .../docs/advanced/security/http-basic-auth.md | 22 ++++--- docs/zh/docs/advanced/templates.md | 44 ++++++++++--- docs/zh/docs/async.md | 14 ++--- docs/zh/docs/features.md | 32 +++++----- docs/zh/docs/index.md | 18 +++--- docs/zh/docs/tutorial/bigger-applications.md | 13 ++-- docs/zh/docs/tutorial/body-fields.md | 6 +- docs/zh/docs/tutorial/cookie-param-models.md | 16 +++++ .../tutorial/dependencies/sub-dependencies.md | 10 +-- docs/zh/docs/tutorial/extra-models.md | 26 ++++---- docs/zh/docs/tutorial/header-param-models.md | 20 ++++++ .../path-params-numeric-validations.md | 8 +-- docs/zh/docs/tutorial/query-param-models.md | 38 +++++++++++- .../tutorial/query-params-str-validations.md | 16 +++-- docs/zh/docs/tutorial/query-params.md | 14 +++-- docs/zh/docs/tutorial/request-form-models.md | 54 ++++++++++++++++ docs/zh/docs/tutorial/request-forms.md | 10 +++ docs/zh/docs/tutorial/response-model.md | 6 +- .../docs/tutorial/security/simple-oauth2.md | 10 +-- 22 files changed, 298 insertions(+), 144 deletions(-) diff --git a/docs/zh/docs/advanced/advanced-python-types.md b/docs/zh/docs/advanced/advanced-python-types.md index bbc9302e86..fdf87199c5 100644 --- a/docs/zh/docs/advanced/advanced-python-types.md +++ b/docs/zh/docs/advanced/advanced-python-types.md @@ -13,7 +13,7 @@ from typing import Union def say_hi(name: Union[str, None]): - print(f"Hi {name}!") + print(f"Hi {name}!") ``` `typing` 也提供了一个声明“可能为 `None`”的快捷方式:`Optional`。 diff --git a/docs/zh/docs/advanced/async-tests.md b/docs/zh/docs/advanced/async-tests.md index 5ba7c6129b..445bbcad67 100644 --- a/docs/zh/docs/advanced/async-tests.md +++ b/docs/zh/docs/advanced/async-tests.md @@ -71,7 +71,7 @@ $ uv run pytest 这相当于: ```Python -response = client.get('/') +response = client.get("/") ``` ...我们曾经通过它向 `TestClient` 发出请求。 diff --git a/docs/zh/docs/advanced/behind-a-proxy.md b/docs/zh/docs/advanced/behind-a-proxy.md index bd99497b75..a4a1d0d74a 100644 --- a/docs/zh/docs/advanced/behind-a-proxy.md +++ b/docs/zh/docs/advanced/behind-a-proxy.md @@ -8,7 +8,7 @@ 在你的应用前面的**代理**通常会在把请求转发给你的**服务器**之前,临时设置一些请求头,让服务器知道该请求是由代理**转发**的,并告知原始(公网)URL,包括域名、是否使用 HTTPS 等。 -**服务器**程序(例如通过 **FastAPI CLI** 运行的 **Uvicorn**)能够解析这些请求头,然后把这些信息传递给你的应用。 +由 `fastapi run` 启动的**服务器**能够解析这些请求头,然后把这些信息传递给你的应用。 但出于安全考虑,由于服务器并不知道自己处在受信任的代理之后,它默认不会解析这些请求头。 @@ -34,8 +34,6 @@ ```console $ uv run fastapi run --forwarded-allow-ips="*" - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -101,7 +99,7 @@ sequenceDiagram 你可能会有一个代理,为你的应用添加一个路径前缀。 -在这些情况下,你可以使用 `root_path` 来配置你的应用。 +在这些情况下,你可以使用 `fastapi run --root-path` 来配置服务器。 `root_path` 是 ASGI 规范(FastAPI 基于该规范,通过 Starlette 构建)提供的机制。 @@ -117,7 +115,7 @@ sequenceDiagram {* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} -代理会在将请求传递给应用服务器(可能是通过 FastAPI CLI 运行的 Uvicorn)之前,实时**“移除”**这个**路径前缀**,让你的应用认为它是在 `/app` 被服务,这样你就不需要更新所有代码去包含 `/api/v1` 前缀。 +代理会在将请求传递给服务器之前,实时**“移除”**这个**路径前缀**,让你的应用认为它是在 `/app` 被服务,这样你就不需要更新所有代码去包含 `/api/v1` 前缀。 到这里,一切都会像往常一样工作。 @@ -161,7 +159,7 @@ IP `0.0.0.0` 通常表示程序监听该机器/服务器上的所有可用 IP。 } ``` -在此示例中,“Proxy” 可以是 **Traefik** 之类的。服务器可以是用 **Uvicorn** 的 **FastAPI CLI** 运行你的 FastAPI 应用。 +在此示例中,“Proxy” 可以是 **Traefik** 之类的。而 `fastapi run` 会启动运行你的 FastAPI 应用的服务器。 ### 提供 `root_path` { #providing-the-root-path } @@ -171,14 +169,10 @@ IP `0.0.0.0` 通常表示程序监听该机器/服务器上的所有可用 IP。 ```console $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` -如果你使用 Hypercorn,它也有 `--root-path` 选项。 - /// note | 技术细节 ASGI 规范为这种用例定义了 `root_path`。 @@ -195,14 +189,12 @@ ASGI 规范为这种用例定义了 `root_path`。 {* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} -然后,如果你这样启动 Uvicorn: +然后,如果你这样启动服务器:
```console $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
@@ -216,30 +208,11 @@ $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 } ``` -### 在 FastAPI 应用中设置 `root_path` { #setting-the-root-path-in-the-fastapi-app } +/// warning | 已弃用的 `root_path` 参数 -或者,如果你无法提供类似 `--root-path` 的命令行选项,你可以在创建 FastAPI 应用时设置参数 `root_path`: +在 FastAPI 0.145.0 及更早版本中,也可以在 `FastAPI()` 中配置 `root_path`。此参数现已弃用,因为其行为与服务器配置不一致。请改用 `fastapi run --root-path /api/v1`。 -{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} - -把 `root_path` 传给 `FastAPI` 等同于把命令行选项 `--root-path` 传给 Uvicorn 或 Hypercorn。 - -### 关于 `root_path` { #about-root-path } - -请注意,服务器(Uvicorn)不会用这个 `root_path` 做别的事情,只会把它传给应用。 - -但是,如果你用浏览器打开 [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app),你会看到正常的响应: - -```JSON -{ - "message": "Hello World", - "root_path": "/api/v1" -} -``` - -因此,它不会期望被访问于 `http://127.0.0.1:8000/api/v1/app`。 - -Uvicorn 会期望代理以 `http://127.0.0.1:8000/app` 访问 Uvicorn,而在顶部额外添加 `/api/v1` 前缀是代理的职责。 +/// ## 关于移除路径前缀的代理 { #about-proxies-with-a-stripped-path-prefix } @@ -247,7 +220,7 @@ Uvicorn 会期望代理以 `http://127.0.0.1:8000/app` 访问 Uvicorn,而在 在很多情况下,默认是代理不会移除路径前缀。 -在这种情况下(没有移除路径前缀),代理会监听类似 `https://myawesomeapp.com`,当浏览器访问 `https://myawesomeapp.com/api/v1/app` 且你的服务器(例如 Uvicorn)监听 `http://127.0.0.1:8000` 时,代理(未移除路径前缀)会以相同路径访问 Uvicorn:`http://127.0.0.1:8000/api/v1/app`。 +在这种情况下(没有移除路径前缀),代理会监听类似 `https://myawesomeapp.com`,当浏览器访问 `https://myawesomeapp.com/api/v1/app` 且你的服务器监听 `http://127.0.0.1:8000` 时,代理(未移除路径前缀)会以相同路径访问服务器:`http://127.0.0.1:8000/api/v1/app`。 ## 使用 Traefik 进行本地测试 { #testing-locally-with-traefik } @@ -302,7 +275,7 @@ Uvicorn 会期望代理以 `http://127.0.0.1:8000/app` 访问 Uvicorn,而在 这个文件配置 Traefik 使用路径前缀 `/api/v1`。 -随后 Traefik 会把请求转发到运行在 `http://127.0.0.1:8000` 的 Uvicorn。 +随后 Traefik 会把请求转发到运行在 `http://127.0.0.1:8000` 的服务器。 现在启动 Traefik: @@ -322,15 +295,13 @@ INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml ```console $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` ### 查看响应 { #check-the-responses } -现在,如果你访问 Uvicorn 端口对应的 URL:[http://127.0.0.1:8000/app](http://127.0.0.1:8000/app),你会看到正常响应: +现在,如果你访问服务器端口对应的 URL:[http://127.0.0.1:8000/app](http://127.0.0.1:8000/app),你会看到正常响应: ```JSON { @@ -360,15 +331,15 @@ $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 当然,这里的想法是每个人都通过代理访问应用,因此带有路径前缀 `/api/v1` 的版本才是“正确”的。 -而不带路径前缀的版本(`http://127.0.0.1:8000/app`)由 Uvicorn 直接提供,仅供_代理_(Traefik)访问。 +而不带路径前缀的版本(`http://127.0.0.1:8000/app`)由服务器直接提供,仅供_代理_(Traefik)访问。 -这说明了代理(Traefik)如何使用路径前缀,以及服务器(Uvicorn)如何使用 `--root-path` 选项提供的 `root_path`。 +这说明了代理(Traefik)如何使用路径前缀,以及服务器如何使用 `--root-path` 选项提供的 `root_path`。 ### 查看文档界面 { #check-the-docs-ui } 有趣的部分来了。✨ -访问应用的“官方”方式应该是通过我们定义的带有路径前缀的代理。因此,正如预期的那样,如果你尝试不带路径前缀、直接由 Uvicorn 提供的文档界面,它将无法工作,因为它期望通过代理访问。 +访问应用的“官方”方式应该是通过我们定义的带有路径前缀的代理。因此,正如预期的那样,如果你尝试不带路径前缀、直接由服务器提供的文档界面,它将无法工作,因为它期望通过代理访问。 你可以在 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) 查看: @@ -398,7 +369,7 @@ $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 如果你传入了自定义的 `servers` 列表,并且存在 `root_path`(因为你的 API 位于代理后面),**FastAPI** 会在列表开头插入一个使用该 `root_path` 的“server”。 -例如: +例如,使用相同的 `fastapi run --root-path /api/v1` 服务器配置: {* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} @@ -455,7 +426,7 @@ OpenAPI 规范中的 `servers` 属性是可选的。 如果你不希望 **FastAPI** 包含一个使用 `root_path` 的自动服务器,可以使用参数 `root_path_in_servers=False`: -{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[8] *} 这样它就不会被包含到 OpenAPI 模式中。 diff --git a/docs/zh/docs/advanced/security/http-basic-auth.md b/docs/zh/docs/advanced/security/http-basic-auth.md index 37e4b5abcb..7772f9f66b 100644 --- a/docs/zh/docs/advanced/security/http-basic-auth.md +++ b/docs/zh/docs/advanced/security/http-basic-auth.md @@ -4,7 +4,7 @@ 在 HTTP 基础授权中,应用需要请求头包含用户名与密码。 -如果没有接收到 HTTP 基础授权,就返回 HTTP 401 `"Unauthorized"` 错误。 +如果没有接收到 HTTP 基础授权,就返回 HTTP 401 "Unauthorized" 错误。 并返回响应头 `WWW-Authenticate`,其值为 `Basic`,以及可选的 `realm` 参数。 @@ -15,7 +15,7 @@ HTTP 基础授权让浏览器显示内置的用户名与密码提示。 ## 简单的 HTTP 基础授权 { #simple-http-basic-auth } * 导入 `HTTPBasic` 与 `HTTPBasicCredentials` -* 使用 `HTTPBasic` 创建**安全方案** +* 使用 `HTTPBasic` 创建“`security` 方案” * 在*路径操作*的依赖项中使用 `security` * 返回类型为 `HTTPBasicCredentials` 的对象: * 包含发送的 `username` 与 `password` @@ -45,8 +45,10 @@ HTTP 基础授权让浏览器显示内置的用户名与密码提示。 这类似于: ```Python -if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): - # Return some error +if not (credentials.username == "stanleyjobson") or not ( + credentials.password == "swordfish" +): + # 返回某个错误 ... ``` @@ -67,9 +69,9 @@ if "johndoe" == "stanleyjobson" and "love123" == "swordfish": ... ``` -但就在 Python 比较完 `johndoe` 的第一个字母 `j` 与 `stanleyjobson` 的 `s` 时,Python 就已经知道这两个字符串不相同了,它会这么想,**没必要浪费更多时间执行剩余字母的对比计算了**。应用立刻就会返回**错误的用户或密码**。 +但就在 Python 比较完 `johndoe` 的第一个字母 `j` 与 `stanleyjobson` 的 `s` 时,它就会返回 `False`,因为 Python 已经知道这两个字符串不相同了,它会这么想,**没必要浪费更多时间执行剩余字母的对比计算了**。应用就会返回**错误的用户名或密码**。 -但接下来,攻击者继续尝试 `stanleyjobsox` 和 密码 `love123`。 +但接下来,攻击者继续尝试用户名 `stanleyjobsox` 和密码 `love123`。 应用代码会执行类似下面的操作: @@ -78,17 +80,17 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": ... ``` -此时,Python 要对比 `stanleyjobsox` 与 `stanleyjobson` 中的 `stanleyjobso`,才能知道这两个字符串不一样。因此会多花费几微秒来返回**错误的用户或密码**。 +此时,Python 要对比 `stanleyjobsox` 与 `stanleyjobson` 中的 `stanleyjobso`,才能知道这两个字符串不一样。因此会多花费几微秒来返回**错误的用户名或密码**。 #### 反应时间对攻击者的帮助 { #the-time-to-answer-helps-the-attackers } -通过服务器花费了更多微秒才发送**错误的用户或密码**响应,攻击者会知道猜对了一些内容,起码开头字母是正确的。 +通过服务器花费了更多微秒才发送**错误的用户名或密码**响应,攻击者会知道猜对了一些内容,起码开头的一些字母是正确的。 -然后,他们就可以放弃 `johndoe`,再用类似 `stanleyjobsox` 的内容进行尝试。 +然后,他们就可以再次尝试,因为他们知道正确的用户名可能更接近 `stanleyjobsox`,而不是 `johndoe`。 #### **专业**攻击 { #a-professional-attack } -当然,攻击者不用手动操作,而是编写每秒能执行成千上万次测试的攻击程序,每次都会找到更多正确字符。 +当然,攻击者不用手动操作,而是编写每秒可能执行数千甚至数百万次测试的攻击程序,每次只会多找到一个正确字符。 但是,在您的应用的**帮助**下,攻击者利用时间差,就能在几分钟或几小时内,以这种方式猜出正确的用户名和密码。 diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md index 8535c24a73..584e4e6c6d 100644 --- a/docs/zh/docs/advanced/templates.md +++ b/docs/zh/docs/advanced/templates.md @@ -1,3 +1,7 @@ +--- +render_macros: false +--- + # 模板 { #templates } 你可以在 **FastAPI** 中使用任何你想用的模板引擎。 @@ -63,14 +67,10 @@ $ uv add jinja2 在包含如下语句的 HTML 中: -{% raw %} - ```jinja Item ID: {{ id }} ``` -{% endraw %} - ...它会显示你传入的 "context" `dict` 中取得的 `id`: ```Python @@ -89,22 +89,48 @@ Item ID: 42 所以,该部分: -{% raw %} - ```jinja ``` -{% endraw %} - ...将生成一个链接,指向由*路径操作函数* `read_item(id=id)` 处理的同一个 URL。 -例如,当 ID 为 `42` 时,会渲染成: +`url_for()` 根据当前请求返回一个包含协议和主机的绝对 URL。 + +例如,如果你的应用部署在 `https://example.com`,当 ID 为 `42` 时,会渲染成: + +```html + +``` + +### 模板中的 URL 路径 { #url-paths-in-templates } + +对于指向同一站点的链接,你可以使用 `.path` 属性仅获取 URL 路径,例如,在 `templates/item_path.html` 中: + +```jinja hl_lines="4 7" +{!../../docs_src/templates/templates/item_path.html!} +``` + +将模板名称传递给 `TemplateResponse`: + +{* ../../docs_src/templates/tutorial002_py310.py ln[14:18] hl[17] *} + +使用同一个示例,条目链接会渲染成: ```html ``` +开头的 `/` 表示该路径相对于当前站点的根路径。 + +`.path` 属性不包含协议、主机、查询参数和片段。对于指向其他主机的链接,请使用完整 URL。 + +/// tip | 提示 + +如果你的应用位于代理之后,请按照[代理背后](behind-a-proxy.md)中的说明配置转发请求头和 `root_path`。 + +/// + ## 模板与静态文件 { #templates-and-static-files } 你还可以在模板内部使用 `url_for()`,例如将它与你挂载的 `name="static"` 的 `StaticFiles` 一起使用。 diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md index 8645fd6349..659f42e9da 100644 --- a/docs/zh/docs/async.md +++ b/docs/zh/docs/async.md @@ -15,7 +15,7 @@ results = await some_library() 然后,通过 `async def` 声明你的 *路径操作函数*: ```Python hl_lines="2" -@app.get('/') +@app.get("/") async def read_results(): results = await some_library() return results @@ -32,7 +32,7 @@ async def read_results(): 如果你正在使用一个第三方库和某些组件(比如:数据库、API、文件系统等)进行通信,而该第三方库不支持使用 `await`(目前大多数数据库库都是这样),这种情况你可以像平常那样使用 `def` 声明一个路径操作函数,就像这样: ```Python hl_lines="2" -@app.get('/') +@app.get("/") def results(): results = some_library() return results @@ -221,7 +221,7 @@ Python 的现代版本支持通过一种叫**“协程”**——使用 `async` --- -这将是与汉堡的类似故事。🍔 +这就是汉堡故事对应的并行版本。🍔 一种更“贴近生活”的例子,想象一家银行。 @@ -235,7 +235,7 @@ Python 的现代版本支持通过一种叫**“协程”**——使用 `async` ### 汉堡结论 { #burger-conclusion } -在“你与恋人一起吃汉堡”的这个场景中,因为有很多人在等待 🕙,使用并发系统更有意义 ⏸🔀⏯。 +在“你与恋人一起吃汉堡”的这个场景中,因为有很多等待 🕙,使用并发系统更有意义 ⏸🔀⏯。 大多数 Web 应用都是这样的。 @@ -288,7 +288,7 @@ CPU 密集型操作的常见示例是需要复杂的数学处理。 * **音频**或**图像**处理; * **计算机视觉**:一幅图像由数百万像素组成,每个像素有 3 种颜色值,处理通常需要同时对这些像素进行计算; * **机器学习**:它通常需要大量的“矩阵”和“向量”乘法。想象一个包含数字的巨大电子表格,并同时将所有数字相乘; -* **深度学习**:这是机器学习的一个子领域,同样适用。只是没有一个数字的电子表格可以相乘,而是一个庞大的数字集合,在很多情况下,你需要使用一个特殊的处理器来构建和/或使用这些模型。 +* **深度学习**:这是机器学习的一个子领域,同样适用。只是需要做乘法的不再是单个数字电子表格,而是一大批这样的表格,在很多情况下,你需要使用一个特殊的处理器来构建和/或使用这些模型。 ### 并发 + 并行: Web + 机器学习 { #concurrency-parallelism-web-machine-learning } @@ -343,7 +343,7 @@ burgers = get_burgers(2) 因此,如果你使用的库告诉你可以使用 `await` 调用它,则需要使用 `async def` 创建路径操作函数,如: ```Python hl_lines="2-3" -@app.get('/burgers') +@app.get("/burgers") async def read_burgers(): burgers = await get_burgers(2) return burgers @@ -419,7 +419,7 @@ Starlette(和 **FastAPI**)是基于 [AnyIO](https://anyio.readthedocs.io/en/ 如果你使用过另一个不以上述方式工作的异步框架,并且你习惯于用普通的 `def` 定义普通的仅计算路径操作函数,以获得微小的性能增益(大约 100 纳秒),请注意,在 FastAPI 中,效果将完全相反。在这些情况下,最好使用 `async def`,除非路径操作函数内使用执行阻塞 I/O 的代码。 -在这两种情况下,**FastAPI** [仍然会更快](index.md#performance)(或至少与之前的框架相当)。 +在这两种情况下,**FastAPI** 很可能[仍然会更快](index.md#performance)(或至少与之前的框架相当)。 ### 依赖 { #dependencies } diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index 878be5d183..8aee9eb4a7 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -17,7 +17,7 @@ * [**Swagger UI**](https://github.com/swagger-api/swagger-ui),可交互式操作,能在浏览器中直接调用和测试你的 API。 -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) +![Swagger UI 交互](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) * 另外的 API 文档:[**ReDoc**](https://github.com/Redocly/redoc)。 @@ -27,7 +27,7 @@ 全部都基于标准的 **Python 类型** 声明(感谢 Pydantic)。没有新的语法需要学习。只需要标准的现代 Python。 -如果你需要2分钟来学习如何使用 Python 类型(即使你不使用 FastAPI),看看这个简短的教程:[Python 类型](python-types.md)。 +如果你需要2分钟来复习如何使用 Python 类型(即使你不使用 FastAPI),看看这个简短的教程:[Python 类型](python-types.md)。 编写带有类型标注的标准 Python: @@ -36,6 +36,7 @@ from datetime import date from pydantic import BaseModel + # 将变量声明为 str # 并在函数内获得编辑器支持 def main(user_id: str): @@ -63,7 +64,6 @@ second_user_data = { my_second_user: User = User(**second_user_data) ``` - /// note | 注意 `**second_user_data` 意思是: @@ -86,11 +86,11 @@ my_second_user: User = User(**second_user_data) * 在 [Visual Studio Code](https://code.visualstudio.com/) 中: -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![编辑器支持](https://fastapi.tiangolo.com/img/vscode-completion.png) * 在 [PyCharm](https://www.jetbrains.com/pycharm/) 中: -![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![编辑器支持](https://fastapi.tiangolo.com/img/pycharm-completion.png) 你将能进行代码补全,这是在之前你可能曾认为不可能的事。例如,在来自请求 JSON 体(可能是嵌套的)中的键 `price`。 @@ -98,7 +98,7 @@ my_second_user: User = User(**second_user_data) ### 简洁 { #short } -任何类型都有合理的**默认值**,任何地方都有可选配置。所有的参数被微调,来满足你的需求,定义成你需要的 API。 +任何类型都有合理的**默认值**,任何地方都有可选配置。所有的参数都可以微调,来满足你的需求,定义成你需要的 API。 但是默认情况下,一切都能**“顺利工作”**。 @@ -107,7 +107,7 @@ my_second_user: User = User(**second_user_data) * 校验大部分(甚至所有?)的 Python **数据类型**,包括: * JSON 对象 (`dict`)。 * JSON 数组 (`list`) 定义成员类型。 - * 字符串 (`str`) 字段,定义最小或最大长度。 + * 字符串 (`str`) 字段,定义最小和最大长度。 * 数字 (`int`, `float`) 有最大值和最小值,等等。 * 校验更特殊的类型,比如: @@ -133,18 +133,18 @@ OpenAPI 中定义的所有安全模式,包括: 加上来自 Starlette(包括 **session cookies**)的所有安全特性。 -所有的这些都是可复用的工具和组件,可以轻松与你的系统,数据仓库,关系型以及 NoSQL 数据库等等集成。 +所有的这些都是可复用的工具和组件,可以轻松与你的系统,数据存储,关系型以及 NoSQL 数据库等等集成。 ### 依赖注入 { #dependency-injection } -FastAPI 有一个使用非常简单,但是非常强大的依赖注入系统。 +FastAPI 有一个使用非常简单,但是非常强大的依赖注入系统。 * 甚至依赖也可以有依赖,创建一个层级或者**“图”依赖**。 * 所有**自动化处理**都由框架完成。 * 所有的依赖关系都可以从请求中获取数据,并且**增加了路径操作**约束和自动文档生成。 * 即使是在依赖项中定义的*路径操作*参数也会**自动验证**。 * 支持复杂的用户身份认证系统,**数据库连接**等等。 -* **不依赖**数据库,前端等。但是和它们集成很简单。 +* **无需迁就**数据库,前端等。但是和它们集成很简单。 ### 无限制的“插件” { #unlimited-plug-ins } @@ -169,7 +169,7 @@ FastAPI 有一个使用非常简单,但是非常强大的ORMs、ODMs。 +兼容包括基于 Pydantic 的外部库,例如用于数据库的 ORM 和 ODM。 这也意味着在很多情况下,你可以将从请求中获得的相同对象**直接传到数据库**,因为所有的验证都是自动的。 反之亦然,在很多情况下,你也可以将从数据库中获取的对象**直接传到客户端**。 -通过 **FastAPI** 你可以获得所有 **Pydantic**(FastAPI 基于 Pydantic 做了所有的数据处理): +通过 **FastAPI** 你可以获得所有 **Pydantic** 的特性(FastAPI 基于 Pydantic 做了所有的数据处理): * **不烧脑**: - * 没有新的模式定义 micro-language 需要学习。 + * 没有新的模式定义微型语言需要学习。 * 如果你知道 Python 类型,你就知道如何使用 Pydantic。 -* 和你 **IDE/linter/brain** 适配: +* 和你 **IDE/linter/大脑** 适配: * 因为 pydantic 数据结构仅仅是你定义的类的实例;自动补全,linting,mypy 以及你的直觉应该可以和你验证的数据一起正常工作。 * 验证**复杂结构**: * 使用分层的 Pydantic 模型,Python `typing` 的 `List` 和 `Dict` 等等。 * 验证器使我们能够简单清楚地将复杂的数据模式定义、检查并记录为 JSON Schema。 * 你可以拥有深度**嵌套的 JSON** 对象并对它们进行验证和注释。 * **可扩展**: - * Pydantic 允许定义自定义数据类型或者你可以用验证器装饰器对被装饰的模型上的方法扩展验证。 + * Pydantic 允许定义自定义数据类型,或者你可以通过模型上使用验证器装饰器装饰的方法扩展验证。 * 100% 测试覆盖率。 diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index 74ca286391..d331fba8b2 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -105,7 +105,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框