From 263766548dfe75d38a67f578b0a72f536b3e2092 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:26 +0800
Subject: [PATCH 001/163] New translations additional-responses.md (Chinese
Simplified)
---
docs/zh/docs/advanced/additional-responses.md | 240 ++++++++++++++++++
1 file changed, 240 insertions(+)
create mode 100644 docs/zh/docs/advanced/additional-responses.md
diff --git a/docs/zh/docs/advanced/additional-responses.md b/docs/zh/docs/advanced/additional-responses.md
new file mode 100644
index 0000000000000..c76a92f238c37
--- /dev/null
+++ b/docs/zh/docs/advanced/additional-responses.md
@@ -0,0 +1,240 @@
+# Additional Responses in OpenAPI
+
+!!! warning
+ This is a rather advanced topic.
+
+ If you are starting with **FastAPI**, you might not need this.
+
+You can declare additional responses, with additional status codes, media types, descriptions, etc.
+
+Those additional responses will be included in the OpenAPI schema, so they will also appear in the API docs.
+
+But for those additional responses you have to make sure you return a `Response` like `JSONResponse` directly, with your status code and content.
+
+## Additional Response with `model`
+
+You can pass to your *path operation decorators* a parameter `responses`.
+
+It receives a `dict`, the keys are status codes for each response, like `200`, and the values are other `dict`s with the information for each of them.
+
+Each of those response `dict`s can have a key `model`, containing a Pydantic model, just like `response_model`.
+
+**FastAPI** will take that model, generate its JSON Schema and include it in the correct place in OpenAPI.
+
+For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write:
+
+```Python hl_lines="18 22"
+{!../../../docs_src/additional_responses/tutorial001.py!}
+```
+
+!!! note
+ Have in mind that you have to return the `JSONResponse` directly.
+
+!!! info
+ The `model` key is not part of OpenAPI.
+
+ **FastAPI** will take the Pydantic model from there, generate the `JSON Schema`, and put it in the correct place.
+
+ The correct place is:
+
+ * In the key `content`, that has as value another JSON object (`dict`) that contains:
+ * A key with the media type, e.g. `application/json`, that contains as value another JSON object, that contains:
+ * A key `schema`, that has as the value the JSON Schema from the model, here's the correct place.
+ * **FastAPI** adds a reference here to the global JSON Schemas in another place in your OpenAPI instead of including it directly. This way, other applications and clients can use those JSON Schemas directly, provide better code generation tools, etc.
+
+The generated responses in the OpenAPI for this *path operation* will be:
+
+```JSON hl_lines="3-12"
+{
+ "responses": {
+ "404": {
+ "description": "Additional Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ }
+ }
+ },
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Item"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/HTTPValidationError"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+The schemas are referenced to another place inside the OpenAPI schema:
+
+```JSON hl_lines="4-16"
+{
+ "components": {
+ "schemas": {
+ "Message": {
+ "title": "Message",
+ "required": [
+ "message"
+ ],
+ "type": "object",
+ "properties": {
+ "message": {
+ "title": "Message",
+ "type": "string"
+ }
+ }
+ },
+ "Item": {
+ "title": "Item",
+ "required": [
+ "id",
+ "value"
+ ],
+ "type": "object",
+ "properties": {
+ "id": {
+ "title": "Id",
+ "type": "string"
+ },
+ "value": {
+ "title": "Value",
+ "type": "string"
+ }
+ }
+ },
+ "ValidationError": {
+ "title": "ValidationError",
+ "required": [
+ "loc",
+ "msg",
+ "type"
+ ],
+ "type": "object",
+ "properties": {
+ "loc": {
+ "title": "Location",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "msg": {
+ "title": "Message",
+ "type": "string"
+ },
+ "type": {
+ "title": "Error Type",
+ "type": "string"
+ }
+ }
+ },
+ "HTTPValidationError": {
+ "title": "HTTPValidationError",
+ "type": "object",
+ "properties": {
+ "detail": {
+ "title": "Detail",
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+## Additional media types for the main response
+
+You can use this same `responses` parameter to add different media types for the same main response.
+
+For example, you can add an additional media type of `image/png`, declaring that your *path operation* can return a JSON object (with media type `application/json`) or a PNG image:
+
+```Python hl_lines="19-24 28"
+{!../../../docs_src/additional_responses/tutorial002.py!}
+```
+
+!!! note
+ Notice that you have to return the image using a `FileResponse` directly.
+
+!!! info
+ Unless you specify a different media type explicitly in your `responses` parameter, FastAPI will assume the response has the same media type as the main response class (default `application/json`).
+
+ But if you have specified a custom response class with `None` as its media type, FastAPI will use `application/json` for any additional response that has an associated model.
+
+## Combining information
+
+You can also combine response information from multiple places, including the `response_model`, `status_code`, and `responses` parameters.
+
+You can declare a `response_model`, using the default status code `200` (or a custom one if you need), and then declare additional information for that same response in `responses`, directly in the OpenAPI schema.
+
+**FastAPI** will keep the additional information from `responses`, and combine it with the JSON Schema from your model.
+
+For example, you can declare a response with a status code `404` that uses a Pydantic model and has a custom `description`.
+
+And a response with a status code `200` that uses your `response_model`, but includes a custom `example`:
+
+```Python hl_lines="20-31"
+{!../../../docs_src/additional_responses/tutorial003.py!}
+```
+
+It will all be combined and included in your OpenAPI, and shown in the API docs:
+
+
+
+## Combine predefined responses and custom ones
+
+You might want to have some predefined responses that apply to many *path operations*, but you want to combine them with custom responses needed by each *path operation*.
+
+For those cases, you can use the Python technique of "unpacking" a `dict` with `**dict_to_unpack`:
+
+```Python
+old_dict = {
+ "old key": "old value",
+ "second old key": "second old value",
+}
+new_dict = {**old_dict, "new key": "new value"}
+```
+
+Here, `new_dict` will contain all the key-value pairs from `old_dict` plus the new key-value pair:
+
+```Python
+{
+ "old key": "old value",
+ "second old key": "second old value",
+ "new key": "new value",
+}
+```
+
+You can use that technique to re-use some predefined responses in your *path operations* and combine them with additional custom ones.
+
+For example:
+
+```Python hl_lines="13-17 26"
+{!../../../docs_src/additional_responses/tutorial004.py!}
+```
+
+## More information about OpenAPI responses
+
+To see what exactly you can include in the responses, you can check these sections in the OpenAPI specification:
+
+* OpenAPI Responses Object, it includes the `Response Object`.
+* OpenAPI Response Object, you can include anything from this directly in each response inside your `responses` parameter. Including `description`, `headers`, `content` (inside of this is that you declare different media types and JSON Schemas), and `links`.
From fc7c5bdf7ad5b69a073441aee0539d3b9c570157 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:27 +0800
Subject: [PATCH 002/163] New translations additional-status-codes.md (Chinese
Simplified)
---
.../docs/advanced/additional-status-codes.md | 74 +++++++++++++------
1 file changed, 53 insertions(+), 21 deletions(-)
diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md
index 54ec9775b6204..2bccdbb402b2b 100644
--- a/docs/zh/docs/advanced/additional-status-codes.md
+++ b/docs/zh/docs/advanced/additional-status-codes.md
@@ -1,37 +1,69 @@
-# 额外的状态码
+# Additional Status Codes
-**FastAPI** 默认使用 `JSONResponse` 返回一个响应,将你的 *路径操作* 中的返回内容放到该 `JSONResponse` 中。
+By default, **FastAPI** will return the responses using a `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`.
-**FastAPI** 会自动使用默认的状态码或者使用你在 *路径操作* 中设置的状态码。
+It will use the default status code or the one you set in your *path operation*.
-## 额外的状态码
+## Additional status codes
-如果你想要返回主要状态码之外的状态码,你可以通过直接返回一个 `Response` 来实现,比如 `JSONResponse`,然后直接设置额外的状态码。
+If you want to return additional status codes apart from the main one, you can do that by returning a `Response` directly, like a `JSONResponse`, and set the additional status code directly.
-例如,假设你想有一个 *路径操作* 能够更新条目,并且更新成功时返回 200 「成功」 的 HTTP 状态码。
+For example, let's say that you want to have a *path operation* that allows to update items, and returns HTTP status codes of 200 "OK" when successful.
-但是你也希望它能够接受新的条目。并且当这些条目不存在时,会自动创建并返回 201 「创建」的 HTTP 状态码。
+But you also want it to accept new items. And when the items didn't exist before, it creates them, and returns an HTTP status code of 201 "Created".
-要实现它,导入 `JSONResponse`,然后在其中直接返回你的内容,并将 `status_code` 设置为为你要的值。
+To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
-```Python hl_lines="4 25"
-{!../../../docs_src/additional_status_codes/tutorial001.py!}
-```
+=== "Python 3.10+"
-!!! warning "警告"
- 当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。
+ ```Python hl_lines="4 25"
+ {!> ../../../docs_src/additional_status_codes/tutorial001_an_py310.py!}
+ ```
- FastAPI 不会用模型等对该响应进行序列化。
+=== "Python 3.9+"
- 确保其中有你想要的数据,且返回的值为合法的 JSON(如果你使用 `JSONResponse` 的话)。
+ ```Python hl_lines="4 25"
+ {!> ../../../docs_src/additional_status_codes/tutorial001_an_py39.py!}
+ ```
-!!! note "技术细节"
- 你也可以使用 `from starlette.responses import JSONResponse`。
+=== "Python 3.6+"
- 出于方便,**FastAPI** 为开发者提供同 `starlette.responses` 一样的 `fastapi.responses`。但是大多数可用的响应都是直接来自 Starlette。`status` 也是一样。
+ ```Python hl_lines="4 26"
+ {!> ../../../docs_src/additional_status_codes/tutorial001_an.py!}
+ ```
-## OpenAPI 和 API 文档
+=== "Python 3.10+ non-Annotated"
-如果你直接返回额外的状态码和响应,它们不会包含在 OpenAPI 方案(API 文档)中,因为 FastAPI 没办法预先知道你要返回什么。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-但是你可以使用 [额外的响应](additional-responses.md){.internal-link target=_blank} 在代码中记录这些内容。
+ ```Python hl_lines="2 23"
+ {!> ../../../docs_src/additional_status_codes/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4 25"
+ {!> ../../../docs_src/additional_status_codes/tutorial001.py!}
+ ```
+
+!!! warning
+ When you return a `Response` directly, like in the example above, it will be returned directly.
+
+ It won't be serialized with a model, etc.
+
+ Make sure it has the data you want it to have, and that the values are valid JSON (if you are using `JSONResponse`).
+
+!!! note "Technical Details"
+ You could also use `from starlette.responses import JSONResponse`.
+
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `status`.
+
+## OpenAPI and API docs
+
+If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know beforehand what you are going to return.
+
+But you can document that in your code, using: [Additional Responses](additional-responses.md){.internal-link target=_blank}.
From 98209f5abd9b3ce5bbd1ac6628b34d36bdb8fa7e Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:28 +0800
Subject: [PATCH 003/163] New translations advanced-dependencies.md (Chinese
Simplified)
---
.../zh/docs/advanced/advanced-dependencies.md | 138 ++++++++++++++++++
1 file changed, 138 insertions(+)
create mode 100644 docs/zh/docs/advanced/advanced-dependencies.md
diff --git a/docs/zh/docs/advanced/advanced-dependencies.md b/docs/zh/docs/advanced/advanced-dependencies.md
new file mode 100644
index 0000000000000..845713c30a966
--- /dev/null
+++ b/docs/zh/docs/advanced/advanced-dependencies.md
@@ -0,0 +1,138 @@
+# Advanced Dependencies
+
+## Parameterized dependencies
+
+All the dependencies we have seen are a fixed function or class.
+
+But there could be cases where you want to be able to set parameters on the dependency, without having to declare many different functions or classes.
+
+Let's imagine that we want to have a dependency that checks if the query parameter `q` contains some fixed content.
+
+But we want to be able to parameterize that fixed content.
+
+## A "callable" instance
+
+In Python there's a way to make an instance of a class a "callable".
+
+Not the class itself (which is already a callable), but an instance of that class.
+
+To do that, we declare a method `__call__`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/dependencies/tutorial011_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/dependencies/tutorial011.py!}
+ ```
+
+In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later.
+
+## Parameterize the instance
+
+And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/dependencies/tutorial011_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/dependencies/tutorial011.py!}
+ ```
+
+In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code.
+
+## Create an instance
+
+We could create an instance of this class with:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial011_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/dependencies/tutorial011.py!}
+ ```
+
+And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`.
+
+## Use the instance as a dependency
+
+Then, we could use this `checker` in a `Depends(checker)`, instead of `Depends(FixedContentQueryChecker)`, because the dependency is the instance, `checker`, not the class itself.
+
+And when solving the dependency, **FastAPI** will call this `checker` like:
+
+```Python
+checker(q="somequery")
+```
+
+...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/dependencies/tutorial011_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/dependencies/tutorial011.py!}
+ ```
+
+!!! tip
+ All this might seem contrived. And it might not be very clear how is it useful yet.
+
+ These examples are intentionally simple, but show how it all works.
+
+ In the chapters about security, there are utility functions that are implemented in this same way.
+
+ If you understood all this, you already know how those utility tools for security work underneath.
From b890d056a623274fe1ff3d0179d1c916c2ce6ae9 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:29 +0800
Subject: [PATCH 004/163] New translations async-sql-databases.md (Chinese
Simplified)
---
docs/zh/docs/advanced/async-sql-databases.md | 169 +++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 docs/zh/docs/advanced/async-sql-databases.md
diff --git a/docs/zh/docs/advanced/async-sql-databases.md b/docs/zh/docs/advanced/async-sql-databases.md
new file mode 100644
index 0000000000000..6a85f2237ea1f
--- /dev/null
+++ b/docs/zh/docs/advanced/async-sql-databases.md
@@ -0,0 +1,169 @@
+# Async SQL (Relational) Databases
+
+!!! info
+ These docs are about to be updated. 🎉
+
+ The current version assumes Pydantic v1.
+
+ The new docs will include Pydantic v2 and will use SQLModel once it is updated to use Pydantic v2 as well.
+
+You can also use `encode/databases` with **FastAPI** to connect to databases using `async` and `await`.
+
+It is compatible with:
+
+* PostgreSQL
+* MySQL
+* SQLite
+
+In this example, we'll use **SQLite**, because it uses a single file and Python has integrated support. So, you can copy this example and run it as is.
+
+Later, for your production application, you might want to use a database server like **PostgreSQL**.
+
+!!! tip
+ You could adopt ideas from the section about SQLAlchemy ORM ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}), like using utility functions to perform operations in the database, independent of your **FastAPI** code.
+
+ This section doesn't apply those ideas, to be equivalent to the counterpart in Starlette.
+
+## Import and set up `SQLAlchemy`
+
+* Import `SQLAlchemy`.
+* Create a `metadata` object.
+* Create a table `notes` using the `metadata` object.
+
+```Python hl_lines="4 14 16-22"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! tip
+ Notice that all this code is pure SQLAlchemy Core.
+
+ `databases` is not doing anything here yet.
+
+## Import and set up `databases`
+
+* Import `databases`.
+* Create a `DATABASE_URL`.
+* Create a `database` object.
+
+```Python hl_lines="3 9 12"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! tip
+ If you were connecting to a different database (e.g. PostgreSQL), you would need to change the `DATABASE_URL`.
+
+## Create the tables
+
+In this case, we are creating the tables in the same Python file, but in production, you would probably want to create them with Alembic, integrated with migrations, etc.
+
+Here, this section would run directly, right before starting your **FastAPI** application.
+
+* Create an `engine`.
+* Create all the tables from the `metadata` object.
+
+```Python hl_lines="25-28"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+## Create models
+
+Create Pydantic models for:
+
+* Notes to be created (`NoteIn`).
+* Notes to be returned (`Note`).
+
+```Python hl_lines="31-33 36-39"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+By creating these Pydantic models, the input data will be validated, serialized (converted), and annotated (documented).
+
+So, you will be able to see it all in the interactive API docs.
+
+## Connect and disconnect
+
+* Create your `FastAPI` application.
+* Create event handlers to connect and disconnect from the database.
+
+```Python hl_lines="42 45-47 50-52"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+## Read notes
+
+Create the *path operation function* to read notes:
+
+```Python hl_lines="55-58"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! Note
+ Notice that as we communicate with the database using `await`, the *path operation function* is declared with `async`.
+
+### Notice the `response_model=List[Note]`
+
+It uses `typing.List`.
+
+That documents (and validates, serializes, filters) the output data, as a `list` of `Note`s.
+
+## Create notes
+
+Create the *path operation function* to create notes:
+
+```Python hl_lines="61-65"
+{!../../../docs_src/async_sql_databases/tutorial001.py!}
+```
+
+!!! Note
+ Notice that as we communicate with the database using `await`, the *path operation function* is declared with `async`.
+
+### About `{**note.dict(), "id": last_record_id}`
+
+`note` is a Pydantic `Note` object.
+
+`note.dict()` returns a `dict` with its data, something like:
+
+```Python
+{
+ "text": "Some note",
+ "completed": False,
+}
+```
+
+but it doesn't have the `id` field.
+
+So we create a new `dict`, that contains the key-value pairs from `note.dict()` with:
+
+```Python
+{**note.dict()}
+```
+
+`**note.dict()` "unpacks" the key value pairs directly, so, `{**note.dict()}` would be, more or less, a copy of `note.dict()`.
+
+And then, we extend that copy `dict`, adding another key-value pair: `"id": last_record_id`:
+
+```Python
+{**note.dict(), "id": last_record_id}
+```
+
+So, the final result returned would be something like:
+
+```Python
+{
+ "id": 1,
+ "text": "Some note",
+ "completed": False,
+}
+```
+
+## Check it
+
+You can copy this code as is, and see the docs at http://127.0.0.1:8000/docs.
+
+There you can see all your API documented and interact with it:
+
+
+
+## More info
+
+You can read more about `encode/databases` at its GitHub page.
From 6369a0e4b93af378edf755b32e668cf9056886be Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:30 +0800
Subject: [PATCH 005/163] New translations async-tests.md (Chinese Simplified)
---
docs/zh/docs/advanced/async-tests.md | 92 ++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 docs/zh/docs/advanced/async-tests.md
diff --git a/docs/zh/docs/advanced/async-tests.md b/docs/zh/docs/advanced/async-tests.md
new file mode 100644
index 0000000000000..9b39d70fca6a8
--- /dev/null
+++ b/docs/zh/docs/advanced/async-tests.md
@@ -0,0 +1,92 @@
+# Async Tests
+
+You have already seen how to test your **FastAPI** applications using the provided `TestClient`. Up to now, you have only seen how to write synchronous tests, without using `async` functions.
+
+Being able to use asynchronous functions in your tests could be useful, for example, when you're querying your database asynchronously. Imagine you want to test sending requests to your FastAPI application and then verify that your backend successfully wrote the correct data in the database, while using an async database library.
+
+Let's look at how we can make that work.
+
+## pytest.mark.anyio
+
+If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. AnyIO provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously.
+
+## HTTPX
+
+Even if your **FastAPI** application uses normal `def` functions instead of `async def`, it is still an `async` application underneath.
+
+The `TestClient` does some magic inside to call the asynchronous FastAPI application in your normal `def` test functions, using standard pytest. But that magic doesn't work anymore when we're using it inside asynchronous functions. By running our tests asynchronously, we can no longer use the `TestClient` inside our test functions.
+
+The `TestClient` is based on HTTPX, and luckily, we can use it directly to test the API.
+
+## Example
+
+For a simple example, let's consider a file structure similar to the one described in [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} and [Testing](../tutorial/testing.md){.internal-link target=_blank}:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+│ └── test_main.py
+```
+
+The file `main.py` would have:
+
+```Python
+{!../../../docs_src/async_tests/main.py!}
+```
+
+The file `test_main.py` would have the tests for `main.py`, it could look like this now:
+
+```Python
+{!../../../docs_src/async_tests/test_main.py!}
+```
+
+## Run it
+
+You can run your tests as usual via:
+
+
+
+But if we access the docs UI at the "official" URL using the proxy with port `9999`, at `/api/v1/docs`, it works correctly! 🎉
+
+You can check it at http://127.0.0.1:9999/api/v1/docs:
+
+
+
+Right as we wanted it. ✔️
+
+This is because FastAPI uses this `root_path` to create the default `server` in OpenAPI with the URL provided by `root_path`.
+
+## Additional servers
+
+!!! warning
+ This is a more advanced use case. Feel free to skip it.
+
+By default, **FastAPI** will create a `server` in the OpenAPI schema with the URL for the `root_path`.
+
+But you can also provide other alternative `servers`, for example if you want *the same* docs UI to interact with a staging and production environments.
+
+If you pass a custom list of `servers` and there's a `root_path` (because your API lives behind a proxy), **FastAPI** will insert a "server" with this `root_path` at the beginning of the list.
+
+For example:
+
+```Python hl_lines="4-7"
+{!../../../docs_src/behind_a_proxy/tutorial003.py!}
+```
+
+Will generate an OpenAPI schema like:
+
+```JSON hl_lines="5-7"
+{
+ "openapi": "3.1.0",
+ // More stuff here
+ "servers": [
+ {
+ "url": "/api/v1"
+ },
+ {
+ "url": "https://stag.example.com",
+ "description": "Staging environment"
+ },
+ {
+ "url": "https://prod.example.com",
+ "description": "Production environment"
+ }
+ ],
+ "paths": {
+ // More stuff here
+ }
+}
+```
+
+!!! tip
+ Notice the auto-generated server with a `url` value of `/api/v1`, taken from the `root_path`.
+
+In the docs UI at http://127.0.0.1:9999/api/v1/docs it would look like:
+
+
+
+!!! tip
+ The docs UI will interact with the server that you select.
+
+### Disable automatic server from `root_path`
+
+If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`:
+
+```Python hl_lines="9"
+{!../../../docs_src/behind_a_proxy/tutorial004.py!}
+```
+
+and then it won't include it in the OpenAPI schema.
+
+## Mounting a sub-application
+
+If you need to mount a sub-application (as described in [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}) while also using a proxy with `root_path`, you can do it normally, as you would expect.
+
+FastAPI will internally use the `root_path` smartly, so it will just work. ✨
From 896bb02a1191f9a6cad2b68222ace9cac8220273 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:31 +0800
Subject: [PATCH 007/163] New translations conditional-openapi.md (Chinese
Simplified)
---
docs/zh/docs/advanced/conditional-openapi.md | 58 ++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 docs/zh/docs/advanced/conditional-openapi.md
diff --git a/docs/zh/docs/advanced/conditional-openapi.md b/docs/zh/docs/advanced/conditional-openapi.md
new file mode 100644
index 0000000000000..add16fbec519e
--- /dev/null
+++ b/docs/zh/docs/advanced/conditional-openapi.md
@@ -0,0 +1,58 @@
+# Conditional OpenAPI
+
+If you needed to, you could use settings and environment variables to configure OpenAPI conditionally depending on the environment, and even disable it entirely.
+
+## About security, APIs, and docs
+
+Hiding your documentation user interfaces in production *shouldn't* be the way to protect your API.
+
+That doesn't add any extra security to your API, the *path operations* will still be available where they are.
+
+If there's a security flaw in your code, it will still exist.
+
+Hiding the documentation just makes it more difficult to understand how to interact with your API, and could make it more difficult for you to debug it in production. It could be considered simply a form of Security through obscurity.
+
+If you want to secure your API, there are several better things you can do, for example:
+
+* Make sure you have well defined Pydantic models for your request bodies and responses.
+* Configure any required permissions and roles using dependencies.
+* Never store plaintext passwords, only password hashes.
+* Implement and use well-known cryptographic tools, like Passlib and JWT tokens, etc.
+* Add more granular permission controls with OAuth2 scopes where needed.
+* ...etc.
+
+Nevertheless, you might have a very specific use case where you really need to disable the API docs for some environment (e.g. for production) or depending on configurations from environment variables.
+
+## Conditional OpenAPI from settings and env vars
+
+You can easily use the same Pydantic settings to configure your generated OpenAPI and the docs UIs.
+
+For example:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/conditional_openapi/tutorial001.py!}
+```
+
+Here we declare the setting `openapi_url` with the same default of `"/openapi.json"`.
+
+And then we use it when creating the `FastAPI` app.
+
+Then you could disable OpenAPI (including the UI docs) by setting the environment variable `OPENAPI_URL` to the empty string, like:
+
+
+
-## 可用响应
+## Available responses
-这里有一些可用的响应。
+Here are some of the available responses.
-要记得你可以使用 `Response` 来返回任何其他东西,甚至创建一个自定义的子类。
+Have in mind that you can use `Response` to return anything else, or even create a custom sub-class.
-!!! note "技术细节"
- 你也可以使用 `from starlette.responses import HTMLResponse`。
+!!! note "Technical Details"
+ You could also use `from starlette.responses import HTMLResponse`.
- **FastAPI** 提供了同 `fastapi.responses` 相同的 `starlette.responses` 只是为了方便开发者。但大多数可用的响应都直接来自 Starlette。
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
### `Response`
-其他全部的响应都继承自主类 `Response`。
-
-你可以直接返回它。
+The main `Response` class, all the other responses inherit from it.
-`Response` 类接受如下参数:
+You can return it directly.
-* `content` - 一个 `str` 或者 `bytes`。
-* `status_code` - 一个 `int` 类型的 HTTP 状态码。
-* `headers` - 一个由字符串组成的 `dict`。
-* `media_type` - 一个给出媒体类型的 `str`,比如 `"text/html"`。
+It accepts the following parameters:
-FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它还将包含一个基于 media_type 的 Content-Type 头,并为文本类型附加一个字符集。
+* `content` - A `str` or `bytes`.
+* `status_code` - An `int` HTTP status code.
+* `headers` - A `dict` of strings.
+* `media_type` - A `str` giving the media type. E.g. `"text/html"`.
+FastAPI (actually Starlette) will automatically include a Content-Length header. It will also include a Content-Type header, based on the media_type and appending a charset for text types.
```Python hl_lines="1 18"
{!../../../docs_src/response_directly/tutorial002.py!}
@@ -126,11 +129,11 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它
### `HTMLResponse`
-如上文所述,接受文本或字节并返回 HTML 响应。
+Takes some text or bytes and returns an HTML response, as you read above.
### `PlainTextResponse`
-接受文本或字节并返回纯文本响应。
+Takes some text or bytes and returns an plain text response.
```Python hl_lines="2 7 9"
{!../../../docs_src/custom_response/tutorial005.py!}
@@ -138,75 +141,160 @@ FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。它
### `JSONResponse`
-接受数据并返回一个 `application/json` 编码的响应。
+Takes some data and returns an `application/json` encoded response.
-如上文所述,这是 **FastAPI** 中使用的默认响应。
+This is the default response used in **FastAPI**, as you read above.
### `ORJSONResponse`
-如上文所述,`ORJSONResponse` 是一个使用 `orjson` 的快速的可选 JSON 响应。
-
+A fast alternative JSON response using `orjson`, as you read above.
### `UJSONResponse`
-`UJSONResponse` 是一个使用 `ujson` 的可选 JSON 响应。
+An alternative JSON response using `ujson`.
-!!! warning "警告"
- 在处理某些边缘情况时,`ujson` 不如 Python 的内置实现那么谨慎。
+!!! warning
+ `ujson` is less careful than Python's built-in implementation in how it handles some edge-cases.
-```Python hl_lines="2 7"
+```Python hl_lines="2 7"
{!../../../docs_src/custom_response/tutorial001.py!}
```
-!!! tip "小贴士"
- `ORJSONResponse` 可能是一个更快的选择。
+!!! tip
+ It's possible that `ORJSONResponse` might be a faster alternative.
### `RedirectResponse`
-返回 HTTP 重定向。默认情况下使用 307 状态代码(临时重定向)。
+Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default.
+
+You can return a `RedirectResponse` directly:
```Python hl_lines="2 9"
{!../../../docs_src/custom_response/tutorial006.py!}
```
+---
+
+Or you can use it in the `response_class` parameter:
+
+
+```Python hl_lines="2 7 9"
+{!../../../docs_src/custom_response/tutorial006b.py!}
+```
+
+If you do that, then you can return the URL directly from your *path operation* function.
+
+In this case, the `status_code` used will be the default one for the `RedirectResponse`, which is `307`.
+
+---
+
+You can also use the `status_code` parameter combined with the `response_class` parameter:
+
+```Python hl_lines="2 7 9"
+{!../../../docs_src/custom_response/tutorial006c.py!}
+```
+
### `StreamingResponse`
-采用异步生成器或普通生成器/迭代器,然后流式传输响应主体。
+Takes an async generator or a normal generator/iterator and streams the response body.
```Python hl_lines="2 14"
{!../../../docs_src/custom_response/tutorial007.py!}
```
-#### 对类似文件的对象使用 `StreamingResponse`
+#### Using `StreamingResponse` with file-like objects
+
+If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object.
-如果您有类似文件的对象(例如,由 `open()` 返回的对象),则可以在 `StreamingResponse` 中将其返回。
+That way, you don't have to read it all first in memory, and you can pass that generator function to the `StreamingResponse`, and return it.
-包括许多与云存储,视频处理等交互的库。
+This includes many libraries to interact with cloud storage, video processing, and others.
-```Python hl_lines="2 10-12 14"
+```{ .python .annotate hl_lines="2 10-12 14" }
{!../../../docs_src/custom_response/tutorial008.py!}
```
-!!! tip "小贴士"
- 注意在这里,因为我们使用的是不支持 `async` 和 `await` 的标准 `open()`,我们使用普通的 `def` 声明了路径操作。
+1. This is the generator function. It's a "generator function" because it contains `yield` statements inside.
+2. By using a `with` block, we make sure that the file-like object is closed after the generator function is done. So, after it finishes sending the response.
+3. This `yield from` tells the function to iterate over that thing named `file_like`. And then, for each part iterated, yield that part as coming from this generator function.
+
+ So, it is a generator function that transfers the "generating" work to something else internally.
+
+ By doing it this way, we can put it in a `with` block, and that way, ensure that it is closed after finishing.
+
+!!! tip
+ Notice that here as we are using standard `open()` that doesn't support `async` and `await`, we declare the path operation with normal `def`.
### `FileResponse`
-异步传输文件作为响应。
+Asynchronously streams a file as the response.
-与其他响应类型相比,接受不同的参数集进行实例化:
+Takes a different set of arguments to instantiate than the other response types:
-* `path` - 要流式传输的文件的文件路径。
-* `headers` - 任何自定义响应头,传入字典类型。
-* `media_type` - 给出媒体类型的字符串。如果未设置,则文件名或路径将用于推断媒体类型。
-* `filename` - 如果给出,它将包含在响应的 `Content-Disposition` 中。
+* `path` - The filepath to the file to stream.
+* `headers` - Any custom headers to include, as a dictionary.
+* `media_type` - A string giving the media type. If unset, the filename or path will be used to infer a media type.
+* `filename` - If set, this will be included in the response `Content-Disposition`.
-文件响应将包含适当的 `Content-Length`,`Last-Modified` 和 `ETag` 的响应头。
+File responses will include appropriate `Content-Length`, `Last-Modified` and `ETag` headers.
```Python hl_lines="2 10"
{!../../../docs_src/custom_response/tutorial009.py!}
```
-## 额外文档
+You can also use the `response_class` parameter:
+
+```Python hl_lines="2 8 10"
+{!../../../docs_src/custom_response/tutorial009b.py!}
+```
+
+In this case, you can return the file path directly from your *path operation* function.
+
+## Custom response class
+
+You can create your own custom response class, inheriting from `Response` and using it.
+
+For example, let's say that you want to use `orjson`, but with some custom settings not used in the included `ORJSONResponse` class.
+
+Let's say you want it to return indented and formatted JSON, so you want to use the orjson option `orjson.OPT_INDENT_2`.
+
+You could create a `CustomORJSONResponse`. The main thing you have to do is create a `Response.render(content)` method that returns the content as `bytes`:
+
+```Python hl_lines="9-14 17"
+{!../../../docs_src/custom_response/tutorial009c.py!}
+```
+
+Now instead of returning:
+
+```json
+{"message": "Hello World"}
+```
+
+...this response will return:
+
+```json
+{
+ "message": "Hello World"
+}
+```
+
+Of course, you will probably find much better ways to take advantage of this than formatting JSON. 😉
+
+## Default response class
+
+When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
+
+The parameter that defines this is `default_response_class`.
+
+In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
+
+```Python hl_lines="2 4"
+{!../../../docs_src/custom_response/tutorial010.py!}
+```
+
+!!! tip
+ You can still override `response_class` in *path operations* as before.
+
+## Additional documentation
-您还可以使用 `response` 在 OpenAPI 中声明媒体类型和许多其他详细信息:[OpenAPI 中的额外文档](additional-responses.md){.internal-link target=_blank}。
+You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
From faf37886bd57e19da0ce5a191959ebf7ab60ed46 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:35 +0800
Subject: [PATCH 010/163] New translations dataclasses.md (Chinese Simplified)
---
docs/zh/docs/advanced/dataclasses.md | 98 ++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)
create mode 100644 docs/zh/docs/advanced/dataclasses.md
diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md
new file mode 100644
index 0000000000000..fe6b740aa391a
--- /dev/null
+++ b/docs/zh/docs/advanced/dataclasses.md
@@ -0,0 +1,98 @@
+# Using Dataclasses
+
+FastAPI is built on top of **Pydantic**, and I have been showing you how to use Pydantic models to declare requests and responses.
+
+But FastAPI also supports using `dataclasses` the same way:
+
+```Python hl_lines="1 7-12 19-20"
+{!../../../docs_src/dataclasses/tutorial001.py!}
+```
+
+This is still supported thanks to **Pydantic**, as it has internal support for `dataclasses`.
+
+So, even with the code above that doesn't use Pydantic explicitly, FastAPI is using Pydantic to convert those standard dataclasses to Pydantic's own flavor of dataclasses.
+
+And of course, it supports the same:
+
+* data validation
+* data serialization
+* data documentation, etc.
+
+This works the same way as with Pydantic models. And it is actually achieved in the same way underneath, using Pydantic.
+
+!!! info
+ Have in mind that dataclasses can't do everything Pydantic models can do.
+
+ So, you might still need to use Pydantic models.
+
+ But if you have a bunch of dataclasses laying around, this is a nice trick to use them to power a web API using FastAPI. 🤓
+
+## Dataclasses in `response_model`
+
+You can also use `dataclasses` in the `response_model` parameter:
+
+```Python hl_lines="1 7-13 19"
+{!../../../docs_src/dataclasses/tutorial002.py!}
+```
+
+The dataclass will be automatically converted to a Pydantic dataclass.
+
+This way, its schema will show up in the API docs user interface:
+
+
+
+## Dataclasses in Nested Data Structures
+
+You can also combine `dataclasses` with other type annotations to make nested data structures.
+
+In some cases, you might still have to use Pydantic's version of `dataclasses`. For example, if you have errors with the automatically generated API documentation.
+
+In that case, you can simply swap the standard `dataclasses` with `pydantic.dataclasses`, which is a drop-in replacement:
+
+```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" }
+{!../../../docs_src/dataclasses/tutorial003.py!}
+```
+
+1. We still import `field` from standard `dataclasses`.
+
+2. `pydantic.dataclasses` is a drop-in replacement for `dataclasses`.
+
+3. The `Author` dataclass includes a list of `Item` dataclasses.
+
+4. The `Author` dataclass is used as the `response_model` parameter.
+
+5. You can use other standard type annotations with dataclasses as the request body.
+
+ In this case, it's a list of `Item` dataclasses.
+
+6. Here we are returning a dictionary that contains `items` which is a list of dataclasses.
+
+ FastAPI is still capable of serializing the data to JSON.
+
+7. Here the `response_model` is using a type annotation of a list of `Author` dataclasses.
+
+ Again, you can combine `dataclasses` with standard type annotations.
+
+8. Notice that this *path operation function* uses regular `def` instead of `async def`.
+
+ As always, in FastAPI you can combine `def` and `async def` as needed.
+
+ If you need a refresher about when to use which, check out the section _"In a hurry?"_ in the docs about `async` and `await`.
+
+9. This *path operation function* is not returning dataclasses (although it could), but a list of dictionaries with internal data.
+
+ FastAPI will use the `response_model` parameter (that includes dataclasses) to convert the response.
+
+You can combine `dataclasses` with other type annotations in many different combinations to form complex data structures.
+
+Check the in-code annotation tips above to see more specific details.
+
+## Learn More
+
+You can also combine `dataclasses` with other Pydantic models, inherit from them, include them in your own models, etc.
+
+To learn more, check the Pydantic docs about dataclasses.
+
+## Version
+
+This is available since FastAPI version `0.67.0`. 🔖
From 6db8453b26ecd97de30f6b5c4409ff49b1266833 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:35 +0800
Subject: [PATCH 011/163] New translations events.md (Chinese Simplified)
---
docs/zh/docs/advanced/events.md | 162 ++++++++++++++++++++++++++++++++
1 file changed, 162 insertions(+)
create mode 100644 docs/zh/docs/advanced/events.md
diff --git a/docs/zh/docs/advanced/events.md b/docs/zh/docs/advanced/events.md
new file mode 100644
index 0000000000000..f62743b798255
--- /dev/null
+++ b/docs/zh/docs/advanced/events.md
@@ -0,0 +1,162 @@
+# Lifespan Events
+
+You can define logic (code) that should be executed before the application **starts up**. This means that this code will be executed **once**, **before** the application **starts receiving requests**.
+
+The same way, you can define logic (code) that should be executed when the application is **shutting down**. In this case, this code will be executed **once**, **after** having handled possibly **many requests**.
+
+Because this code is executed before the application **starts** taking requests, and right after it **finishes** handling requests, it covers the whole application **lifespan** (the word "lifespan" will be important in a second 😉).
+
+This can be very useful for setting up **resources** that you need to use for the whole app, and that are **shared** among requests, and/or that you need to **clean up** afterwards. For example, a database connection pool, or loading a shared machine learning model.
+
+## Use Case
+
+Let's start with an example **use case** and then see how to solve it with this.
+
+Let's imagine that you have some **machine learning models** that you want to use to handle requests. 🤖
+
+The same models are shared among requests, so, it's not one model per request, or one per user or something similar.
+
+Let's imagine that loading the model can **take quite some time**, because it has to read a lot of **data from disk**. So you don't want to do it for every request.
+
+You could load it at the top level of the module/file, but that would also mean that it would **load the model** even if you are just running a simple automated test, then that test would be **slow** because it would have to wait for the model to load before being able to run an independent part of the code.
+
+That's what we'll solve, let's load the model before the requests are handled, but only right before the application starts receiving requests, not while the code is being loaded.
+
+## Lifespan
+
+You can define this *startup* and *shutdown* logic using the `lifespan` parameter of the `FastAPI` app, and a "context manager" (I'll show you what that is in a second).
+
+Let's start with an example and then see it in detail.
+
+We create an async function `lifespan()` with `yield` like this:
+
+```Python hl_lines="16 19"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+Here we are simulating the expensive *startup* operation of loading the model by putting the (fake) model function in the dictionary with machine learning models before the `yield`. This code will be executed **before** the application **starts taking requests**, during the *startup*.
+
+And then, right after the `yield`, we unload the model. This code will be executed **after** the application **finishes handling requests**, right before the *shutdown*. This could, for example, release resources like memory or a GPU.
+
+!!! tip
+ The `shutdown` would happen when you are **stopping** the application.
+
+ Maybe you need to start a new version, or you just got tired of running it. 🤷
+
+### Lifespan function
+
+The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`.
+
+```Python hl_lines="14-19"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+The first part of the function, before the `yield`, will be executed **before** the application starts.
+
+And the part after the `yield` will be executed **after** the application has finished.
+
+### Async Context Manager
+
+If you check, the function is decorated with an `@asynccontextmanager`.
+
+That converts the function into something called an "**async context manager**".
+
+```Python hl_lines="1 13"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+A **context manager** in Python is something that you can use in a `with` statement, for example, `open()` can be used as a context manager:
+
+```Python
+with open("file.txt") as file:
+ file.read()
+```
+
+In recent versions of Python, there's also an **async context manager**. You would use it with `async with`:
+
+```Python
+async with lifespan(app):
+ await do_stuff()
+```
+
+When you create a context manager or an async context manager like above, what it does is that, before entering the `with` block, it will execute the code before the `yield`, and after exiting the `with` block, it will execute the code after the `yield`.
+
+In our code example above, we don't use it directly, but we pass it to FastAPI for it to use it.
+
+The `lifespan` parameter of the `FastAPI` app takes an **async context manager**, so we can pass our new `lifespan` async context manager to it.
+
+```Python hl_lines="22"
+{!../../../docs_src/events/tutorial003.py!}
+```
+
+## Alternative Events (deprecated)
+
+!!! warning
+ The recommended way to handle the *startup* and *shutdown* is using the `lifespan` parameter of the `FastAPI` app as described above.
+
+ You can probably skip this part.
+
+There's an alternative way to define this logic to be executed during *startup* and during *shutdown*.
+
+You can define event handlers (functions) that need to be executed before the application starts up, or when the application is shutting down.
+
+These functions can be declared with `async def` or normal `def`.
+
+### `startup` event
+
+To add a function that should be run before the application starts, declare it with the event `"startup"`:
+
+```Python hl_lines="8"
+{!../../../docs_src/events/tutorial001.py!}
+```
+
+In this case, the `startup` event handler function will initialize the items "database" (just a `dict`) with some values.
+
+You can add more than one event handler function.
+
+And your application won't start receiving requests until all the `startup` event handlers have completed.
+
+### `shutdown` event
+
+To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`:
+
+```Python hl_lines="6"
+{!../../../docs_src/events/tutorial002.py!}
+```
+
+Here, the `shutdown` event handler function will write a text line `"Application shutdown"` to a file `log.txt`.
+
+!!! info
+ In the `open()` function, the `mode="a"` means "append", so, the line will be added after whatever is on that file, without overwriting the previous contents.
+
+!!! tip
+ Notice that in this case we are using a standard Python `open()` function that interacts with a file.
+
+ So, it involves I/O (input/output), that requires "waiting" for things to be written to disk.
+
+ But `open()` doesn't use `async` and `await`.
+
+ So, we declare the event handler function with standard `def` instead of `async def`.
+
+### `startup` and `shutdown` together
+
+There's a high chance that the logic for your *startup* and *shutdown* is connected, you might want to start something and then finish it, acquire a resource and then release it, etc.
+
+Doing that in separated functions that don't share logic or variables together is more difficult as you would need to store values in global variables or similar tricks.
+
+Because of that, it's now recommended to instead use the `lifespan` as explained above.
+
+## Technical Details
+
+Just a technical detail for the curious nerds. 🤓
+
+Underneath, in the ASGI technical specification, this is part of the Lifespan Protocol, and it defines events called `startup` and `shutdown`.
+
+!!! info
+ You can read more about the Starlette `lifespan` handlers in Starlette's Lifespan' docs.
+
+ Including how to handle lifespan state that can be used in other areas of your code.
+
+## Sub Applications
+
+🚨 Have in mind that these lifespan events (startup and shutdown) will only be executed for the main application, not for [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}.
From d207dce4aa7c98067a557a1f9328d827d058aaa3 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:37 +0800
Subject: [PATCH 012/163] New translations extending-openapi.md (Chinese
Simplified)
---
docs/zh/docs/advanced/extending-openapi.md | 318 +++++++++++++++++++++
1 file changed, 318 insertions(+)
create mode 100644 docs/zh/docs/advanced/extending-openapi.md
diff --git a/docs/zh/docs/advanced/extending-openapi.md b/docs/zh/docs/advanced/extending-openapi.md
new file mode 100644
index 0000000000000..fe3f649f93230
--- /dev/null
+++ b/docs/zh/docs/advanced/extending-openapi.md
@@ -0,0 +1,318 @@
+# Extending OpenAPI
+
+!!! warning
+ This is a rather advanced feature. You probably can skip it.
+
+ If you are just following the tutorial - user guide, you can probably skip this section.
+
+ If you already know that you need to modify the generated OpenAPI schema, continue reading.
+
+There are some cases where you might need to modify the generated OpenAPI schema.
+
+In this section you will see how.
+
+## The normal process
+
+The normal (default) process, is as follows.
+
+A `FastAPI` application (instance) has an `.openapi()` method that is expected to return the OpenAPI schema.
+
+As part of the application object creation, a *path operation* for `/openapi.json` (or for whatever you set your `openapi_url`) is registered.
+
+It just returns a JSON response with the result of the application's `.openapi()` method.
+
+By default, what the method `.openapi()` does is check the property `.openapi_schema` to see if it has contents and return them.
+
+If it doesn't, it generates them using the utility function at `fastapi.openapi.utils.get_openapi`.
+
+And that function `get_openapi()` receives as parameters:
+
+* `title`: The OpenAPI title, shown in the docs.
+* `version`: The version of your API, e.g. `2.5.0`.
+* `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.1.0`.
+* `summary`: A short summary of the API.
+* `description`: The description of your API, this can include markdown and will be shown in the docs.
+* `routes`: A list of routes, these are each of the registered *path operations*. They are taken from `app.routes`.
+
+!!! info
+ The parameter `summary` is available in OpenAPI 3.1.0 and above, supported by FastAPI 0.99.0 and above.
+
+## Overriding the defaults
+
+Using the information above, you can use the same utility function to generate the OpenAPI schema and override each part that you need.
+
+For example, let's add ReDoc's OpenAPI extension to include a custom logo.
+
+### Normal **FastAPI**
+
+First, write all your **FastAPI** application as normally:
+
+```Python hl_lines="1 4 7-9"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### Generate the OpenAPI schema
+
+Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
+
+```Python hl_lines="2 15-21"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### Modify the OpenAPI schema
+
+Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
+
+```Python hl_lines="22-24"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### Cache the OpenAPI schema
+
+You can use the property `.openapi_schema` as a "cache", to store your generated schema.
+
+That way, your application won't have to generate the schema every time a user opens your API docs.
+
+It will be generated only once, and then the same cached schema will be used for the next requests.
+
+```Python hl_lines="13-14 25-26"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### Override the method
+
+Now you can replace the `.openapi()` method with your new function.
+
+```Python hl_lines="29"
+{!../../../docs_src/extending_openapi/tutorial001.py!}
+```
+
+### Check it
+
+Once you go to http://127.0.0.1:8000/redoc you will see that you are using your custom logo (in this example, **FastAPI**'s logo):
+
+
+
+## Self-hosting JavaScript and CSS for docs
+
+The API docs use **Swagger UI** and **ReDoc**, and each of those need some JavaScript and CSS files.
+
+By default, those files are served from a CDN.
+
+But it's possible to customize it, you can set a specific CDN, or serve the files yourself.
+
+That's useful, for example, if you need your app to keep working even while offline, without open Internet access, or in a local network.
+
+Here you'll see how to serve those files yourself, in the same FastAPI app, and configure the docs to use them.
+
+### Project file structure
+
+Let's say your project file structure looks like this:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+```
+
+Now create a directory to store those static files.
+
+Your new file structure could look like this:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+└── static/
+```
+
+### Download the files
+
+Download the static files needed for the docs and put them on that `static/` directory.
+
+You can probably right-click each link and select an option similar to `Save link as...`.
+
+**Swagger UI** uses the files:
+
+* `swagger-ui-bundle.js`
+* `swagger-ui.css`
+
+And **ReDoc** uses the file:
+
+* `redoc.standalone.js`
+
+After that, your file structure could look like:
+
+```
+.
+├── app
+│ ├── __init__.py
+│ ├── main.py
+└── static
+ ├── redoc.standalone.js
+ ├── swagger-ui-bundle.js
+ └── swagger-ui.css
+```
+
+### Serve the static files
+
+* Import `StaticFiles`.
+* "Mount" a `StaticFiles()` instance in a specific path.
+
+```Python hl_lines="7 11"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+### Test the static files
+
+Start your application and go to http://127.0.0.1:8000/static/redoc.standalone.js.
+
+You should see a very long JavaScript file for **ReDoc**.
+
+It could start with something like:
+
+```JavaScript
+/*!
+ * ReDoc - OpenAPI/Swagger-generated API Reference Documentation
+ * -------------------------------------------------------------
+ * Version: "2.0.0-rc.18"
+ * Repo: https://github.com/Redocly/redoc
+ */
+!function(e,t){"object"==typeof exports&&"object"==typeof m
+
+...
+```
+
+That confirms that you are being able to serve static files from your app, and that you placed the static files for the docs in the correct place.
+
+Now we can configure the app to use those static files for the docs.
+
+### Disable the automatic docs
+
+The first step is to disable the automatic docs, as those use the CDN by default.
+
+To disable them, set their URLs to `None` when creating your `FastAPI` app:
+
+```Python hl_lines="9"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+### Include the custom docs
+
+Now you can create the *path operations* for the custom docs.
+
+You can re-use FastAPI's internal functions to create the HTML pages for the docs, and pass them the needed arguments:
+
+* `openapi_url`: the URL where the HTML page for the docs can get the OpenAPI schema for your API. You can use here the attribute `app.openapi_url`.
+* `title`: the title of your API.
+* `oauth2_redirect_url`: you can use `app.swagger_ui_oauth2_redirect_url` here to use the default.
+* `swagger_js_url`: the URL where the HTML for your Swagger UI docs can get the **JavaScript** file. This is the one that your own app is now serving.
+* `swagger_css_url`: the URL where the HTML for your Swagger UI docs can get the **CSS** file. This is the one that your own app is now serving.
+
+And similarly for ReDoc...
+
+```Python hl_lines="2-6 14-22 25-27 30-36"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+!!! tip
+ The *path operation* for `swagger_ui_redirect` is a helper for when you use OAuth2.
+
+ If you integrate your API with an OAuth2 provider, you will be able to authenticate and come back to the API docs with the acquired credentials. And interact with it using the real OAuth2 authentication.
+
+ Swagger UI will handle it behind the scenes for you, but it needs this "redirect" helper.
+
+### Create a *path operation* to test it
+
+Now, to be able to test that everything works, create a *path operation*:
+
+```Python hl_lines="39-41"
+{!../../../docs_src/extending_openapi/tutorial002.py!}
+```
+
+### Test it
+
+Now, you should be able to disconnect your WiFi, go to your docs at http://127.0.0.1:8000/docs, and reload the page.
+
+And even without Internet, you would be able to see the docs for your API and interact with it.
+
+## Configuring Swagger UI
+
+You can configure some extra Swagger UI parameters.
+
+To configure them, pass the `swagger_ui_parameters` argument when creating the `FastAPI()` app object or to the `get_swagger_ui_html()` function.
+
+`swagger_ui_parameters` receives a dictionary with the configurations passed to Swagger UI directly.
+
+FastAPI converts the configurations to **JSON** to make them compatible with JavaScript, as that's what Swagger UI needs.
+
+### Disable Syntax Highlighting
+
+For example, you could disable syntax highlighting in Swagger UI.
+
+Without changing the settings, syntax highlighting is enabled by default:
+
+
+
+But you can disable it by setting `syntaxHighlight` to `False`:
+
+```Python hl_lines="3"
+{!../../../docs_src/extending_openapi/tutorial003.py!}
+```
+
+...and then Swagger UI won't show the syntax highlighting anymore:
+
+
+
+### Change the Theme
+
+The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle):
+
+```Python hl_lines="3"
+{!../../../docs_src/extending_openapi/tutorial004.py!}
+```
+
+That configuration would change the syntax highlighting color theme:
+
+
+
+### Change Default Swagger UI Parameters
+
+FastAPI includes some default configuration parameters appropriate for most of the use cases.
+
+It includes these default configurations:
+
+```Python
+{!../../../fastapi/openapi/docs.py[ln:7-13]!}
+```
+
+You can override any of them by setting a different value in the argument `swagger_ui_parameters`.
+
+For example, to disable `deepLinking` you could pass these settings to `swagger_ui_parameters`:
+
+```Python hl_lines="3"
+{!../../../docs_src/extending_openapi/tutorial005.py!}
+```
+
+### Other Swagger UI Parameters
+
+To see all the other possible configurations you can use, read the official docs for Swagger UI parameters.
+
+### JavaScript-only settings
+
+Swagger UI also allows other configurations to be **JavaScript-only** objects (for example, JavaScript functions).
+
+FastAPI also includes these JavaScript-only `presets` settings:
+
+```JavaScript
+presets: [
+ SwaggerUIBundle.presets.apis,
+ SwaggerUIBundle.SwaggerUIStandalonePreset
+]
+```
+
+These are **JavaScript** objects, not strings, so you can't pass them from Python code directly.
+
+If you need to use JavaScript-only configurations like those, you can use one of the methods above. Override all the Swagger UI *path operation* and manually write any JavaScript you need.
From 862544547cbc05b97425313456d93567954ac269 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:38 +0800
Subject: [PATCH 013/163] New translations generate-clients.md (Chinese
Simplified)
---
docs/zh/docs/advanced/generate-clients.md | 266 ++++++++++++++++++++++
1 file changed, 266 insertions(+)
create mode 100644 docs/zh/docs/advanced/generate-clients.md
diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md
new file mode 100644
index 0000000000000..5edfccb23b1a5
--- /dev/null
+++ b/docs/zh/docs/advanced/generate-clients.md
@@ -0,0 +1,266 @@
+# Generate Clients
+
+As **FastAPI** is based on the OpenAPI specification, you get automatic compatibility with many tools, including the automatic API docs (provided by Swagger UI).
+
+One particular advantage that is not necessarily obvious is that you can **generate clients** (sometimes called **SDKs** ) for your API, for many different **programming languages**.
+
+## OpenAPI Client Generators
+
+There are many tools to generate clients from **OpenAPI**.
+
+A common tool is OpenAPI Generator.
+
+If you are building a **frontend**, a very interesting alternative is openapi-typescript-codegen.
+
+## Generate a TypeScript Frontend Client
+
+Let's start with a simple FastAPI application:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="7-9 12-13 16-17 21"
+ {!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-11 14-15 18 19 23"
+ {!> ../../../docs_src/generate_clients/tutorial001.py!}
+ ```
+
+Notice that the *path operations* define the models they use for request payload and response payload, using the models `Item` and `ResponseMessage`.
+
+### API Docs
+
+If you go to the API docs, you will see that it has the **schemas** for the data to be sent in requests and received in responses:
+
+
+
+You can see those schemas because they were declared with the models in the app.
+
+That information is available in the app's **OpenAPI schema**, and then shown in the API docs (by Swagger UI).
+
+And that same information from the models that is included in OpenAPI is what can be used to **generate the client code**.
+
+### Generate a TypeScript Client
+
+Now that we have the app with the models, we can generate the client code for the frontend.
+
+#### Install `openapi-typescript-codegen`
+
+You can install `openapi-typescript-codegen` in your frontend code with:
+
+
+
+You will also get autocompletion for the payload to send:
+
+
+
+!!! tip
+ Notice the autocompletion for `name` and `price`, that was defined in the FastAPI application, in the `Item` model.
+
+You will have inline errors for the data that you send:
+
+
+
+The response object will also have autocompletion:
+
+
+
+## FastAPI App with Tags
+
+In many cases your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*.
+
+For example, you could have a section for **items** and another section for **users**, and they could be separated by tags:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="21 26 34"
+ {!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="23 28 36"
+ {!> ../../../docs_src/generate_clients/tutorial002.py!}
+ ```
+
+### Generate a TypeScript Client with Tags
+
+If you generate a client for a FastAPI app using tags, it will normally also separate the client code based on the tags.
+
+This way you will be able to have things ordered and grouped correctly for the client code:
+
+
+
+In this case you have:
+
+* `ItemsService`
+* `UsersService`
+
+### Client Method Names
+
+Right now the generated method names like `createItemItemsPost` don't look very clean:
+
+```TypeScript
+ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
+```
+
+...that's because the client generator uses the OpenAPI internal **operation ID** for each *path operation*.
+
+OpenAPI requires that each operation ID is unique across all the *path operations*, so FastAPI uses the **function name**, the **path**, and the **HTTP method/operation** to generate that operation ID, because that way it can make sure that the operation IDs are unique.
+
+But I'll show you how to improve that next. 🤓
+
+## Custom Operation IDs and Better Method Names
+
+You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients.
+
+In this case you will have to ensure that each operation ID is **unique** in some other way.
+
+For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation* **name** (the function name).
+
+### Custom Generate Unique ID Function
+
+FastAPI uses a **unique ID** for each *path operation*, it is used for the **operation ID** and also for the names of any needed custom models, for requests or responses.
+
+You can customize that function. It takes an `APIRoute` and outputs a string.
+
+For example, here it is using the first tag (you will probably have only one tag) and the *path operation* name (the function name).
+
+You can then pass that custom function to **FastAPI** as the `generate_unique_id_function` parameter:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="6-7 10"
+ {!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8-9 12"
+ {!> ../../../docs_src/generate_clients/tutorial003.py!}
+ ```
+
+### Generate a TypeScript Client with Custom Operation IDs
+
+Now if you generate the client again, you will see that it has the improved method names:
+
+
+
+As you see, the method names now have the tag and then the function name, now they don't include information from the URL path and the HTTP operation.
+
+### Preprocess the OpenAPI Specification for the Client Generator
+
+The generated code still has some **duplicated information**.
+
+We already know that this method is related to the **items** because that word is in the `ItemsService` (taken from the tag), but we still have the tag name prefixed in the method name too. 😕
+
+We will probably still want to keep it for OpenAPI in general, as that will ensure that the operation IDs are **unique**.
+
+But for the generated client we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**.
+
+We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this:
+
+```Python
+{!../../../docs_src/generate_clients/tutorial004.py!}
+```
+
+With that, the operation IDs would be renamed from things like `items-get_items` to just `get_items`, that way the client generator can generate simpler method names.
+
+### Generate a TypeScript Client with the Preprocessed OpenAPI
+
+Now as the end result is in a file `openapi.json`, you would modify the `package.json` to use that local file, for example:
+
+```JSON hl_lines="7"
+{
+ "name": "frontend-app",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "generate-client": "openapi --input ./openapi.json --output ./src/client --client axios"
+ },
+ "author": "",
+ "license": "",
+ "devDependencies": {
+ "openapi-typescript-codegen": "^0.20.1",
+ "typescript": "^4.6.2"
+ }
+}
+```
+
+After generating the new client, you would now have **clean method names**, with all the **autocompletion**, **inline errors**, etc:
+
+
+
+## Benefits
+
+When using the automatically generated clients you would **autocompletion** for:
+
+* Methods.
+* Request payloads in the body, query parameters, etc.
+* Response payloads.
+
+You would also have **inline errors** for everything.
+
+And whenever you update the backend code, and **regenerate** the frontend, it would have any new *path operations* available as methods, the old ones removed, and any other change would be reflected on the generated code. 🤓
+
+This also means that if something changed it will be **reflected** on the client code automatically. And if you **build** the client it will error out if you have any **mismatch** in the data used.
+
+So, you would **detect many errors** very early in the development cycle instead of having to wait for the errors to show up to your final users in production and then trying to debug where the problem is. ✨
From 6ca3045289127468499ef324ff5655750e447071 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:39 +0800
Subject: [PATCH 014/163] New translations graphql.md (Chinese Simplified)
---
docs/zh/docs/advanced/graphql.md | 59 ++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
create mode 100644 docs/zh/docs/advanced/graphql.md
diff --git a/docs/zh/docs/advanced/graphql.md b/docs/zh/docs/advanced/graphql.md
new file mode 100644
index 0000000000000..1d2753fc4ce1b
--- /dev/null
+++ b/docs/zh/docs/advanced/graphql.md
@@ -0,0 +1,59 @@
+# GraphQL
+
+As **FastAPI** is based on the **ASGI** standard, it's very easy to integrate any **GraphQL** library also compatible with ASGI.
+
+You can combine normal FastAPI *path operations* with GraphQL on the same application.
+
+!!! tip
+ **GraphQL** solves some very specific use cases.
+
+ It has **advantages** and **disadvantages** when compared to common **web APIs**.
+
+ Make sure you evaluate if the **benefits** for your use case compensate the **drawbacks**. 🤓
+
+## GraphQL Libraries
+
+Here are some of the **GraphQL** libraries that have **ASGI** support. You could use them with **FastAPI**:
+
+* Strawberry 🍓
+ * With docs for FastAPI
+* Ariadne
+
+ * With docs for Starlette (that also apply to FastAPI)
+* Tartiflette
+
+ * With Tartiflette ASGI to provide ASGI integration
+* Graphene
+
+ * With starlette-graphene3
+
+## GraphQL with Strawberry
+
+If you need or want to work with **GraphQL**, **Strawberry** is the **recommended** library as it has the design closest to **FastAPI's** design, it's all based on **type annotations**.
+
+Depending on your use case, you might prefer to use a different library, but if you asked me, I would probably suggest you try **Strawberry**.
+
+Here's a small preview of how you could integrate Strawberry with FastAPI:
+
+```Python hl_lines="3 22 25-26"
+{!../../../docs_src/graphql/tutorial001.py!}
+```
+
+You can learn more about Strawberry in the Strawberry documentation.
+
+And also the docs about Strawberry with FastAPI.
+
+## Older `GraphQLApp` from Starlette
+
+Previous versions of Starlette included a `GraphQLApp` class to integrate with Graphene.
+
+It was deprecated from Starlette, but if you have code that used it, you can easily **migrate** to starlette-graphene3, that covers the same use case and has an **almost identical interface**.
+
+!!! tip
+ If you need GraphQL, I still would recommend you check out Strawberry, as it's based on type annotations instead of custom classes and types.
+
+## Learn More
+
+You can learn more about **GraphQL** in the official GraphQL documentation.
+
+You can also read more about each those libraries described above in their links.
From 66fbb1ca3c142a11fe436577150753e52ea97f6b Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:40 +0800
Subject: [PATCH 015/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/advanced/index.md | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/docs/zh/docs/advanced/index.md b/docs/zh/docs/advanced/index.md
index 824f91f47ba90..467f0833e60a6 100644
--- a/docs/zh/docs/advanced/index.md
+++ b/docs/zh/docs/advanced/index.md
@@ -1,18 +1,24 @@
-# 高级用户指南
+# Advanced User Guide
-## 额外特性
+## Additional Features
-主要的教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 应该足以让你了解 **FastAPI** 的所有主要特性。
+The main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank} should be enough to give you a tour through all the main features of **FastAPI**.
-你会在接下来的章节中了解到其他的选项、配置以及额外的特性。
+In the next sections you will see other options, configurations, and additional features.
!!! tip
- 接下来的章节**并不一定是**「高级的」。
+ The next sections are **not necessarily "advanced"**.
- 而且对于你的使用场景来说,解决方案很可能就在其中。
+ And it's possible that for your use case, the solution is in one of them.
-## 先阅读教程
+## Read the Tutorial first
-你可能仍会用到 **FastAPI** 主教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 中的大多数特性。
+You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank}.
-接下来的章节我们认为你已经读过 [教程 - 用户指南](../tutorial/){.internal-link target=_blank},并且假设你已经知晓其中主要思想。
+And the next sections assume you already read it, and assume that you know those main ideas.
+
+## TestDriven.io course
+
+If you would like to take an advanced-beginner course to complement this section of the docs, you might want to check: Test-Driven Development with FastAPI and Docker by **TestDriven.io**.
+
+They are currently donating 10% of all profits to the development of **FastAPI**. 🎉 😄
From c48d45af7d131e6f6d632c307943a6e9172a12c4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:41 +0800
Subject: [PATCH 016/163] New translations middleware.md (Chinese Simplified)
---
docs/zh/docs/advanced/middleware.md | 99 +++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
create mode 100644 docs/zh/docs/advanced/middleware.md
diff --git a/docs/zh/docs/advanced/middleware.md b/docs/zh/docs/advanced/middleware.md
new file mode 100644
index 0000000000000..9219f1d2cb35d
--- /dev/null
+++ b/docs/zh/docs/advanced/middleware.md
@@ -0,0 +1,99 @@
+# Advanced Middleware
+
+In the main tutorial you read how to add [Custom Middleware](../tutorial/middleware.md){.internal-link target=_blank} to your application.
+
+And then you also read how to handle [CORS with the `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}.
+
+In this section we'll see how to use other middlewares.
+
+## Adding ASGI middlewares
+
+As **FastAPI** is based on Starlette and implements the ASGI specification, you can use any ASGI middleware.
+
+A middleware doesn't have to be made for FastAPI or Starlette to work, as long as it follows the ASGI spec.
+
+In general, ASGI middlewares are classes that expect to receive an ASGI app as the first argument.
+
+So, in the documentation for third-party ASGI middlewares they will probably tell you to do something like:
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+But FastAPI (actually Starlette) provides a simpler way to do it that makes sure that the internal middlewares to handle server errors and custom exception handlers work properly.
+
+For that, you use `app.add_middleware()` (as in the example for CORS).
+
+```Python
+from fastapi import FastAPI
+from unicorn import UnicornMiddleware
+
+app = FastAPI()
+
+app.add_middleware(UnicornMiddleware, some_config="rainbow")
+```
+
+`app.add_middleware()` receives a middleware class as the first argument and any additional arguments to be passed to the middleware.
+
+## Integrated middlewares
+
+**FastAPI** includes several middlewares for common use cases, we'll see next how to use them.
+
+!!! note "Technical Details"
+ For the next examples, you could also use `from starlette.middleware.something import SomethingMiddleware`.
+
+ **FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette.
+
+## `HTTPSRedirectMiddleware`
+
+Enforces that all incoming requests must either be `https` or `wss`.
+
+Any incoming requests to `http` or `ws` will be redirected to the secure scheme instead.
+
+```Python hl_lines="2 6"
+{!../../../docs_src/advanced_middleware/tutorial001.py!}
+```
+
+## `TrustedHostMiddleware`
+
+Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks.
+
+```Python hl_lines="2 6-8"
+{!../../../docs_src/advanced_middleware/tutorial002.py!}
+```
+
+The following arguments are supported:
+
+* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains. To allow any hostname either use `allowed_hosts=["*"]` or omit the middleware.
+
+If an incoming request does not validate correctly then a `400` response will be sent.
+
+## `GZipMiddleware`
+
+Handles GZip responses for any request that includes `"gzip"` in the `Accept-Encoding` header.
+
+The middleware will handle both standard and streaming responses.
+
+```Python hl_lines="2 6"
+{!../../../docs_src/advanced_middleware/tutorial003.py!}
+```
+
+The following arguments are supported:
+
+* `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`.
+
+## Other middlewares
+
+There are many other ASGI middlewares.
+
+For example:
+
+* Sentry
+* Uvicorn's `ProxyHeadersMiddleware`
+* MessagePack
+
+To see other available middlewares check Starlette's Middleware docs and the ASGI Awesome List.
From 47303c22cd196b33cb6801d2037de6d2192bb337 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:42 +0800
Subject: [PATCH 017/163] New translations nosql-databases.md (Chinese
Simplified)
---
docs/zh/docs/advanced/nosql-databases.md | 163 +++++++++++++++++++++++
1 file changed, 163 insertions(+)
create mode 100644 docs/zh/docs/advanced/nosql-databases.md
diff --git a/docs/zh/docs/advanced/nosql-databases.md b/docs/zh/docs/advanced/nosql-databases.md
new file mode 100644
index 0000000000000..f97f986c4261e
--- /dev/null
+++ b/docs/zh/docs/advanced/nosql-databases.md
@@ -0,0 +1,163 @@
+# NoSQL (Distributed / Big Data) Databases
+
+!!! info
+ These docs are about to be updated. 🎉
+
+ The current version assumes Pydantic v1.
+
+ The new docs will hopefully use Pydantic v2 and will use ODMantic with MongoDB.
+
+**FastAPI** can also be integrated with any NoSQL.
+
+Here we'll see an example using **Couchbase**, a document based NoSQL database.
+
+You can adapt it to any other NoSQL database like:
+
+* **MongoDB**
+* **Cassandra**
+* **CouchDB**
+* **ArangoDB**
+* **ElasticSearch**, etc.
+
+!!! tip
+ There is an official project generator with **FastAPI** and **Couchbase**, all based on **Docker**, including a frontend and more tools: https://github.com/tiangolo/full-stack-fastapi-couchbase
+
+## Import Couchbase components
+
+For now, don't pay attention to the rest, only the imports:
+
+```Python hl_lines="3-5"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## Define a constant to use as a "document type"
+
+We will use it later as a fixed field `type` in our documents.
+
+This is not required by Couchbase, but is a good practice that will help you afterwards.
+
+```Python hl_lines="9"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## Add a function to get a `Bucket`
+
+In **Couchbase**, a bucket is a set of documents, that can be of different types.
+
+They are generally all related to the same application.
+
+The analogy in the relational database world would be a "database" (a specific database, not the database server).
+
+The analogy in **MongoDB** would be a "collection".
+
+In the code, a `Bucket` represents the main entrypoint of communication with the database.
+
+This utility function will:
+
+* Connect to a **Couchbase** cluster (that might be a single machine).
+ * Set defaults for timeouts.
+* Authenticate in the cluster.
+* Get a `Bucket` instance.
+ * Set defaults for timeouts.
+* Return it.
+
+```Python hl_lines="12-21"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## Create Pydantic models
+
+As **Couchbase** "documents" are actually just "JSON objects", we can model them with Pydantic.
+
+### `User` model
+
+First, let's create a `User` model:
+
+```Python hl_lines="24-28"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+We will use this model in our *path operation function*, so, we don't include in it the `hashed_password`.
+
+### `UserInDB` model
+
+Now, let's create a `UserInDB` model.
+
+This will have the data that is actually stored in the database.
+
+We don't create it as a subclass of Pydantic's `BaseModel` but as a subclass of our own `User`, because it will have all the attributes in `User` plus a couple more:
+
+```Python hl_lines="31-33"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+!!! note
+ Notice that we have a `hashed_password` and a `type` field that will be stored in the database.
+
+ But it is not part of the general `User` model (the one we will return in the *path operation*).
+
+## Get the user
+
+Now create a function that will:
+
+* Take a username.
+* Generate a document ID from it.
+* Get the document with that ID.
+* Put the contents of the document in a `UserInDB` model.
+
+By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your *path operation function*, you can more easily re-use it in multiple parts and also add unit tests for it:
+
+```Python hl_lines="36-42"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+### f-strings
+
+If you are not familiar with the `f"userprofile::{username}"`, it is a Python "f-string".
+
+Any variable that is put inside of `{}` in an f-string will be expanded / injected in the string.
+
+### `dict` unpacking
+
+If you are not familiar with the `UserInDB(**result.value)`, it is using `dict` "unpacking".
+
+It will take the `dict` at `result.value`, and take each of its keys and values and pass them as key-values to `UserInDB` as keyword arguments.
+
+So, if the `dict` contains:
+
+```Python
+{
+ "username": "johndoe",
+ "hashed_password": "some_hash",
+}
+```
+
+It will be passed to `UserInDB` as:
+
+```Python
+UserInDB(username="johndoe", hashed_password="some_hash")
+```
+
+## Create your **FastAPI** code
+
+### Create the `FastAPI` app
+
+```Python hl_lines="46"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+### Create the *path operation function*
+
+As our code is calling Couchbase and we are not using the experimental Python await support, we should declare our function with normal `def` instead of `async def`.
+
+Also, Couchbase recommends not using a single `Bucket` object in multiple "threads", so, we can just get the bucket directly and pass it to our utility functions:
+
+```Python hl_lines="49-53"
+{!../../../docs_src/nosql_databases/tutorial001.py!}
+```
+
+## Recap
+
+You can integrate any third party NoSQL database, just using their standard packages.
+
+The same applies to any other external tool, system or API.
From 52f74c0423eeb6d479cb9534ea5332e2d1c6aa5c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:43 +0800
Subject: [PATCH 018/163] New translations openapi-callbacks.md (Chinese
Simplified)
---
docs/zh/docs/advanced/openapi-callbacks.md | 179 +++++++++++++++++++++
1 file changed, 179 insertions(+)
create mode 100644 docs/zh/docs/advanced/openapi-callbacks.md
diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md
new file mode 100644
index 0000000000000..14004d948e430
--- /dev/null
+++ b/docs/zh/docs/advanced/openapi-callbacks.md
@@ -0,0 +1,179 @@
+# OpenAPI Callbacks
+
+You could create an API with a *path operation* that could trigger a request to an *external API* created by someone else (probably the same developer that would be *using* your API).
+
+The process that happens when your API app calls the *external API* is named a "callback". Because the software that the external developer wrote sends a request to your API and then your API *calls back*, sending a request to an *external API* (that was probably created by the same developer).
+
+In this case, you could want to document how that external API *should* look like. What *path operation* it should have, what body it should expect, what response it should return, etc.
+
+## An app with callbacks
+
+Let's see all this with an example.
+
+Imagine you develop an app that allows creating invoices.
+
+These invoices will have an `id`, `title` (optional), `customer`, and `total`.
+
+The user of your API (an external developer) will create an invoice in your API with a POST request.
+
+Then your API will (let's imagine):
+
+* Send the invoice to some customer of the external developer.
+* Collect the money.
+* Send a notification back to the API user (the external developer).
+ * This will be done by sending a POST request (from *your API*) to some *external API* provided by that external developer (this is the "callback").
+
+## The normal **FastAPI** app
+
+Let's first see how the normal API app would look like before adding the callback.
+
+It will have a *path operation* that will receive an `Invoice` body, and a query parameter `callback_url` that will contain the URL for the callback.
+
+This part is pretty normal, most of the code is probably already familiar to you:
+
+```Python hl_lines="9-13 36-53"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+!!! tip
+ The `callback_url` query parameter uses a Pydantic URL type.
+
+The only new thing is the `callbacks=messages_callback_router.routes` as an argument to the *path operation decorator*. We'll see what that is next.
+
+## Documenting the callback
+
+The actual callback code will depend heavily on your own API app.
+
+And it will probably vary a lot from one app to the next.
+
+It could be just one or two lines of code, like:
+
+```Python
+callback_url = "https://example.com/api/v1/invoices/events/"
+httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
+```
+
+But possibly the most important part of the callback is making sure that your API user (the external developer) implements the *external API* correctly, according to the data that *your API* is going to send in the request body of the callback, etc.
+
+So, what we will do next is add the code to document how that *external API* should look like to receive the callback from *your API*.
+
+That documentation will show up in the Swagger UI at `/docs` in your API, and it will let external developers know how to build the *external API*.
+
+This example doesn't implement the callback itself (that could be just a line of code), only the documentation part.
+
+!!! tip
+ The actual callback is just an HTTP request.
+
+ When implementing the callback yourself, you could use something like HTTPX or Requests.
+
+## Write the callback documentation code
+
+This code won't be executed in your app, we only need it to *document* how that *external API* should look like.
+
+But, you already know how to easily create automatic documentation for an API with **FastAPI**.
+
+So we are going to use that same knowledge to document how the *external API* should look like... by creating the *path operation(s)* that the external API should implement (the ones your API will call).
+
+!!! tip
+ When writing the code to document a callback, it might be useful to imagine that you are that *external developer*. And that you are currently implementing the *external API*, not *your API*.
+
+ Temporarily adopting this point of view (of the *external developer*) can help you feel like it's more obvious where to put the parameters, the Pydantic model for the body, for the response, etc. for that *external API*.
+
+### Create a callback `APIRouter`
+
+First create a new `APIRouter` that will contain one or more callbacks.
+
+```Python hl_lines="3 25"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+### Create the callback *path operation*
+
+To create the callback *path operation* use the same `APIRouter` you created above.
+
+It should look just like a normal FastAPI *path operation*:
+
+* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`.
+* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`.
+
+```Python hl_lines="16-18 21-22 28-32"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+There are 2 main differences from a normal *path operation*:
+
+* It doesn't need to have any actual code, because your app will never call this code. It's only used to document the *external API*. So, the function could just have `pass`.
+* The *path* can contain an OpenAPI 3 expression (see more below) where it can use variables with parameters and parts of the original request sent to *your API*.
+
+### The callback path expression
+
+The callback *path* can have an OpenAPI 3 expression that can contain parts of the original request sent to *your API*.
+
+In this case, it's the `str`:
+
+```Python
+"{$callback_url}/invoices/{$request.body.id}"
+```
+
+So, if your API user (the external developer) sends a request to *your API* to:
+
+```
+https://yourapi.com/invoices/?callback_url=https://www.external.org/events
+```
+
+with a JSON body of:
+
+```JSON
+{
+ "id": "2expen51ve",
+ "customer": "Mr. Richie Rich",
+ "total": "9999"
+}
+```
+
+Then *your API* will process the invoice, and at some point later, send a callback request to the `callback_url` (the *external API*):
+
+```
+https://www.external.org/events/invoices/2expen51ve
+```
+
+with a JSON body containing something like:
+
+```JSON
+{
+ "description": "Payment celebration",
+ "paid": true
+}
+```
+
+and it would expect a response from that *external API* with a JSON body like:
+
+```JSON
+{
+ "ok": true
+}
+```
+
+!!! tip
+ Notice how the callback URL used contains the URL received as a query parameter in `callback_url` (`https://www.external.org/events`) and also the invoice `id` from inside of the JSON body (`2expen51ve`).
+
+### Add the callback router
+
+At this point you have the *callback path operation(s)* needed (the one(s) that the *external developer* should implement in the *external API*) in the callback router you created above.
+
+Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` (that's actually just a `list` of routes/*path operations*) from that callback router:
+
+```Python hl_lines="35"
+{!../../../docs_src/openapi_callbacks/tutorial001.py!}
+```
+
+!!! tip
+ Notice that you are not passing the router itself (`invoices_callback_router`) to `callback=`, but the attribute `.routes`, as in `invoices_callback_router.routes`.
+
+### Check the docs
+
+Now you can start your app with Uvicorn and go to http://127.0.0.1:8000/docs.
+
+You will see your docs including a "Callback" section for your *path operation* that shows how the *external API* should look like:
+
+
From b450dc8fcd9ec33881f3e92a834df491c628255c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:44 +0800
Subject: [PATCH 019/163] New translations openapi-webhooks.md (Chinese
Simplified)
---
docs/zh/docs/advanced/openapi-webhooks.md | 51 +++++++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 docs/zh/docs/advanced/openapi-webhooks.md
diff --git a/docs/zh/docs/advanced/openapi-webhooks.md b/docs/zh/docs/advanced/openapi-webhooks.md
new file mode 100644
index 0000000000000..a41f8c820490d
--- /dev/null
+++ b/docs/zh/docs/advanced/openapi-webhooks.md
@@ -0,0 +1,51 @@
+# OpenAPI Webhooks
+
+There are cases where you want to tell your API **users** that your app could call *their* app (sending a request) with some data, normally to **notify** of some type of **event**.
+
+This means that instead of the normal process of your users sending requests to your API, it's **your API** (or your app) that could **send requests to their system** (to their API, their app).
+
+This is normally called a **webhook**.
+
+## Webhooks steps
+
+The process normally is that **you define** in your code what is the message that you will send, the **body of the request**.
+
+You also define in some way at which **moments** your app will send those requests or events.
+
+And **your users** define in some way (for example in a web dashboard somewhere) the **URL** where your app should send those requests.
+
+All the **logic** about how to register the URLs for webhooks and the code to actually send those requests is up to you. You write it however you want to in **your own code**.
+
+## Documenting webhooks with **FastAPI** and OpenAPI
+
+With **FastAPI**, using OpenAPI, you can define the names of these webhooks, the types of HTTP operations that your app can send (e.g. `POST`, `PUT`, etc.) and the request **bodies** that your app would send.
+
+This can make it a lot easier for your users to **implement their APIs** to receive your **webhook** requests, they might even be able to autogenerate some of their own API code.
+
+!!! info
+ Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0` and above.
+
+## An app with webhooks
+
+When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`.
+
+```Python hl_lines="9-13 36-53"
+{!../../../docs_src/openapi_webhooks/tutorial001.py!}
+```
+
+The webhooks that you define will end up in the **OpenAPI** schema and the automatic **docs UI**.
+
+!!! info
+ The `app.webhooks` object is actually just an `APIRouter`, the same type you would use when structuring your app with multiple files.
+
+Notice that with webhooks you are actually not declaring a *path* (like `/items/`), the text you pass there is just an **identifier** of the webhook (the name of the event), for example in `@app.webhooks.post("new-subscription")`, the webhook name is `new-subscription`.
+
+This is because it is expected that **your users** would define the actual **URL path** where they want to receive the webhook request in some other way (e.g. a web dashboard).
+
+### Check the docs
+
+Now you can start your app with Uvicorn and go to http://127.0.0.1:8000/docs.
+
+You will see your docs have the normal *path operations* and now also some **webhooks**:
+
+
From 1d3a76ee649eb2f513a40807b2afa17d8160cdef Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:44 +0800
Subject: [PATCH 020/163] New translations
path-operation-advanced-configuration.md (Chinese Simplified)
---
.../path-operation-advanced-configuration.md | 179 ++++++++++++++++--
1 file changed, 159 insertions(+), 20 deletions(-)
diff --git a/docs/zh/docs/advanced/path-operation-advanced-configuration.md b/docs/zh/docs/advanced/path-operation-advanced-configuration.md
index 7da9f251e30db..f8bffadf4ffcf 100644
--- a/docs/zh/docs/advanced/path-operation-advanced-configuration.md
+++ b/docs/zh/docs/advanced/path-operation-advanced-configuration.md
@@ -1,53 +1,192 @@
-# 路径操作的高级配置
+# Path Operation Advanced Configuration
-## OpenAPI 的 operationId
+## OpenAPI operationId
!!! warning
- 如果你并非 OpenAPI 的「专家」,你可能不需要这部分内容。
+ If you are not an "expert" in OpenAPI, you probably don't need this.
-你可以在路径操作中通过参数 `operation_id` 设置要使用的 OpenAPI `operationId`。
+You can set the OpenAPI `operationId` to be used in your *path operation* with the parameter `operation_id`.
-务必确保每个操作路径的 `operation_id` 都是唯一的。
+You would have to make sure that it is unique for each operation.
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
```
-### 使用 *路径操作函数* 的函数名作为 operationId
+### Using the *path operation function* name as the operationId
-如果你想用你的 API 的函数名作为 `operationId` 的名字,你可以遍历一遍 API 的函数名,然后使用他们的 `APIRoute.name` 重写每个 *路径操作* 的 `operation_id`。
+If you want to use your APIs' function names as `operationId`s, you can iterate over all of them and override each *path operation's* `operation_id` using their `APIRoute.name`.
-你应该在添加了所有 *路径操作* 之后执行此操作。
+You should do it after adding all your *path operations*.
-```Python hl_lines="2 12 13 14 15 16 17 18 19 20 21 24"
+```Python hl_lines="2 12-21 24"
{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
```
!!! tip
- 如果你手动调用 `app.openapi()`,你应该在此之前更新 `operationId`。
+ If you manually call `app.openapi()`, you should update the `operationId`s before that.
!!! warning
- 如果你这样做,务必确保你的每个 *路径操作函数* 的名字唯一。
+ If you do this, you have to make sure each one of your *path operation functions* has a unique name.
- 即使它们在不同的模块中(Python 文件)。
+ Even if they are in different modules (Python files).
-## 从 OpenAPI 中排除
+## Exclude from OpenAPI
-使用参数 `include_in_schema` 并将其设置为 `False` ,来从生成的 OpenAPI 方案中排除一个 *路径操作*(这样一来,就从自动化文档系统中排除掉了)。
+To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`:
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
```
-## docstring 的高级描述
+## Advanced description from docstring
-你可以限制 *路径操作函数* 的 `docstring` 中用于 OpenAPI 的行数。
+You can limit the lines used from the docstring of a *path operation function* for OpenAPI.
-添加一个 `\f` (一个「换页」的转义字符)可以使 **FastAPI** 在那一位置截断用于 OpenAPI 的输出。
+Adding an `\f` (an escaped "form feed" character) causes **FastAPI** to truncate the output used for OpenAPI at this point.
-剩余部分不会出现在文档中,但是其他工具(比如 Sphinx)可以使用剩余部分。
+It won't show up in the documentation, but other tools (such as Sphinx) will be able to use the rest.
-
-```Python hl_lines="19 20 21 22 23 24 25 26 27 28 29"
+```Python hl_lines="19-29"
{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
```
+
+## Additional Responses
+
+You probably have seen how to declare the `response_model` and `status_code` for a *path operation*.
+
+That defines the metadata about the main response of a *path operation*.
+
+You can also declare additional responses with their models, status codes, etc.
+
+There's a whole chapter here in the documentation about it, you can read it at [Additional Responses in OpenAPI](./additional-responses.md){.internal-link target=_blank}.
+
+## OpenAPI Extra
+
+When you declare a *path operation* in your application, **FastAPI** automatically generates the relevant metadata about that *path operation* to be included in the OpenAPI schema.
+
+!!! note "Technical details"
+ In the OpenAPI specification it is called the Operation Object.
+
+It has all the information about the *path operation* and is used to generate the automatic documentation.
+
+It includes the `tags`, `parameters`, `requestBody`, `responses`, etc.
+
+This *path operation*-specific OpenAPI schema is normally generated automatically by **FastAPI**, but you can also extend it.
+
+!!! tip
+ This is a low level extension point.
+
+ If you only need to declare additional responses, a more convenient way to do it is with [Additional Responses in OpenAPI](./additional-responses.md){.internal-link target=_blank}.
+
+You can extend the OpenAPI schema for a *path operation* using the parameter `openapi_extra`.
+
+### OpenAPI Extensions
+
+This `openapi_extra` can be helpful, for example, to declare [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
+
+```Python hl_lines="6"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial005.py!}
+```
+
+If you open the automatic API docs, your extension will show up at the bottom of the specific *path operation*.
+
+
+
+And if you see the resulting OpenAPI (at `/openapi.json` in your API), you will see your extension as part of the specific *path operation* too:
+
+```JSON hl_lines="22"
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "FastAPI",
+ "version": "0.1.0"
+ },
+ "paths": {
+ "/items/": {
+ "get": {
+ "summary": "Read Items",
+ "operationId": "read_items_items__get",
+ "responses": {
+ "200": {
+ "description": "Successful Response",
+ "content": {
+ "application/json": {
+ "schema": {}
+ }
+ }
+ }
+ },
+ "x-aperture-labs-portal": "blue"
+ }
+ }
+ }
+}
+```
+
+### Custom OpenAPI *path operation* schema
+
+The dictionary in `openapi_extra` will be deeply merged with the automatically generated OpenAPI schema for the *path operation*.
+
+So, you could add additional data to the automatically generated schema.
+
+For example, you could decide to read and validate the request with your own code, without using the automatic features of FastAPI with Pydantic, but you could still want to define the request in the OpenAPI schema.
+
+You could do that with `openapi_extra`:
+
+```Python hl_lines="20-37 39-40"
+{!../../../docs_src/path_operation_advanced_configuration/tutorial006.py!}
+```
+
+In this example, we didn't declare any Pydantic model. In fact, the request body is not even parsed as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way.
+
+Nevertheless, we can declare the expected schema for the request body.
+
+### Custom OpenAPI content type
+
+Using this same trick, you could use a Pydantic model to define the JSON Schema that is then included in the custom OpenAPI schema section for the *path operation*.
+
+And you could do this even if the data type in the request is not JSON.
+
+For example, in this application we don't use FastAPI's integrated functionality to extract the JSON Schema from Pydantic models nor the automatic validation for JSON. In fact, we are declaring the request content type as YAML, not JSON:
+
+=== "Pydantic v2"
+
+ ```Python hl_lines="17-22 24"
+ {!> ../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
+ ```
+
+=== "Pydantic v1"
+
+ ```Python hl_lines="17-22 24"
+ {!> ../../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
+ ```
+
+!!! info
+ In Pydantic version 1 the method to get the JSON Schema for a model was called `Item.schema()`, in Pydantic version 2, the method is called `Item.model_schema_json()`.
+
+Nevertheless, although we are not using the default integrated functionality, we are still using a Pydantic model to manually generate the JSON Schema for the data that we want to receive in YAML.
+
+Then we use the request directly, and extract the body as `bytes`. This means that FastAPI won't even try to parse the request payload as JSON.
+
+And then in our code, we parse that YAML content directly, and then we are again using the same Pydantic model to validate the YAML content:
+
+=== "Pydantic v2"
+
+ ```Python hl_lines="26-33"
+ {!> ../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
+ ```
+
+=== "Pydantic v1"
+
+ ```Python hl_lines="26-33"
+ {!> ../../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
+ ```
+
+!!! info
+ In Pydantic version 1 the method to parse and validate an object was `Item.parse_obj()`, in Pydantic version 2, the method is called `Item.model_validate()`.
+
+!!! tip
+ Here we re-use the same Pydantic model.
+
+ But the same way, we could have validated it in some other way.
From 439b6faea51984ed9f871016a676bc941f989be4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:45 +0800
Subject: [PATCH 021/163] New translations response-change-status-code.md
(Chinese Simplified)
---
.../advanced/response-change-status-code.md | 30 ++++++++++---------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md
index a289cf20178f0..979cef3f05367 100644
--- a/docs/zh/docs/advanced/response-change-status-code.md
+++ b/docs/zh/docs/advanced/response-change-status-code.md
@@ -1,31 +1,33 @@
-# 响应 - 更改状态码
+# Response - Change Status Code
-你可能之前已经了解到,你可以设置默认的[响应状态码](../tutorial/response-status-code.md){.internal-link target=_blank}。
+You probably read before that you can set a default [Response Status Code](../tutorial/response-status-code.md){.internal-link target=_blank}.
-但在某些情况下,你需要返回一个不同于默认值的状态码。
+But in some cases you need to return a different status code than the default.
-## 使用场景
+## Use case
-例如,假设你想默认返回一个HTTP状态码为“OK”`200`。
+For example, imagine that you want to return an HTTP status code of "OK" `200` by default.
-但如果数据不存在,你想创建它,并返回一个HTTP状态码为“CREATED”`201`。
+But if the data didn't exist, you want to create it, and return an HTTP status code of "CREATED" `201`.
-但你仍然希望能够使用`response_model`过滤和转换你返回的数据。
+But you still want to be able to filter and convert the data you return with a `response_model`.
-对于这些情况,你可以使用一个`Response`参数。
+For those cases, you can use a `Response` parameter.
-## 使用 `Response` 参数
+## Use a `Response` parameter
-你可以在你的*路径操作函数*中声明一个`Response`类型的参数(就像你可以为cookies和头部做的那样)。
+You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies and headers).
-然后你可以在这个*临时*响应对象中设置`status_code`。
+And then you can set the `status_code` in that *temporal* response object.
```Python hl_lines="1 9 12"
{!../../../docs_src/response_change_status_code/tutorial001.py!}
```
-然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
+And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
-**FastAPI**将使用这个临时响应来提取状态码(也包括cookies和头部),并将它们放入包含你返回的值的最终响应中,该响应由任何`response_model`过滤。
+And if you declared a `response_model`, it will still be used to filter and convert the object you returned.
-你也可以在依赖项中声明`Response`参数,并在其中设置状态码。但请注意,最后设置的状态码将会生效。
+**FastAPI** will use that *temporal* response to extract the status code (also cookies and headers), and will put them in the final response that contains the value you returned, filtered by any `response_model`.
+
+You can also declare the `Response` parameter in dependencies, and set the status code in them. But have in mind that the last one to be set will win.
From af622ebd3d31a84075f70d5465b4287fc6206c2d Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:46 +0800
Subject: [PATCH 022/163] New translations response-cookies.md (Chinese
Simplified)
---
docs/zh/docs/advanced/response-cookies.md | 46 ++++++++++++-----------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md
index 3e53c53191a4c..328094c9b5f7a 100644
--- a/docs/zh/docs/advanced/response-cookies.md
+++ b/docs/zh/docs/advanced/response-cookies.md
@@ -1,47 +1,49 @@
-# 响应Cookies
+# Response Cookies
-## 使用 `Response` 参数
+## Use a `Response` parameter
-你可以在 *路径函数* 中定义一个类型为 `Response`的参数,这样你就可以在这个临时响应对象中设置cookie了。
+You can declare a parameter of type `Response` in your *path operation function*.
+
+And then you can set cookies in that *temporal* response object.
```Python hl_lines="1 8-9"
{!../../../docs_src/response_cookies/tutorial002.py!}
```
-而且你还可以根据你的需要响应不同的对象,比如常用的 `dict`,数据库model等。
+And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
-如果你定义了 `response_model`,程序会自动根据`response_model`来过滤和转换你响应的对象。
+And if you declared a `response_model`, it will still be used to filter and convert the object you returned.
-**FastAPI** 会使用这个 *临时* 响应对象去装在这些cookies信息 (同样还有headers和状态码等信息), 最终会将这些信息和通过`response_model`转化过的数据合并到最终的响应里。
+**FastAPI** will use that *temporal* response to extract the cookies (also headers and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`.
-你也可以在depend中定义`Response`参数,并设置cookie和header。
+You can also declare the `Response` parameter in dependencies, and set cookies (and headers) in them.
-## 直接响应 `Response`
+## Return a `Response` directly
-你还可以在直接响应`Response`时直接创建cookies。
+You can also create cookies when returning a `Response` directly in your code.
-你可以参考[Return a Response Directly](response-directly.md){.internal-link target=_blank}来创建response
+To do that, you can create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank}.
-然后设置Cookies,并返回:
+Then set Cookies in it, and then return it:
```Python hl_lines="10-12"
{!../../../docs_src/response_cookies/tutorial001.py!}
```
!!! tip
- 需要注意,如果你直接反馈一个response对象,而不是使用`Response`入参,FastAPI则会直接反馈你封装的response对象。
-
- 所以你需要确保你响应数据类型的正确性,如:你可以使用`JSONResponse`来兼容JSON的场景。
-
- 同时,你也应当仅反馈通过`response_model`过滤过的数据。
+ Have in mind that if you return a response directly instead of using the `Response` parameter, FastAPI will return it directly.
-### 更多信息
+ So, you will have to make sure your data is of the correct type. E.g. it is compatible with JSON, if you are returning a `JSONResponse`.
+
+ And also that you are not sending any data that should have been filtered by a `response_model`.
-!!! note "技术细节"
- 你也可以使用`from starlette.responses import Response` 或者 `from starlette.responses import JSONResponse`。
+### More info
- 为了方便开发者,**FastAPI** 封装了相同数据类型,如`starlette.responses` 和 `fastapi.responses`。不过大部分response对象都是直接引用自Starlette。
+!!! note "Technical Details"
+ You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
- 因为`Response`对象可以非常便捷的设置headers和cookies,所以 **FastAPI** 同时也封装了`fastapi.Response`。
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+
+ And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
-如果你想查看所有可用的参数和选项,可以参考 Starlette帮助文档
+To see all the available parameters and options, check the documentation in Starlette.
From 751f7cf362db13f8a2d4d93b56e2ce5f30ffa971 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:47 +0800
Subject: [PATCH 023/163] New translations response-directly.md (Chinese
Simplified)
---
docs/zh/docs/advanced/response-directly.md | 61 +++++++++++-----------
1 file changed, 30 insertions(+), 31 deletions(-)
diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md
index 797a878eb923b..8836140ecf7ee 100644
--- a/docs/zh/docs/advanced/response-directly.md
+++ b/docs/zh/docs/advanced/response-directly.md
@@ -1,64 +1,63 @@
-# 直接返回响应
+# Return a Response Directly
-当你创建一个 **FastAPI** *路径操作* 时,你可以正常返回以下任意一种数据:`dict`,`list`,Pydantic 模型,数据库模型等等。
+When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc.
-**FastAPI** 默认会使用 `jsonable_encoder` 将这些类型的返回值转换成 JSON 格式,`jsonable_encoder` 在 [JSON 兼容编码器](../tutorial/encoder.md){.internal-link target=_blank} 中有阐述。
+By default, **FastAPI** would automatically convert that return value to JSON using the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
-然后,**FastAPI** 会在后台将这些兼容 JSON 的数据(比如字典)放到一个 `JSONResponse` 中,该 `JSONResponse` 会用来发送响应给客户端。
+Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a `JSONResponse` that would be used to send the response to the client.
-但是你可以在你的 *路径操作* 中直接返回一个 `JSONResponse`。
+But you can return a `JSONResponse` directly from your *path operations*.
-直接返回响应可能会有用处,比如返回自定义的响应头和 cookies。
+It might be useful, for example, to return custom headers or cookies.
-## 返回 `Response`
+## Return a `Response`
-事实上,你可以返回任意 `Response` 或者任意 `Response` 的子类。
+In fact, you can return any `Response` or any sub-class of it.
-!!! tip "小贴士"
- `JSONResponse` 本身是一个 `Response` 的子类。
+!!! tip
+ `JSONResponse` itself is a sub-class of `Response`.
-当你返回一个 `Response` 时,**FastAPI** 会直接传递它。
+And when you return a `Response`, **FastAPI** will pass it directly.
-**FastAPI** 不会用 Pydantic 模型做任何数据转换,不会将响应内容转换成任何类型,等等。
+It won't do any data conversion with Pydantic models, it won't convert the contents to any type, etc.
-这种特性给你极大的可扩展性。你可以返回任何数据类型,重写任何数据声明或者校验,等等。
+This gives you a lot of flexibility. You can return any data type, override any data declaration or validation, etc.
-## 在 `Response` 中使用 `jsonable_encoder`
+## Using the `jsonable_encoder` in a `Response`
-由于 **FastAPI** 并未对你返回的 `Response` 做任何改变,你必须确保你已经准备好响应内容。
+Because **FastAPI** doesn't do any change to a `Response` you return, you have to make sure it's contents are ready for it.
-例如,如果不首先将 Pydantic 模型转换为 `dict`,并将所有数据类型(如 `datetime`、`UUID` 等)转换为兼容 JSON 的类型,则不能将其放入JSONResponse中。
+For example, you cannot put a Pydantic model in a `JSONResponse` without first converting it to a `dict` with all the data types (like `datetime`, `UUID`, etc) converted to JSON-compatible types.
-对于这些情况,在将数据传递给响应之前,你可以使用 `jsonable_encoder` 来转换你的数据。
+For those cases, you can use the `jsonable_encoder` to convert your data before passing it to a response:
-
-```Python hl_lines="4 6 20 21"
+```Python hl_lines="6-7 21-22"
{!../../../docs_src/response_directly/tutorial001.py!}
```
-!!! note "技术细节"
- 你也可以使用 `from starlette.responses import JSONResponse`。
+!!! note "Technical Details"
+ You could also use `from starlette.responses import JSONResponse`.
- 出于方便,**FastAPI** 会提供与 `starlette.responses` 相同的 `fastapi.responses` 给开发者。但是大多数可用的响应都直接来自 Starlette。
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
-## 返回自定义 `Response`
+## Returning a custom `Response`
-上面的例子展示了需要的所有部分,但还不够实用,因为你本可以只是直接返回 `item`,而**FastAPI** 默认帮你把这个 `item` 放到 `JSONResponse` 中,又默认将其转换成了 `dict`等等。
+The example above shows all the parts you need, but it's not very useful yet, as you could have just returned the `item` directly, and **FastAPI** would put it in a `JSONResponse` for you, converting it to a `dict`, etc. All that by default.
-现在,让我们看看你如何才能返回一个自定义的响应。
+Now, let's see how you could use that to return a custom response.
-假设你想要返回一个 XML 响应。
+Let's say that you want to return an XML response.
-你可以把你的 XML 内容放到一个字符串中,放到一个 `Response` 中,然后返回。
+You could put your XML content in a string, put it in a `Response`, and return it:
```Python hl_lines="1 18"
{!../../../docs_src/response_directly/tutorial002.py!}
```
-## 说明
+## Notes
-当你直接返回 `Response` 时,它的数据既没有校验,又不会进行转换(序列化),也不会自动生成文档。
+When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically.
-但是你仍可以参考 [OpenApI 中的额外响应](additional-responses.md){.internal-link target=_blank} 给响应编写文档。
+But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
-在后续的章节中你可以了解到如何使用/声明这些自定义的 `Response` 的同时还保留自动化的数据转换和文档等。
+You can see in later sections how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc.
From 1f9f7f9760c4d435c18221d348cdde815b4ab501 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:49 +0800
Subject: [PATCH 024/163] New translations response-headers.md (Chinese
Simplified)
---
docs/zh/docs/advanced/response-headers.md | 41 ++++++++++++-----------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md
index 85dab15ac092f..99c280024f59d 100644
--- a/docs/zh/docs/advanced/response-headers.md
+++ b/docs/zh/docs/advanced/response-headers.md
@@ -1,39 +1,42 @@
-# 响应头
+# Response Headers
-## 使用 `Response` 参数
+## Use a `Response` parameter
-你可以在你的*路径操作函数*中声明一个`Response`类型的参数(就像你可以为cookies做的那样)。
+You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies).
+
+And then you can set headers in that *temporal* response object.
-然后你可以在这个*临时*响应对象中设置头部。
```Python hl_lines="1 7-8"
{!../../../docs_src/response_headers/tutorial002.py!}
```
-然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
+And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
+
+And if you declared a `response_model`, it will still be used to filter and convert the object you returned.
+
+**FastAPI** will use that *temporal* response to extract the headers (also cookies and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`.
-**FastAPI**将使用这个临时响应来提取头部(也包括cookies和状态码),并将它们放入包含你返回的值的最终响应中,该响应由任何`response_model`过滤。
+You can also declare the `Response` parameter in dependencies, and set headers (and cookies) in them.
-你也可以在依赖项中声明`Response`参数,并在其中设置头部(和cookies)。
+## Return a `Response` directly
-## 直接返回 `Response`
+You can also add headers when you return a `Response` directly.
-你也可以在直接返回`Response`时添加头部。
+Create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank} and pass the headers as an additional parameter:
-按照[直接返回响应](response-directly.md){.internal-link target=_blank}中所述创建响应,并将头部作为附加参数传递:
```Python hl_lines="10-12"
{!../../../docs_src/response_headers/tutorial001.py!}
```
+!!! note "Technical Details"
+ You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
-!!! 注意 "技术细节"
- 你也可以使用`from starlette.responses import Response`或`from starlette.responses import JSONResponse`。
-
- **FastAPI**提供了与`fastapi.responses`相同的`starlette.responses`,只是为了方便开发者。但是,大多数可用的响应都直接来自Starlette。
-
- 由于`Response`经常用于设置头部和cookies,因此**FastAPI**还在`fastapi.Response`中提供了它。
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+
+ And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
-## 自定义头部
+## Custom Headers
-请注意,可以使用'X-'前缀添加自定义专有头部。
+Have in mind that custom proprietary headers can be added using the 'X-' prefix.
-但是,如果你有自定义头部,你希望浏览器中的客户端能够看到它们,你需要将它们添加到你的CORS配置中(在[CORS(跨源资源共享)](../tutorial/cors.md){.internal-link target=_blank}中阅读更多),使用在Starlette的CORS文档中记录的`expose_headers`参数。
+But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in Starlette's CORS docs.
From 659550f9ae5495ce797a9042f713670936e14114 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:49 +0800
Subject: [PATCH 025/163] New translations http-basic-auth.md (Chinese
Simplified)
---
.../docs/advanced/security/http-basic-auth.md | 164 ++++++++++++++++++
1 file changed, 164 insertions(+)
create mode 100644 docs/zh/docs/advanced/security/http-basic-auth.md
diff --git a/docs/zh/docs/advanced/security/http-basic-auth.md b/docs/zh/docs/advanced/security/http-basic-auth.md
new file mode 100644
index 0000000000000..c24dfc8c7e25d
--- /dev/null
+++ b/docs/zh/docs/advanced/security/http-basic-auth.md
@@ -0,0 +1,164 @@
+# HTTP Basic Auth
+
+For the simplest cases, you can use HTTP Basic Auth.
+
+In HTTP Basic Auth, the application expects a header that contains a username and a password.
+
+If it doesn't receive it, it returns an HTTP 401 "Unauthorized" error.
+
+And returns a header `WWW-Authenticate` with a value of `Basic`, and an optional `realm` parameter.
+
+That tells the browser to show the integrated prompt for a username and password.
+
+Then, when you type that username and password, the browser sends them in the header automatically.
+
+## Simple HTTP Basic Auth
+
+* Import `HTTPBasic` and `HTTPBasicCredentials`.
+* Create a "`security` scheme" using `HTTPBasic`.
+* Use that `security` with a dependency in your *path operation*.
+* It returns an object of type `HTTPBasicCredentials`:
+ * It contains the `username` and `password` sent.
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 8 12"
+ {!> ../../../docs_src/security/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="2 7 11"
+ {!> ../../../docs_src/security/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="2 6 10"
+ {!> ../../../docs_src/security/tutorial006.py!}
+ ```
+
+When you try to open the URL for the first time (or click the "Execute" button in the docs) the browser will ask you for your username and password:
+
+
+
+## Check the username
+
+Here's a more complete example.
+
+Use a dependency to check if the username and password are correct.
+
+For this, use the Python standard module `secrets` to check the username and password.
+
+`secrets.compare_digest()` needs to take `bytes` or a `str` that only contains ASCII characters (the ones in English), this means it wouldn't work with characters like `á`, as in `Sebastián`.
+
+To handle that, we first convert the `username` and `password` to `bytes` encoding them with UTF-8.
+
+Then we can use `secrets.compare_digest()` to ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`.
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="1 12-24"
+ {!> ../../../docs_src/security/tutorial007_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 12-24"
+ {!> ../../../docs_src/security/tutorial007_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1 11-21"
+ {!> ../../../docs_src/security/tutorial007.py!}
+ ```
+
+This would be similar to:
+
+```Python
+if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
+ # Return some error
+ ...
+```
+
+But by using the `secrets.compare_digest()` it will be secure against a type of attacks called "timing attacks".
+
+### Timing Attacks
+
+But what's a "timing attack"?
+
+Let's imagine some attackers are trying to guess the username and password.
+
+And they send a request with a username `johndoe` and a password `love123`.
+
+Then the Python code in your application would be equivalent to something like:
+
+```Python
+if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+But right at the moment Python compares the first `j` in `johndoe` to the first `s` in `stanleyjobson`, it will return `False`, because it already knows that those two strings are not the same, thinking that "there's no need to waste more computation comparing the rest of the letters". And your application will say "incorrect user or password".
+
+But then the attackers try with username `stanleyjobsox` and password `love123`.
+
+And your application code does something like:
+
+```Python
+if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
+ ...
+```
+
+Python will have to compare the whole `stanleyjobso` in both `stanleyjobsox` and `stanleyjobson` before realizing that both strings are not the same. So it will take some extra microseconds to reply back "incorrect user or password".
+
+#### The time to answer helps the attackers
+
+At that point, by noticing that the server took some microseconds longer to send the "incorrect user or password" response, the attackers will know that they got _something_ right, some of the initial letters were right.
+
+And then they can try again knowing that it's probably something more similar to `stanleyjobsox` than to `johndoe`.
+
+#### A "professional" attack
+
+Of course, the attackers would not try all this by hand, they would write a program to do it, possibly with thousands or millions of tests per second. And would get just one extra correct letter at a time.
+
+But doing that, in some minutes or hours the attackers would have guessed the correct username and password, with the "help" of our application, just using the time taken to answer.
+
+#### Fix it with `secrets.compare_digest()`
+
+But in our code we are actually using `secrets.compare_digest()`.
+
+In short, it will take the same time to compare `stanleyjobsox` to `stanleyjobson` than it takes to compare `johndoe` to `stanleyjobson`. And the same for the password.
+
+That way, using `secrets.compare_digest()` in your application code, it will be safe against this whole range of security attacks.
+
+### Return the error
+
+After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="26-30"
+ {!> ../../../docs_src/security/tutorial007_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="26-30"
+ {!> ../../../docs_src/security/tutorial007_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="23-27"
+ {!> ../../../docs_src/security/tutorial007.py!}
+ ```
From 17b5f9b84b7cf112d6974ff9112872a5b7f3882c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:50 +0800
Subject: [PATCH 026/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/advanced/security/index.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/docs/zh/docs/advanced/security/index.md b/docs/zh/docs/advanced/security/index.md
index fdc8075c765ba..c18baf64b0d27 100644
--- a/docs/zh/docs/advanced/security/index.md
+++ b/docs/zh/docs/advanced/security/index.md
@@ -1,16 +1,16 @@
-# 高级安全
+# Advanced Security
-## 附加特性
+## Additional Features
-除 [教程 - 用户指南: 安全性](../../tutorial/security/){.internal-link target=_blank} 中涵盖的功能之外,还有一些额外的功能来处理安全性.
+There are some extra features to handle security apart from the ones covered in the [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
-!!! tip "小贴士"
- 接下来的章节 **并不一定是 "高级的"**.
+!!! tip
+ The next sections are **not necessarily "advanced"**.
- 而且对于你的使用场景来说,解决方案很可能就在其中。
+ And it's possible that for your use case, the solution is in one of them.
-## 先阅读教程
+## Read the Tutorial first
-接下来的部分假设你已经阅读了主要的 [教程 - 用户指南: 安全性](../../tutorial/security/){.internal-link target=_blank}.
+The next sections assume you already read the main [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
-它们都基于相同的概念,但支持一些额外的功能.
+They are all based on the same concepts, but allow some extra functionalities.
From 5076bd2a2257dfc1dbc9e628900408825f55debb Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:51 +0800
Subject: [PATCH 027/163] New translations oauth2-scopes.md (Chinese
Simplified)
---
.../docs/advanced/security/oauth2-scopes.md | 598 ++++++++++++++++++
1 file changed, 598 insertions(+)
create mode 100644 docs/zh/docs/advanced/security/oauth2-scopes.md
diff --git a/docs/zh/docs/advanced/security/oauth2-scopes.md b/docs/zh/docs/advanced/security/oauth2-scopes.md
new file mode 100644
index 0000000000000..3f230e9e74627
--- /dev/null
+++ b/docs/zh/docs/advanced/security/oauth2-scopes.md
@@ -0,0 +1,598 @@
+# OAuth2 scopes
+
+You can use OAuth2 scopes directly with **FastAPI**, they are integrated to work seamlessly.
+
+This would allow you to have a more fine-grained permission system, following the OAuth2 standard, integrated into your OpenAPI application (and the API docs).
+
+OAuth2 with scopes is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, Twitter, etc. They use it to provide specific permissions to users and applications.
+
+Every time you "log in with" Facebook, Google, GitHub, Microsoft, Twitter, that application is using OAuth2 with scopes.
+
+In this section you will see how to manage authentication and authorization with the same OAuth2 with scopes in your **FastAPI** application.
+
+!!! warning
+ This is a more or less advanced section. If you are just starting, you can skip it.
+
+ You don't necessarily need OAuth2 scopes, and you can handle authentication and authorization however you want.
+
+ But OAuth2 with scopes can be nicely integrated into your API (with OpenAPI) and your API docs.
+
+ Nevertheless, you still enforce those scopes, or any other security/authorization requirement, however you need, in your code.
+
+ In many cases, OAuth2 with scopes can be an overkill.
+
+ But if you know you need it, or you are curious, keep reading.
+
+## OAuth2 scopes and OpenAPI
+
+The OAuth2 specification defines "scopes" as a list of strings separated by spaces.
+
+The content of each of these strings can have any format, but should not contain spaces.
+
+These scopes represent "permissions".
+
+In OpenAPI (e.g. the API docs), you can define "security schemes".
+
+When one of these security schemes uses OAuth2, you can also declare and use scopes.
+
+Each "scope" is just a string (without spaces).
+
+They are normally used to declare specific security permissions, for example:
+
+* `users:read` or `users:write` are common examples.
+* `instagram_basic` is used by Facebook / Instagram.
+* `https://www.googleapis.com/auth/drive` is used by Google.
+
+!!! info
+ In OAuth2 a "scope" is just a string that declares a specific permission required.
+
+ It doesn't matter if it has other characters like `:` or if it is a URL.
+
+ Those details are implementation specific.
+
+ For OAuth2 they are just strings.
+
+## Global view
+
+First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="4 8 12 46 64 105 107-115 121-124 128-134 139 155"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="2 4 8 12 47 65 106 108-116 122-125 129-135 140 156"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3 7 11 45 63 104 106-114 120-123 127-133 138 152"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 153"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 153"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+Now let's review those changes step by step.
+
+## OAuth2 Security scheme
+
+The first change is that now we are declaring the OAuth2 security scheme with two available scopes, `me` and `items`.
+
+The `scopes` parameter receives a `dict` with each scope as a key and the description as the value:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="62-65"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="62-65"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="63-66"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="61-64"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="62-65"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="62-65"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+Because we are now declaring those scopes, they will show up in the API docs when you log-in/authorize.
+
+And you will be able to select which scopes you want to give access to: `me` and `items`.
+
+This is the same mechanism used when you give permissions while logging in with Facebook, Google, GitHub, etc:
+
+
+
+## JWT token with scopes
+
+Now, modify the token *path operation* to return the scopes requested.
+
+We are still using the same `OAuth2PasswordRequestForm`. It includes a property `scopes` with a `list` of `str`, with each scope it received in the request.
+
+And we return the scopes as part of the JWT token.
+
+!!! danger
+ For simplicity, here we are just adding the scopes received directly to the token.
+
+ But in your application, for security, you should make sure you only add the scopes that the user is actually able to have, or the ones you have predefined.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="155"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="155"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="156"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="152"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="153"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="153"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+## Declare scopes in *path operations* and dependencies
+
+Now we declare that the *path operation* for `/users/me/items/` requires the scope `items`.
+
+For this, we import and use `Security` from `fastapi`.
+
+You can use `Security` to declare dependencies (just like `Depends`), but `Security` also receives a parameter `scopes` with a list of scopes (strings).
+
+In this case, we pass a dependency function `get_current_active_user` to `Security` (the same way we would do with `Depends`).
+
+But we also pass a `list` of scopes, in this case with just one scope: `items` (it could have more).
+
+And the dependency function `get_current_active_user` can also declare sub-dependencies, not only with `Depends` but also with `Security`. Declaring its own sub-dependency function (`get_current_user`), and more scope requirements.
+
+In this case, it requires the scope `me` (it could require more than one scope).
+
+!!! note
+ You don't necessarily need to add different scopes in different places.
+
+ We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="4 139 170"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 139 170"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 140 171"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3 138 165"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4 139 166"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4 139 166"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+!!! info "Technical Details"
+ `Security` is actually a subclass of `Depends`, and it has just one extra parameter that we'll see later.
+
+ But by using `Security` instead of `Depends`, **FastAPI** will know that it can declare security scopes, use them internally, and document the API with OpenAPI.
+
+ But when you import `Query`, `Path`, `Depends`, `Security` and others from `fastapi`, those are actually functions that return special classes.
+
+## Use `SecurityScopes`
+
+Now update the dependency `get_current_user`.
+
+This is the one used by the dependencies above.
+
+Here's were we are using the same OAuth2 scheme we created before, declaring it as a dependency: `oauth2_scheme`.
+
+Because this dependency function doesn't have any scope requirements itself, we can use `Depends` with `oauth2_scheme`, we don't have to use `Security` when we don't need to specify security scopes.
+
+We also declare a special parameter of type `SecurityScopes`, imported from `fastapi.security`.
+
+This `SecurityScopes` class is similar to `Request` (`Request` was used to get the request object directly).
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="8 105"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="8 105"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8 106"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7 104"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8 105"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8 105"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+## Use the `scopes`
+
+The parameter `security_scopes` will be of type `SecurityScopes`.
+
+It will have a property `scopes` with a list containing all the scopes required by itself and all the dependencies that use this as a sub-dependency. That means, all the "dependants"... this might sound confusing, it is explained again later below.
+
+The `security_scopes` object (of class `SecurityScopes`) also provides a `scope_str` attribute with a single string, containing those scopes separated by spaces (we are going to use it).
+
+We create an `HTTPException` that we can re-use (`raise`) later at several points.
+
+In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in the `WWW-Authenticate` header (this is part of the spec).
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="105 107-115"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="105 107-115"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="106 108-116"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="104 106-114"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="105 107-115"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="105 107-115"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+## Verify the `username` and data shape
+
+We verify that we get a `username`, and extract the scopes.
+
+And then we validate that data with the Pydantic model (catching the `ValidationError` exception), and if we get an error reading the JWT token or validating the data with Pydantic, we raise the `HTTPException` we created before.
+
+For that, we update the Pydantic model `TokenData` with a new property `scopes`.
+
+By validating the data with Pydantic we can make sure that we have, for example, exactly a `list` of `str` with the scopes and a `str` with the `username`.
+
+Instead of, for example, a `dict`, or something else, as it could break the application at some point later, making it a security risk.
+
+We also verify that we have a user with that username, and if not, we raise that same exception we created before.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="46 116-127"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="46 116-127"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="47 117-128"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="45 115-126"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="46 116-127"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="46 116-127"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+## Verify the `scopes`
+
+We now verify that all the scopes required, by this dependency and all the dependants (including *path operations*), are included in the scopes provided in the token received, otherwise raise an `HTTPException`.
+
+For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="128-134"
+ {!> ../../../docs_src/security/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="128-134"
+ {!> ../../../docs_src/security/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="129-135"
+ {!> ../../../docs_src/security/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="127-133"
+ {!> ../../../docs_src/security/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="128-134"
+ {!> ../../../docs_src/security/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="128-134"
+ {!> ../../../docs_src/security/tutorial005.py!}
+ ```
+
+## Dependency tree and scopes
+
+Let's review again this dependency tree and the scopes.
+
+As the `get_current_active_user` dependency has as a sub-dependency on `get_current_user`, the scope `"me"` declared at `get_current_active_user` will be included in the list of required scopes in the `security_scopes.scopes` passed to `get_current_user`.
+
+The *path operation* itself also declares a scope, `"items"`, so this will also be in the list of `security_scopes.scopes` passed to `get_current_user`.
+
+Here's how the hierarchy of dependencies and scopes looks like:
+
+* The *path operation* `read_own_items` has:
+ * Required scopes `["items"]` with the dependency:
+ * `get_current_active_user`:
+ * The dependency function `get_current_active_user` has:
+ * Required scopes `["me"]` with the dependency:
+ * `get_current_user`:
+ * The dependency function `get_current_user` has:
+ * No scopes required by itself.
+ * A dependency using `oauth2_scheme`.
+ * A `security_scopes` parameter of type `SecurityScopes`:
+ * This `security_scopes` parameter has a property `scopes` with a `list` containing all these scopes declared above, so:
+ * `security_scopes.scopes` will contain `["me", "items"]` for the *path operation* `read_own_items`.
+ * `security_scopes.scopes` will contain `["me"]` for the *path operation* `read_users_me`, because it is declared in the dependency `get_current_active_user`.
+ * `security_scopes.scopes` will contain `[]` (nothing) for the *path operation* `read_system_status`, because it didn't declare any `Security` with `scopes`, and its dependency, `get_current_user`, doesn't declare any `scope` either.
+
+!!! tip
+ The important and "magic" thing here is that `get_current_user` will have a different list of `scopes` to check for each *path operation*.
+
+ All depending on the `scopes` declared in each *path operation* and each dependency in the dependency tree for that specific *path operation*.
+
+## More details about `SecurityScopes`
+
+You can use `SecurityScopes` at any point, and in multiple places, it doesn't have to be at the "root" dependency.
+
+It will always have the security scopes declared in the current `Security` dependencies and all the dependants for **that specific** *path operation* and **that specific** dependency tree.
+
+Because the `SecurityScopes` will have all the scopes declared by dependants, you can use it to verify that a token has the required scopes in a central dependency function, and then declare different scope requirements in different *path operations*.
+
+They will be checked independently for each *path operation*.
+
+## Check it
+
+If you open the API docs, you can authenticate and specify which scopes you want to authorize.
+
+
+
+If you don't select any scope, you will be "authenticated", but when you try to access `/users/me/` or `/users/me/items/` you will get an error saying that you don't have enough permissions. You will still be able to access `/status/`.
+
+And if you select the scope `me` but not the scope `items`, you will be able to access `/users/me/` but not `/users/me/items/`.
+
+That's what would happen to a third party application that tried to access one of these *path operations* with a token provided by a user, depending on how many permissions the user gave the application.
+
+## About third party integrations
+
+In this example we are using the OAuth2 "password" flow.
+
+This is appropriate when we are logging in to our own application, probably with our own frontend.
+
+Because we can trust it to receive the `username` and `password`, as we control it.
+
+But if you are building an OAuth2 application that others would connect to (i.e., if you are building an authentication provider equivalent to Facebook, Google, GitHub, etc.) you should use one of the other flows.
+
+The most common is the implicit flow.
+
+The most secure is the code flow, but is more complex to implement as it requires more steps. As it is more complex, many providers end up suggesting the implicit flow.
+
+!!! note
+ It's common that each authentication provider names their flows in a different way, to make it part of their brand.
+
+ But in the end, they are implementing the same OAuth2 standard.
+
+**FastAPI** includes utilities for all these OAuth2 authentication flows in `fastapi.security.oauth2`.
+
+## `Security` in decorator `dependencies`
+
+The same way you can define a `list` of `Depends` in the decorator's `dependencies` parameter (as explained in [Dependencies in path operation decorators](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), you could also use `Security` with `scopes` there.
From 6fe3493caf80e4510a89993840c270fdd4c532d0 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:52 +0800
Subject: [PATCH 028/163] New translations settings.md (Chinese Simplified)
---
docs/zh/docs/advanced/settings.md | 314 ++++++++++++++++++------------
1 file changed, 185 insertions(+), 129 deletions(-)
diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md
index 597e99a7793c3..a4a773b1fdeaf 100644
--- a/docs/zh/docs/advanced/settings.md
+++ b/docs/zh/docs/advanced/settings.md
@@ -1,34 +1,35 @@
-# 设置和环境变量
+# Settings and Environment Variables
-在许多情况下,您的应用程序可能需要一些外部设置或配置,例如密钥、数据库凭据、电子邮件服务的凭据等等。
+In many cases your application could need some external settings or configurations, for example secret keys, database credentials, credentials for email services, etc.
-这些设置中的大多数是可变的(可以更改的),比如数据库的 URL。而且许多设置可能是敏感的,比如密钥。
+Most of these settings are variable (can change), like database URLs. And many could be sensitive, like secrets.
-因此,通常会将它们提供为由应用程序读取的环境变量。
+For this reason it's common to provide them in environment variables that are read by the application.
-## 环境变量
+## Environment Variables
!!! tip
- 如果您已经知道什么是"环境变量"以及如何使用它们,请随意跳到下面的下一节。
+ If you already know what "environment variables" are and how to use them, feel free to skip to the next section below.
-环境变量(也称为"env var")是一种存在于 Python 代码之外、存在于操作系统中的变量,可以被您的 Python 代码(或其他程序)读取。
+An environment variable (also known as "env var") is a variable that lives outside of the Python code, in the operating system, and could be read by your Python code (or by other programs as well).
-您可以在 shell 中创建和使用环境变量,而无需使用 Python:
+You can create and use environment variables in the shell, without needing Python:
-=== "Linux、macOS、Windows Bash"
+=== "Linux, macOS, Windows Bash"
+
+And then, open the docs for the sub-application, at http://127.0.0.1:8000/subapi/docs.
+
+You will see the automatic API docs for the sub-application, including only its own _path operations_, all under the correct sub-path prefix `/subapi`:
+
+
+
+If you try interacting with any of the two user interfaces, they will work correctly, because the browser will be able to talk to each specific app or sub-app.
+
+### Technical Details: `root_path`
+
+When you mount a sub-application as described above, FastAPI will take care of communicating the mount path for the sub-application using a mechanism from the ASGI specification called a `root_path`.
+
+That way, the sub-application will know to use that path prefix for the docs UI.
+
+And the sub-application could also have its own mounted sub-applications and everything would work correctly, because FastAPI handles all these `root_path`s automatically.
+
+You will learn more about the `root_path` and how to use it explicitly in the section about [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank}.
From e0368590211fe3af0a84eb324b50bc0fd6fa874b Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:36:55 +0800
Subject: [PATCH 031/163] New translations templates.md (Chinese Simplified)
---
docs/zh/docs/advanced/templates.md | 77 ++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100644 docs/zh/docs/advanced/templates.md
diff --git a/docs/zh/docs/advanced/templates.md b/docs/zh/docs/advanced/templates.md
new file mode 100644
index 0000000000000..38618aeeb09cd
--- /dev/null
+++ b/docs/zh/docs/advanced/templates.md
@@ -0,0 +1,77 @@
+# Templates
+
+You can use any template engine you want with **FastAPI**.
+
+A common choice is Jinja2, the same one used by Flask and other tools.
+
+There are utilities to configure it easily that you can use directly in your **FastAPI** application (provided by Starlette).
+
+## Install dependencies
+
+Install `jinja2`:
+
+
+You will see a simple page like:
-您可以在输入框中输入消息并发送:
+
-
+You can type messages in the input box, and send them:
-您的 **FastAPI** 应用程序将回复:
+
-
+And your **FastAPI** application with WebSockets will respond back:
-您可以发送(和接收)多条消息:
+
-
+You can send (and receive) many messages:
-所有这些消息都将使用同一个 WebSocket 连
+
-接。
+And all of them will use the same WebSocket connection.
-## 使用 `Depends` 和其他依赖项
+## Using `Depends` and others
-在 WebSocket 端点中,您可以从 `fastapi` 导入并使用以下内容:
+In WebSocket endpoints you can import from `fastapi` and use:
* `Depends`
* `Security`
@@ -104,7 +110,7 @@ $ uvicorn main:app --reload
* `Path`
* `Query`
-它们的工作方式与其他 FastAPI 端点/ *路径操作* 相同:
+They work the same way as for other FastAPI endpoints/*path operations*:
=== "Python 3.10+"
@@ -124,32 +130,34 @@ $ uvicorn main:app --reload
{!> ../../../docs_src/websockets/tutorial002_an.py!}
```
-=== "Python 3.10+ 非带注解版本"
+=== "Python 3.10+ non-Annotated"
!!! tip
- 如果可能,请尽量使用 `Annotated` 版本。
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="66-67 79"
{!> ../../../docs_src/websockets/tutorial002_py310.py!}
```
-=== "Python 3.6+ 非带注解版本"
+=== "Python 3.6+ non-Annotated"
!!! tip
- 如果可能,请尽量使用 `Annotated` 版本。
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="68-69 81"
{!> ../../../docs_src/websockets/tutorial002.py!}
```
!!! info
- 由于这是一个 WebSocket,抛出 `HTTPException` 并不是很合理,而是抛出 `WebSocketException`。
+ As this is a WebSocket it doesn't really make sense to raise an `HTTPException`, instead we raise a `WebSocketException`.
- 您可以使用规范中定义的有效代码。
+ You can use a closing code from the valid codes defined in the specification.
-### 尝试带有依赖项的 WebSockets
+### Try the WebSockets with dependencies
-如果您的文件名为 `main.py`,请使用以下命令运行应用程序:
+If your file is named `main.py`, run your application with:
+
+
+
-## 处理断开连接和多个客户端
+## Handling disconnections and multiple clients
-当 WebSocket 连接关闭时,`await websocket.receive_text()` 将引发 `WebSocketDisconnect` 异常,您可以捕获并处理该异常,就像本示例中的示例一样。
+When a WebSocket connection is closed, the `await websocket.receive_text()` will raise a `WebSocketDisconnect` exception, which you can then catch and handle like in this example.
=== "Python 3.9+"
@@ -187,28 +197,28 @@ $ uvicorn main:app --reload
{!> ../../../docs_src/websockets/tutorial003.py!}
```
-尝试以下操作:
+To try it out:
-* 使用多个浏览器选项卡打开应用程序。
-* 从这些选项卡中发送消息。
-* 然后关闭其中一个选项卡。
+* Open the app with several browser tabs.
+* Write messages from them.
+* Then close one of the tabs.
-这将引发 `WebSocketDisconnect` 异常,并且所有其他客户端都会收到类似以下的消息:
+That will raise the `WebSocketDisconnect` exception, and all the other clients will receive a message like:
```
Client #1596980209979 left the chat
```
!!! tip
- 上面的应用程序是一个最小和简单的示例,用于演示如何处理和向多个 WebSocket 连接广播消息。
-
- 但请记住,由于所有内容都在内存中以单个列表的形式处理,因此它只能在进程运行时工作,并且只能使用单个进程。
+ The app above is a minimal and simple example to demonstrate how to handle and broadcast messages to several WebSocket connections.
- 如果您需要与 FastAPI 集成更简单但更强大的功能,支持 Redis、PostgreSQL 或其他功能,请查看 [encode/broadcaster](https://github.com/encode/broadcaster)。
+ But have in mind that, as everything is handled in memory, in a single list, it will only work while the process is running, and will only work with a single process.
+
+ If you need something easy to integrate with FastAPI but that is more robust, supported by Redis, PostgreSQL or others, check encode/broadcaster.
-## 更多信息
+## More info
-要了解更多选项,请查看 Starlette 的文档:
+To learn more about the options, check Starlette's documentation for:
-* [WebSocket 类](https://www.starlette.io/websockets/)
-* [基于类的 WebSocket 处理](https://www.starlette.io/endpoints/#websocketendpoint)。
+* The `WebSocket` class.
+* Class-based WebSocket handling.
From 03a62c7bbcc5e4c9e5b64ed4ecc93b6bc18b6c4e Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:00 +0800
Subject: [PATCH 038/163] New translations wsgi.md (Chinese Simplified)
---
docs/zh/docs/advanced/wsgi.md | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md
index ad71280fc6180..cfe3c78c11ca4 100644
--- a/docs/zh/docs/advanced/wsgi.md
+++ b/docs/zh/docs/advanced/wsgi.md
@@ -1,34 +1,34 @@
-# 包含 WSGI - Flask,Django,其它
+# Including WSGI - Flask, Django, others
-您可以挂载多个 WSGI 应用,正如您在 [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank} 中所看到的那样。
+You can mount WSGI applications as you saw with [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank}.
-为此, 您可以使用 `WSGIMiddleware` 来包装你的 WSGI 应用,如:Flask,Django,等等。
+For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc.
-## 使用 `WSGIMiddleware`
+## Using `WSGIMiddleware`
-您需要导入 `WSGIMiddleware`。
+You need to import `WSGIMiddleware`.
-然后使用该中间件包装 WSGI 应用(例如 Flask)。
+Then wrap the WSGI (e.g. Flask) app with the middleware.
-之后将其挂载到某一个路径下。
+And then mount that under a path.
-```Python hl_lines="2-3 22"
+```Python hl_lines="2-3 23"
{!../../../docs_src/wsgi/tutorial001.py!}
```
-## 检查
+## Check it
-现在,所有定义在 `/v1/` 路径下的请求将会被 Flask 应用处理。
+Now, every request under the path `/v1/` will be handled by the Flask application.
-其余的请求则会被 **FastAPI** 处理。
+And the rest will be handled by **FastAPI**.
-如果您使用 Uvicorn 运行应用实例并且访问 http://localhost:8000/v1/,您将会看到由 Flask 返回的响应:
+If you run it with Uvicorn and go to http://localhost:8000/v1/ you will see the response from Flask:
```txt
Hello, World from Flask!
```
-并且如果您访问 http://localhost:8000/v2,您将会看到由 FastAPI 返回的响应:
+And if you go to http://localhost:8000/v2 you will see the response from FastAPI:
```JSON
{
From 66cb27e74e77fc9e849b7f7485301597a6faf3d4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:01 +0800
Subject: [PATCH 039/163] New translations alternatives.md (Chinese Simplified)
---
docs/zh/docs/alternatives.md | 398 +++++++++++++++++++++++++++++++++++
1 file changed, 398 insertions(+)
create mode 100644 docs/zh/docs/alternatives.md
diff --git a/docs/zh/docs/alternatives.md b/docs/zh/docs/alternatives.md
new file mode 100644
index 0000000000000..b9f184cccfe55
--- /dev/null
+++ b/docs/zh/docs/alternatives.md
@@ -0,0 +1,398 @@
+# Alternatives, Inspiration and Comparisons
+
+What inspired **FastAPI**, how it compares to other alternatives and what it learned from them.
+
+## Intro
+
+**FastAPI** wouldn't exist if not for the previous work of others.
+
+There have been many tools created before that have helped inspire its creation.
+
+I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools.
+
+But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints).
+
+## Previous tools
+
+### Django
+
+It's the most popular Python framework and is widely trusted. It is used to build systems like Instagram.
+
+It's relatively tightly coupled with relational databases (like MySQL or PostgreSQL), so, having a NoSQL database (like Couchbase, MongoDB, Cassandra, etc) as the main store engine is not very easy.
+
+It was created to generate the HTML in the backend, not to create APIs used by a modern frontend (like React, Vue.js and Angular) or by other systems (like IoT devices) communicating with it.
+
+### Django REST Framework
+
+Django REST framework was created to be a flexible toolkit for building Web APIs using Django underneath, to improve its API capabilities.
+
+It is used by many companies including Mozilla, Red Hat and Eventbrite.
+
+It was one of the first examples of **automatic API documentation**, and this was specifically one of the first ideas that inspired "the search for" **FastAPI**.
+
+!!! note
+ Django REST Framework was created by Tom Christie. The same creator of Starlette and Uvicorn, on which **FastAPI** is based.
+
+
+!!! check "Inspired **FastAPI** to" Have an automatic API documentation web user interface.
+
+### Flask
+
+Flask is a "microframework", it doesn't include database integrations nor many of the things that come by default in Django.
+
+This simplicity and flexibility allow doing things like using NoSQL databases as the main data storage system.
+
+As it is very simple, it's relatively intuitive to learn, although the documentation gets somewhat technical at some points.
+
+It is also commonly used for other applications that don't necessarily need a database, user management, or any of the many features that come pre-built in Django. Although many of these features can be added with plug-ins.
+
+This decoupling of parts, and being a "microframework" that could be extended to cover exactly what is needed was a key feature that I wanted to keep.
+
+Given the simplicity of Flask, it seemed like a good match for building APIs. The next thing to find was a "Django REST Framework" for Flask.
+
+!!! check "Inspired **FastAPI** to" Be a micro-framework. Making it easy to mix and match the tools and parts needed.
+
+ Have a simple and easy to use routing system.
+
+
+### Requests
+
+**FastAPI** is not actually an alternative to **Requests**. Their scope is very different.
+
+It would actually be common to use Requests *inside* of a FastAPI application.
+
+But still, FastAPI got quite some inspiration from Requests.
+
+**Requests** is a library to *interact* with APIs (as a client), while **FastAPI** is a library to *build* APIs (as a server).
+
+They are, more or less, at opposite ends, complementing each other.
+
+Requests has a very simple and intuitive design, it's very easy to use, with sensible defaults. But at the same time, it's very powerful and customizable.
+
+That's why, as said in the official website:
+
+> Requests is one of the most downloaded Python packages of all time
+
+The way you use it is very simple. For example, to do a `GET` request, you would write:
+
+```Python
+response = requests.get("http://example.com/some/url")
+```
+
+The FastAPI counterpart API *path operation* could look like:
+
+```Python hl_lines="1"
+@app.get("/some/url")
+def read_url():
+ return {"message": "Hello World"}
+```
+
+See the similarities in `requests.get(...)` and `@app.get(...)`.
+
+!!! check "Inspired **FastAPI** to"
+ * Have a simple and intuitive API.
+ * Use HTTP method names (operations) directly, in a straightforward and intuitive way.
+ * Have sensible defaults, but powerful customizations.
+
+
+### Swagger / OpenAPI
+
+The main feature I wanted from Django REST Framework was the automatic API documentation.
+
+Then I found that there was a standard to document APIs, using JSON (or YAML, an extension of JSON) called Swagger.
+
+And there was a web user interface for Swagger APIs already created. So, being able to generate Swagger documentation for an API would allow using this web user interface automatically.
+
+At some point, Swagger was given to the Linux Foundation, to be renamed OpenAPI.
+
+That's why when talking about version 2.0 it's common to say "Swagger", and for version 3+ "OpenAPI".
+
+!!! check "Inspired **FastAPI** to" Adopt and use an open standard for API specifications, instead of a custom schema.
+
+ And integrate standards-based user interface tools:
+
+ * Swagger UI
+ * ReDoc
+
+ These two were chosen for being fairly popular and stable, but doing a quick search, you could find dozens of additional alternative user interfaces for OpenAPI (that you can use with **FastAPI**).
+
+### Flask REST frameworks
+
+There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit.
+
+### Marshmallow
+
+One of the main features needed by API systems is data "serialization" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
+
+Another big feature needed by APIs is data validation, making sure that the data is valid, given certain parameters. For example, that some field is an `int`, and not some random string. This is especially useful for incoming data.
+
+Without a data validation system, you would have to do all the checks by hand, in code.
+
+These features are what Marshmallow was built to provide. It is a great library, and I have used it a lot before.
+
+But it was created before there existed Python type hints. So, to define every schema you need to use specific utils and classes provided by Marshmallow.
+
+!!! check "Inspired **FastAPI** to" Use code to define "schemas" that provide data types and validation, automatically.
+
+### Webargs
+
+Another big feature required by APIs is parsing data from incoming requests.
+
+Webargs is a tool that was made to provide that on top of several frameworks, including Flask.
+
+It uses Marshmallow underneath to do the data validation. And it was created by the same developers.
+
+It's a great tool and I have used it a lot too, before having **FastAPI**.
+
+!!! info
+ Webargs was created by the same Marshmallow developers.
+
+!!! check "Inspired **FastAPI** to" Have automatic validation of incoming request data.
+
+### APISpec
+
+Marshmallow and Webargs provide validation, parsing and serialization as plug-ins.
+
+But documentation is still missing. Then APISpec was created.
+
+It is a plug-in for many frameworks (and there's a plug-in for Starlette too).
+
+The way it works is that you write the definition of the schema using YAML format inside the docstring of each function handling a route.
+
+And it generates OpenAPI schemas.
+
+That's how it works in Flask, Starlette, Responder, etc.
+
+But then, we have again the problem of having a micro-syntax, inside of a Python string (a big YAML).
+
+The editor can't help much with that. And if we modify parameters or Marshmallow schemas and forget to also modify that YAML docstring, the generated schema would be obsolete.
+
+!!! info
+ APISpec was created by the same Marshmallow developers.
+
+
+!!! check "Inspired **FastAPI** to" Support the open standard for APIs, OpenAPI.
+
+### Flask-apispec
+
+It's a Flask plug-in, that ties together Webargs, Marshmallow and APISpec.
+
+It uses the information from Webargs and Marshmallow to automatically generate OpenAPI schemas, using APISpec.
+
+It's a great tool, very under-rated. It should be way more popular than many Flask plug-ins out there. It might be due to its documentation being too concise and abstract.
+
+This solved having to write YAML (another syntax) inside of Python docstrings.
+
+This combination of Flask, Flask-apispec with Marshmallow and Webargs was my favorite backend stack until building **FastAPI**.
+
+Using it led to the creation of several Flask full-stack generators. These are the main stack I (and several external teams) have been using up to now:
+
+* https://github.com/tiangolo/full-stack
+* https://github.com/tiangolo/full-stack-flask-couchbase
+* https://github.com/tiangolo/full-stack-flask-couchdb
+
+And these same full-stack generators were the base of the [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}.
+
+!!! info
+ Flask-apispec was created by the same Marshmallow developers.
+
+!!! check "Inspired **FastAPI** to" Generate the OpenAPI schema automatically, from the same code that defines serialization and validation.
+
+### NestJS (and Angular)
+
+This isn't even Python, NestJS is a JavaScript (TypeScript) NodeJS framework inspired by Angular.
+
+It achieves something somewhat similar to what can be done with Flask-apispec.
+
+It has an integrated dependency injection system, inspired by Angular two. It requires pre-registering the "injectables" (like all the other dependency injection systems I know), so, it adds to the verbosity and code repetition.
+
+As the parameters are described with TypeScript types (similar to Python type hints), editor support is quite good.
+
+But as TypeScript data is not preserved after compilation to JavaScript, it cannot rely on the types to define validation, serialization and documentation at the same time. Due to this and some design decisions, to get validation, serialization and automatic schema generation, it's needed to add decorators in many places. So, it becomes quite verbose.
+
+It can't handle nested models very well. So, if the JSON body in the request is a JSON object that has inner fields that in turn are nested JSON objects, it cannot be properly documented and validated.
+
+!!! check "Inspired **FastAPI** to" Use Python types to have great editor support.
+
+ Have a powerful dependency injection system. Find a way to minimize code repetition.
+
+### Sanic
+
+It was one of the first extremely fast Python frameworks based on `asyncio`. It was made to be very similar to Flask.
+
+!!! note "Technical Details"
+ It used `uvloop` instead of the default Python `asyncio` loop. That's what made it so fast.
+
+ It clearly inspired Uvicorn and Starlette, that are currently faster than Sanic in open benchmarks.
+
+!!! check "Inspired **FastAPI** to" Find a way to have a crazy performance.
+
+ That's why **FastAPI** is based on Starlette, as it is the fastest framework available (tested by third-party benchmarks).
+
+### Falcon
+
+Falcon is another high performance Python framework, it is designed to be minimal, and work as the foundation of other frameworks like Hug.
+
+It is designed to have functions that receive two parameters, one "request" and one "response". Then you "read" parts from the request, and "write" parts to the response. Because of this design, it is not possible to declare request parameters and bodies with standard Python type hints as function parameters.
+
+So, data validation, serialization, and documentation, have to be done in code, not automatically. Or they have to be implemented as a framework on top of Falcon, like Hug. This same distinction happens in other frameworks that are inspired by Falcon's design, of having one request object and one response object as parameters.
+
+!!! check "Inspired **FastAPI** to" Find ways to get great performance.
+
+ Along with Hug (as Hug is based on Falcon) inspired **FastAPI** to declare a `response` parameter in functions.
+
+ Although in FastAPI it's optional, and is used mainly to set headers, cookies, and alternative status codes.
+
+### Molten
+
+I discovered Molten in the first stages of building **FastAPI**. And it has quite similar ideas:
+
+* Based on Python type hints.
+* Validation and documentation from these types.
+* Dependency Injection system.
+
+It doesn't use a data validation, serialization and documentation third-party library like Pydantic, it has its own. So, these data type definitions would not be reusable as easily.
+
+It requires a little bit more verbose configurations. And as it is based on WSGI (instead of ASGI), it is not designed to take advantage of the high-performance provided by tools like Uvicorn, Starlette and Sanic.
+
+The dependency injection system requires pre-registration of the dependencies and the dependencies are solved based on the declared types. So, it's not possible to declare more than one "component" that provides a certain type.
+
+Routes are declared in a single place, using functions declared in other places (instead of using decorators that can be placed right on top of the function that handles the endpoint). This is closer to how Django does it than to how Flask (and Starlette) does it. It separates in the code things that are relatively tightly coupled.
+
+!!! check "Inspired **FastAPI** to" Define extra validations for data types using the "default" value of model attributes. This improves editor support, and it was not available in Pydantic before.
+
+ This actually inspired updating parts of Pydantic, to support the same validation declaration style (all this functionality is now already available in Pydantic).
+
+### Hug
+
+Hug was one of the first frameworks to implement the declaration of API parameter types using Python type hints. This was a great idea that inspired other tools to do the same.
+
+It used custom types in its declarations instead of standard Python types, but it was still a huge step forward.
+
+It also was one of the first frameworks to generate a custom schema declaring the whole API in JSON.
+
+It was not based on a standard like OpenAPI and JSON Schema. So it wouldn't be straightforward to integrate it with other tools, like Swagger UI. But again, it was a very innovative idea.
+
+It has an interesting, uncommon feature: using the same framework, it's possible to create APIs and also CLIs.
+
+As it is based on the previous standard for synchronous Python web frameworks (WSGI), it can't handle Websockets and other things, although it still has high performance too.
+
+!!! info
+ Hug was created by Timothy Crosley, the same creator of `isort`, a great tool to automatically sort imports in Python files.
+
+!!! check "Ideas inspired in **FastAPI**" Hug inspired parts of APIStar, and was one of the tools I found most promising, alongside APIStar.
+
+ Hug helped inspiring **FastAPI** to use Python type hints to declare parameters, and to generate a schema defining the API automatically.
+
+ Hug inspired **FastAPI** to declare a `response` parameter in functions to set headers and cookies.
+
+### APIStar (<= 0.5)
+
+Right before deciding to build **FastAPI** I found **APIStar** server. It had almost everything I was looking for and had a great design.
+
+It was one of the first implementations of a framework using Python type hints to declare parameters and requests that I ever saw (before NestJS and Molten). I found it more or less at the same time as Hug. But APIStar used the OpenAPI standard.
+
+It had automatic data validation, data serialization and OpenAPI schema generation based on the same type hints in several places.
+
+Body schema definitions didn't use the same Python type hints like Pydantic, it was a bit more similar to Marshmallow, so, editor support wouldn't be as good, but still, APIStar was the best available option.
+
+It had the best performance benchmarks at the time (only surpassed by Starlette).
+
+At first, it didn't have an automatic API documentation web UI, but I knew I could add Swagger UI to it.
+
+It had a dependency injection system. It required pre-registration of components, as other tools discussed above. But still, it was a great feature.
+
+I was never able to use it in a full project, as it didn't have security integration, so, I couldn't replace all the features I was having with the full-stack generators based on Flask-apispec. I had in my backlog of projects to create a pull request adding that functionality.
+
+But then, the project's focus shifted.
+
+It was no longer an API web framework, as the creator needed to focus on Starlette.
+
+Now APIStar is a set of tools to validate OpenAPI specifications, not a web framework.
+
+!!! info
+ APIStar was created by Tom Christie. The same guy that created:
+
+ * Django REST Framework
+ * Starlette (in which **FastAPI** is based)
+ * Uvicorn (used by Starlette and **FastAPI**)
+
+!!! check "Inspired **FastAPI** to" Exist.
+
+ The idea of declaring multiple things (data validation, serialization and documentation) with the same Python types, that at the same time provided great editor support, was something I considered a brilliant idea.
+
+ And after searching for a long time for a similar framework and testing many different alternatives, APIStar was the best option available.
+
+ Then APIStar stopped to exist as a server and Starlette was created, and was a new better foundation for such a system. That was the final inspiration to build **FastAPI**.
+
+ I consider **FastAPI** a "spiritual successor" to APIStar, while improving and increasing the features, typing system, and other parts, based on the learnings from all these previous tools.
+
+## Used by **FastAPI**
+
+### Pydantic
+
+Pydantic is a library to define data validation, serialization and documentation (using JSON Schema) based on Python type hints.
+
+That makes it extremely intuitive.
+
+It is comparable to Marshmallow. Although it's faster than Marshmallow in benchmarks. And as it is based on the same Python type hints, the editor support is great.
+
+!!! check "**FastAPI** uses it to" Handle all the data validation, data serialization and automatic model documentation (based on JSON Schema).
+
+ **FastAPI** then takes that JSON Schema data and puts it in OpenAPI, apart from all the other things it does.
+
+### Starlette
+
+Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high-performance asyncio services.
+
+It is very simple and intuitive. It's designed to be easily extensible, and have modular components.
+
+It has:
+
+* Seriously impressive performance.
+* WebSocket support.
+* In-process background tasks.
+* Startup and shutdown events.
+* Test client built on HTTPX.
+* CORS, GZip, Static Files, Streaming responses.
+* Session and Cookie support.
+* 100% test coverage.
+* 100% type annotated codebase.
+* Few hard dependencies.
+
+Starlette is currently the fastest Python framework tested. Only surpassed by Uvicorn, which is not a framework, but a server.
+
+Starlette provides all the basic web microframework functionality.
+
+But it doesn't provide automatic data validation, serialization or documentation.
+
+That's one of the main things that **FastAPI** adds on top, all based on Python type hints (using Pydantic). That, plus the dependency injection system, security utilities, OpenAPI schema generation, etc.
+
+!!! note "Technical Details"
+ ASGI is a new "standard" being developed by Django core team members. It is still not a "Python standard" (a PEP), although they are in the process of doing that.
+
+ Nevertheless, it is already being used as a "standard" by several tools. This greatly improves interoperability, as you could switch Uvicorn for any other ASGI server (like Daphne or Hypercorn), or you could add ASGI compatible tools, like `python-socketio`.
+
+!!! check "**FastAPI** uses it to" Handle all the core web parts. Adding features on top.
+
+ The class `FastAPI` itself inherits directly from the class `Starlette`.
+
+ So, anything that you can do with Starlette, you can do it directly with **FastAPI**, as it is basically Starlette on steroids.
+
+### Uvicorn
+
+Uvicorn is a lightning-fast ASGI server, built on uvloop and httptools.
+
+It is not a web framework, but a server. For example, it doesn't provide tools for routing by paths. That's something that a framework like Starlette (or **FastAPI**) would provide on top.
+
+It is the recommended server for Starlette and **FastAPI**.
+
+!!! check "**FastAPI** recommends it as" The main web server to run **FastAPI** applications.
+
+ You can combine it with Gunicorn, to have an asynchronous multi-process server.
+
+ Check more details in the [Deployment](deployment/index.md){.internal-link target=_blank} section.
+
+## Benchmarks and speed
+
+To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](benchmarks.md){.internal-link target=_blank}.
From 5137ad62c9b36e92c49332c679ce83527d3004b0 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:02 +0800
Subject: [PATCH 040/163] New translations async.md (Chinese Simplified)
---
docs/zh/docs/async.md | 430 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 430 insertions(+)
create mode 100644 docs/zh/docs/async.md
diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md
new file mode 100644
index 0000000000000..3ac62a7795ea9
--- /dev/null
+++ b/docs/zh/docs/async.md
@@ -0,0 +1,430 @@
+# Concurrency and async / await
+
+Details about the `async def` syntax for *path operation functions* and some background about asynchronous code, concurrency, and parallelism.
+
+## In a hurry?
+
+TL;DR:
+
+If you are using third party libraries that tell you to call them with `await`, like:
+
+```Python
+results = await some_library()
+```
+
+Then, declare your *path operation functions* with `async def` like:
+
+```Python hl_lines="2"
+@app.get('/')
+async def read_results():
+ results = await some_library()
+ return results
+```
+
+!!! note
+ You can only use `await` inside of functions created with `async def`.
+
+---
+
+If you are using a third party library that communicates with something (a database, an API, the file system, etc.) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like:
+
+```Python hl_lines="2"
+@app.get('/')
+def results():
+ results = some_library()
+ return results
+```
+
+---
+
+If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`.
+
+---
+
+If you just don't know, use normal `def`.
+
+---
+
+**Note**: You can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
+
+Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast.
+
+But by following the steps above, it will be able to do some performance optimizations.
+
+## Technical Details
+
+Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax.
+
+Let's see that phrase by parts in the sections below:
+
+* **Asynchronous Code**
+* **`async` and `await`**
+* **Coroutines**
+
+## Asynchronous Code
+
+Asynchronous code just means that the language 💬 has a way to tell the computer / program 🤖 that at some point in the code, it 🤖 will have to wait for *something else* to finish somewhere else. Let's say that *something else* is called "slow-file" 📝.
+
+So, during that time, the computer can go and do some other work, while "slow-file" 📝 finishes.
+
+Then the computer / program 🤖 will come back every time it has a chance because it's waiting again, or whenever it 🤖 finished all the work it had at that point. And it 🤖 will see if any of the tasks it was waiting for have already finished, doing whatever it had to do.
+
+Next, it 🤖 takes the first task to finish (let's say, our "slow-file" 📝) and continues whatever it had to do with it.
+
+That "wait for something else" normally refers to I/O operations that are relatively "slow" (compared to the speed of the processor and the RAM memory), like waiting for:
+
+* the data from the client to be sent through the network
+* the data sent by your program to be received by the client through the network
+* the contents of a file in the disk to be read by the system and given to your program
+* the contents your program gave to the system to be written to disk
+* a remote API operation
+* a database operation to finish
+* a database query to return the results
+* etc.
+
+As the execution time is consumed mostly by waiting for I/O operations, they call them "I/O bound" operations.
+
+It's called "asynchronous" because the computer / program doesn't have to be "synchronized" with the slow task, waiting for the exact moment that the task finishes, while doing nothing, to be able to take the task result and continue the work.
+
+Instead of that, by being an "asynchronous" system, once finished, the task can wait in line a little bit (some microseconds) for the computer / program to finish whatever it went to do, and then come back to take the results and continue working with them.
+
+For "synchronous" (contrary to "asynchronous") they commonly also use the term "sequential", because the computer / program follows all the steps in sequence before switching to a different task, even if those steps involve waiting.
+
+### Concurrency and Burgers
+
+This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**.
+
+**Concurrency** and **parallelism** both relate to "different things happening more or less at the same time".
+
+But the details between *concurrency* and *parallelism* are quite different.
+
+To see the difference, imagine the following story about burgers:
+
+### Concurrent Burgers
+
+You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you. 😍
+
+
+
+Then it's your turn, you place your order of 2 very fancy burgers for your crush and you. 🍔🍔
+
+
+
+The cashier says something to the cook in the kitchen so they know they have to prepare your burgers (even though they are currently preparing the ones for the previous clients).
+
+
+
+You pay. 💸
+
+The cashier gives you the number of your turn.
+
+
+
+While you are waiting, you go with your crush and pick a table, you sit and talk with your crush for a long time (as your burgers are very fancy and take some time to prepare).
+
+As you are sitting at the table with your crush, while you wait for the burgers, you can spend that time admiring how awesome, cute and smart your crush is ✨😍✨.
+
+
+
+While waiting and talking to your crush, from time to time, you check the number displayed on the counter to see if it's your turn already.
+
+Then at some point, it finally is your turn. You go to the counter, get your burgers and come back to the table.
+
+
+
+You and your crush eat the burgers and have a nice time. ✨
+
+
+
+!!! info
+ Beautiful illustrations by Ketrina Thompson. 🎨
+
+---
+
+Imagine you are the computer / program 🤖 in that story.
+
+While you are at the line, you are just idle 😴, waiting for your turn, not doing anything very "productive". But the line is fast because the cashier is only taking the orders (not preparing them), so that's fine.
+
+Then, when it's your turn, you do actual "productive" work, you process the menu, decide what you want, get your crush's choice, pay, check that you give the correct bill or card, check that you are charged correctly, check that the order has the correct items, etc.
+
+But then, even though you still don't have your burgers, your work with the cashier is "on pause" ⏸, because you have to wait 🕙 for your burgers to be ready.
+
+But as you go away from the counter and sit at the table with a number for your turn, you can switch 🔀 your attention to your crush, and "work" ⏯ 🤓 on that. Then you are again doing something very "productive" as is flirting with your crush 😍.
+
+Then the cashier 💁 says "I'm finished with doing the burgers" by putting your number on the counter's display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers because you have the number of your turn, and they have theirs.
+
+So you wait for your crush to finish the story (finish the current work ⏯ / task being processed 🤓), smile gently and say that you are going for the burgers ⏸.
+
+Then you go to the counter 🔀, to the initial task that is now finished ⏯, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter ⏹. That in turn, creates a new task, of "eating burgers" 🔀 ⏯, but the previous one of "getting burgers" is finished ⏹.
+
+### Parallel Burgers
+
+Now let's imagine these aren't "Concurrent Burgers", but "Parallel Burgers".
+
+You go with your crush to get parallel fast food.
+
+You stand in line while several (let's say 8) cashiers that at the same time are cooks take the orders from the people in front of you.
+
+Everyone before you is waiting for their burgers to be ready before leaving the counter because each of the 8 cashiers goes and prepares the burger right away before getting the next order.
+
+
+
+Then it's finally your turn, you place your order of 2 very fancy burgers for your crush and you.
+
+You pay 💸.
+
+
+
+The cashier goes to the kitchen.
+
+You wait, standing in front of the counter 🕙, so that no one else takes your burgers before you do, as there are no numbers for turns.
+
+
+
+As you and your crush are busy not letting anyone get in front of you and take your burgers whenever they arrive, you cannot pay attention to your crush. 😞
+
+This is "synchronous" work, you are "synchronized" with the cashier/cook 👨🍳. You have to wait 🕙 and be there at the exact moment that the cashier/cook 👨🍳 finishes the burgers and gives them to you, or otherwise, someone else might take them.
+
+
+
+Then your cashier/cook 👨🍳 finally comes back with your burgers, after a long time waiting 🕙 there in front of the counter.
+
+
+
+You take your burgers and go to the table with your crush.
+
+You just eat them, and you are done. ⏹
+
+
+
+There was not much talk or flirting as most of the time was spent waiting 🕙 in front of the counter. 😞
+
+!!! info
+ Beautiful illustrations by Ketrina Thompson. 🎨
+
+---
+
+In this scenario of the parallel burgers, you are a computer / program 🤖 with two processors (you and your crush), both waiting 🕙 and dedicating their attention ⏯ to be "waiting on the counter" 🕙 for a long time.
+
+The fast food store has 8 processors (cashiers/cooks). While the concurrent burgers store might have had only 2 (one cashier and one cook).
+
+But still, the final experience is not the best. 😞
+
+---
+
+This would be the parallel equivalent story for burgers. 🍔
+
+For a more "real life" example of this, imagine a bank.
+
+Up to recently, most of the banks had multiple cashiers 👨💼👨💼👨💼👨💼 and a big line 🕙🕙🕙🕙🕙🕙🕙🕙.
+
+All of the cashiers doing all the work with one client after the other 👨💼⏯.
+
+And you have to wait 🕙 in the line for a long time or you lose your turn.
+
+You probably wouldn't want to take your crush 😍 with you to do errands at the bank 🏦.
+
+### Burger Conclusion
+
+In this scenario of "fast food burgers with your crush", as there is a lot of waiting 🕙, it makes a lot more sense to have a concurrent system ⏸🔀⏯.
+
+This is the case for most of the web applications.
+
+Many, many users, but your server is waiting 🕙 for their not-so-good connection to send their requests.
+
+And then waiting 🕙 again for the responses to come back.
+
+This "waiting" 🕙 is measured in microseconds, but still, summing it all, it's a lot of waiting in the end.
+
+That's why it makes a lot of sense to use asynchronous ⏸🔀⏯ code for web APIs.
+
+This kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programming language.
+
+And that's the same level of performance you get with **FastAPI**.
+
+And as you can have parallelism and asynchronicity at the same time, you get higher performance than most of the tested NodeJS frameworks and on par with Go, which is a compiled language closer to C (all thanks to Starlette).
+
+### Is concurrency better than parallelism?
+
+Nope! That's not the moral of the story.
+
+Concurrency is different than parallelism. And it is better on **specific** scenarios that involve a lot of waiting. Because of that, it generally is a lot better than parallelism for web application development. But not for everything.
+
+So, to balance that out, imagine the following short story:
+
+> You have to clean a big, dirty house.
+
+*Yep, that's the whole story*.
+
+---
+
+There's no waiting 🕙 anywhere, just a lot of work to be done, on multiple places of the house.
+
+You could have turns as in the burgers example, first the living room, then the kitchen, but as you are not waiting 🕙 for anything, just cleaning and cleaning, the turns wouldn't affect anything.
+
+It would take the same amount of time to finish with or without turns (concurrency) and you would have done the same amount of work.
+
+But in this case, if you could bring the 8 ex-cashier/cooks/now-cleaners, and each one of them (plus you) could take a zone of the house to clean it, you could do all the work in **parallel**, with the extra help, and finish much sooner.
+
+In this scenario, each one of the cleaners (including you) would be a processor, doing their part of the job.
+
+And as most of the execution time is taken by actual work (instead of waiting), and the work in a computer is done by a CPU, they call these problems "CPU bound".
+
+---
+
+Common examples of CPU bound operations are things that require complex math processing.
+
+For example:
+
+* **Audio** or **image processing**.
+* **Computer vision**: an image is composed of millions of pixels, each pixel has 3 values / colors, processing that normally requires computing something on those pixels, all at the same time.
+* **Machine Learning**: it normally requires lots of "matrix" and "vector" multiplications. Think of a huge spreadsheet with numbers and multiplying all of them together at the same time.
+* **Deep Learning**: this is a sub-field of Machine Learning, so, the same applies. It's just that there is not a single spreadsheet of numbers to multiply, but a huge set of them, and in many cases, you use a special processor to build and / or use those models.
+
+### Concurrency + Parallelism: Web + Machine Learning
+
+With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attraction of NodeJS).
+
+But you can also exploit the benefits of parallelism and multiprocessing (having multiple processes running in parallel) for **CPU bound** workloads like those in Machine Learning systems.
+
+That, plus the simple fact that Python is the main language for **Data Science**, Machine Learning and especially Deep Learning, make FastAPI a very good match for Data Science / Machine Learning web APIs and applications (among many others).
+
+To see how to achieve this parallelism in production see the section about [Deployment](deployment/index.md){.internal-link target=_blank}.
+
+## `async` and `await`
+
+Modern versions of Python have a very intuitive way to define asynchronous code. This makes it look just like normal "sequential" code and do the "awaiting" for you at the right moments.
+
+When there is an operation that will require waiting before giving the results and has support for these new Python features, you can code it like:
+
+```Python
+burgers = await get_burgers(2)
+```
+
+The key here is the `await`. It tells Python that it has to wait ⏸ for `get_burgers(2)` to finish doing its thing 🕙 before storing the results in `burgers`. With that, Python will know that it can go and do something else 🔀 ⏯ in the meanwhile (like receiving another request).
+
+For `await` to work, it has to be inside a function that supports this asynchronicity. To do that, you just declare it with `async def`:
+
+```Python hl_lines="1"
+async def get_burgers(number: int):
+ # Do some asynchronous stuff to create the burgers
+ return burgers
+```
+
+...instead of `def`:
+
+```Python hl_lines="2"
+# This is not asynchronous
+def get_sequential_burgers(number: int):
+ # Do some sequential stuff to create the burgers
+ return burgers
+```
+
+With `async def`, Python knows that, inside that function, it has to be aware of `await` expressions, and that it can "pause" ⏸ the execution of that function and go do something else 🔀 before coming back.
+
+When you want to call an `async def` function, you have to "await" it. So, this won't work:
+
+```Python
+# This won't work, because get_burgers was defined with: async def
+burgers = get_burgers(2)
+```
+
+---
+
+So, if you are using a library that tells you that you can call it with `await`, you need to create the *path operation functions* that uses it with `async def`, like in:
+
+```Python hl_lines="2-3"
+@app.get('/burgers')
+async def read_burgers():
+ burgers = await get_burgers(2)
+ return burgers
+```
+
+### More technical details
+
+You might have noticed that `await` can only be used inside of functions defined with `async def`.
+
+But at the same time, functions defined with `async def` have to be "awaited". So, functions with `async def` can only be called inside of functions defined with `async def` too.
+
+So, about the egg and the chicken, how do you call the first `async` function?
+
+If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your *path operation function*, and FastAPI will know how to do the right thing.
+
+But if you want to use `async` / `await` without FastAPI, you can do it as well.
+
+### Write your own async code
+
+Starlette (and **FastAPI**) are based on AnyIO, which makes it compatible with both Python's standard library asyncio and Trio.
+
+In particular, you can directly use AnyIO for your advanced concurrency use cases that require more advanced patterns in your own code.
+
+And even if you were not using FastAPI, you could also write your own async applications with AnyIO to be highly compatible and get its benefits (e.g. *structured concurrency*).
+
+### Other forms of asynchronous code
+
+This style of using `async` and `await` is relatively new in the language.
+
+But it makes working with asynchronous code a lot easier.
+
+This same syntax (or almost identical) was also included recently in modern versions of JavaScript (in Browser and NodeJS).
+
+But before that, handling asynchronous code was quite more complex and difficult.
+
+In previous versions of Python, you could have used threads or Gevent. But the code is way more complex to understand, debug, and think about.
+
+In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which leads to callback hell.
+
+## Coroutines
+
+**Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function that it can start and that it will end at some point, but that it might be paused ⏸ internally too, whenever there is an `await` inside of it.
+
+But all this functionality of using asynchronous code with `async` and `await` is many times summarized as using "coroutines". It is comparable to the main key feature of Go, the "Goroutines".
+
+## Conclusion
+
+Let's see the same phrase from above:
+
+> Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax.
+
+That should make more sense now. ✨
+
+All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance.
+
+## Very Technical Details
+
+!!! warning
+ You can probably skip this.
+
+ These are very technical details of how **FastAPI** works underneath.
+
+ If you have quite some technical knowledge (co-routines, threads, blocking, etc.) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead.
+
+### Path operation functions
+
+When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
+
+If you are coming from another async framework that does not work in the way described above and you are used to defining trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking I/O.
+
+Still, in both situations, chances are that **FastAPI** will [still be faster](/#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework.
+
+### Dependencies
+
+The same applies for [dependencies](/tutorial/dependencies/index.md){.internal-link target=_blank}. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
+
+### Sub-dependencies
+
+You can have multiple dependencies and [sub-dependencies](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
+
+### Other utility functions
+
+Any other utility function that you call directly can be created with normal `def` or `async def` and FastAPI won't affect the way you call it.
+
+This is in contrast to the functions that FastAPI calls for you: *path operation functions* and dependencies.
+
+If your utility function is a normal function with `def`, it will be called directly (as you write it in your code), not in a threadpool, if the function is created with `async def` then you should `await` for that function when you call it in your code.
+
+---
+
+Again, these are very technical details that would probably be useful if you came searching for them.
+
+Otherwise, you should be good with the guidelines from the section above: In a hurry?.
From ca07105e0ac1ef832fe5b5364e7e26d08e166fa0 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:03 +0800
Subject: [PATCH 041/163] New translations benchmarks.md (Chinese Simplified)
---
docs/zh/docs/benchmarks.md | 44 +++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md
index 71e8d483822ac..e05fec8406621 100644
--- a/docs/zh/docs/benchmarks.md
+++ b/docs/zh/docs/benchmarks.md
@@ -1,34 +1,34 @@
-# 基准测试
+# Benchmarks
-第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是 可用的最快的 Python 框架之一,仅次于 Starlette 和 Uvicorn 本身 (由 FastAPI 内部使用)。(*)
+Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
-但是在查看基准得分和对比时,请注意以下几点。
+But when checking benchmarks and comparisons you should have the following in mind.
-## 基准测试和速度
+## Benchmarks and speed
-当你查看基准测试时,几个不同类型的工具被等效地做比较是很常见的情况。
+When you check the benchmarks, it is common to see several tools of different types compared as equivalent.
-具体来说,是将 Uvicorn,Starlette 和 FastAPI 一起比较(在许多其它工具中)。
+Specifically, to see Uvicorn, Starlette and FastAPI compared together (among many other tools).
-该工具解决的问题最简单,它将获得更好的性能。而且大多数基准测试并未测试该工具提供的其他功能。
+The simpler the problem solved by the tool, the better performance it will get. And most of the benchmarks don't test the additional features provided by the tool.
-层次结构如下:
+The hierarchy is like:
-* **Uvicorn**:ASGI服务器
- * **Starlette**:(使用 Uvicorn)网络微框架
- * **FastAPI**:(使用 Starlette) 具有多个附加功能的API微框架,用于构建API,进行数据验证等。
+* **Uvicorn**: an ASGI server
+ * **Starlette**: (uses Uvicorn) a web microframework
+ * **FastAPI**: (uses Starlette) an API microframework with several additional features for building APIs, with data validation, etc.
* **Uvicorn**:
- * 具有最佳性能,因为除了服务器本身外,它没有太多额外的代码。
- * 您不会直接在 Uvicorn 中编写应用程序。这意味着您的代码至少必须包含 Starlette(或 **FastAPI**)提供的代码。如果您这样做了(即直接在 Uvicorn 中编写应用程序),最终的应用程序会和使用了框架并且最小化了应用代码和 bug 的情况具有相同的性能损耗。
- * 如果要对比与 Uvicorn 对标的服务器,请将其与 Daphne,Hypercorn,uWSGI等应用服务器进行比较。
+ * Will have the best performance, as it doesn't have much extra code apart from the server itself.
+ * You wouldn't write an application in Uvicorn directly. That would mean that your code would have to include more or less, at least, all the code provided by Starlette (or **FastAPI**). And if you did that, your final application would have the same overhead as having used a framework and minimizing your app code and bugs.
+ * If you are comparing Uvicorn, compare it against Daphne, Hypercorn, uWSGI, etc. Application servers.
* **Starlette**:
- * 在 Uvicorn 后使用 Starlette,性能会略有下降。实际上,Starlette 使用 Uvicorn运行。因此,由于必须执行更多的代码,它只会比 Uvicorn 更慢。
- * 但它为您提供了构建简单的网络程序的工具,并具有基于路径的路由等功能。
- * 如果想对比与 Starlette 对标的开发框架,请将其与 Sanic,Flask,Django 等网络框架(或微框架)进行比较。
+ * Will have the next best performance, after Uvicorn. In fact, Starlette uses Uvicorn to run. So, it probably can only get "slower" than Uvicorn by having to execute more code.
+ * But it provides you the tools to build simple web applications, with routing based on paths, etc.
+ * If you are comparing Starlette, compare it against Sanic, Flask, Django, etc. Web frameworks (or microframeworks).
* **FastAPI**:
- * 与 Starlette 使用 Uvicorn 一样,由于 **FastAPI** 使用 Starlette,因此 FastAPI 不能比 Starlette 更快。
- * FastAPI 在 Starlette 基础上提供了更多功能。例如在开发 API 时,所需的数据验证和序列化功能。FastAPI 可以帮助您自动生成 API文档,(文档在应用程序启动时自动生成,所以不会增加应用程序运行时的开销)。
- * 如果您不使用 FastAPI 而直接使用 Starlette(或诸如 Sanic,Flask,Responder 等其它工具),您则要自己实现所有的数据验证和序列化。那么最终您的应用程序会和使用 FastAPI 构建的程序有相同的开销。一般这种数据验证和序列化的操作在您应用程序的代码中会占很大比重。
- * 因此,通过使用 FastAPI 意味着您可以节省开发时间,减少编码错误,用更少的编码实现其功能,并且相比不使用 FastAPI 您很大可能会获得相同或更好的性能(因为那样您必须在代码中实现所有相同的功能)。
- * 如果您想对比与 FastAPI 对标的开发框架,请与能够提供数据验证,序列化和带有自动文档生成的网络应用程序框架(或工具集)进行对比,例如具有集成自动数据验证,序列化和自动化文档的 Flask-apispec,NestJS,Molten 等。
+ * The same way that Starlette uses Uvicorn and cannot be faster than it, **FastAPI** uses Starlette, so it cannot be faster than it.
+ * FastAPI provides more features on top of Starlette. Features that you almost always need when building APIs, like data validation and serialization. And by using it, you get automatic documentation for free (the automatic documentation doesn't even add overhead to running applications, it is generated on startup).
+ * If you didn't use FastAPI and used Starlette directly (or another tool, like Sanic, Flask, Responder, etc) you would have to implement all the data validation and serialization yourself. So, your final application would still have the same overhead as if it was built using FastAPI. And in many cases, this data validation and serialization is the biggest amount of code written in applications.
+ * So, by using FastAPI you are saving development time, bugs, lines of code, and you would probably get the same performance (or better) you would if you didn't use it (as you would have to implement it all in your code).
+ * If you are comparing FastAPI, compare it against a web application framework (or set of tools) that provides data validation, serialization and documentation, like Flask-apispec, NestJS, Molten, etc. Frameworks with integrated automatic data validation, serialization and documentation.
From 3f444141a1f4f11cfe1806044df00621a6cf5394 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:04 +0800
Subject: [PATCH 042/163] New translations contributing.md (Chinese Simplified)
---
docs/zh/docs/contributing.md | 333 ++++++++++++++++-------------------
1 file changed, 152 insertions(+), 181 deletions(-)
diff --git a/docs/zh/docs/contributing.md b/docs/zh/docs/contributing.md
index 4ebd673150b25..f9276b28e9e49 100644
--- a/docs/zh/docs/contributing.md
+++ b/docs/zh/docs/contributing.md
@@ -1,14 +1,14 @@
-# 开发 - 贡献
+# Development - Contributing
-首先,你最好先了解 [帮助 FastAPI 及获取帮助](help-fastapi.md){.internal-link target=_blank}的基本方式。
+First, you might want to see the basic ways to [help FastAPI and get help](help-fastapi.md){.internal-link target=_blank}.
-## 开发
+## Developing
-如果你已经克隆了源码仓库,并且需要深入研究代码,下面是设置开发环境的指南。
+If you already cloned the repository and you know that you need to deep dive in the code, here are some guidelines to set up your environment.
-### 通过 `venv` 管理虚拟环境
+### Virtual environment with `venv`
-你可以使用 Python 的 `venv` 模块在一个目录中创建虚拟环境:
+You can create a virtual environment in a directory using Python's `venv` module:
+
+---
+
+Now that we know the difference between the terms **process** and **program**, let's continue talking about deployments.
+
+## Running on Startup
+
+In most cases, when you create a web API, you want it to be **always running**, uninterrupted, so that your clients can always access it. This is of course, unless you have a specific reason why you want it to run only in certain situations, but most of the time you want it constantly running and **available**.
+
+### In a Remote Server
+
+When you set up a remote server (a cloud server, a virtual machine, etc.) the simplest thing you can do is to run Uvicorn (or similar) manually, the same way you do when developing locally.
+
+And it will work and will be useful **during development**.
+
+But if your connection to the server is lost, the **running process** will probably die.
+
+And if the server is restarted (for example after updates, or migrations from the cloud provider) you probably **won't notice it**. And because of that, you won't even know that you have to restart the process manually. So, your API will just stay dead. 😱
+
+### Run Automatically on Startup
+
+In general, you will probably want the server program (e.g. Uvicorn) to be started automatically on server startup, and without needing any **human intervention**, to have a process always running with your API (e.g. Uvicorn running your FastAPI app).
+
+### Separate Program
+
+To achieve this, you will normally have a **separate program** that would make sure your application is run on startup. And in many cases, it would also make sure other components or applications are also run, for example, a database.
+
+### Example Tools to Run at Startup
+
+Some examples of the tools that can do this job are:
+
+* Docker
+* Kubernetes
+* Docker Compose
+* Docker in Swarm Mode
+* Systemd
+* Supervisor
+* Handled internally by a cloud provider as part of their services
+* Others...
+
+I'll give you more concrete examples in the next chapters.
+
+## Restarts
+
+Similar to making sure your application is run on startup, you probably also want to make sure it is **restarted** after failures.
+
+### We Make Mistakes
+
+We, as humans, make **mistakes**, all the time. Software almost *always* has **bugs** hidden in different places. 🐛
+
+And we as developers keep improving the code as we find those bugs and as we implement new features (possibly adding new bugs too 😅).
+
+### Small Errors Automatically Handled
+
+When building web APIs with FastAPI, if there's an error in our code, FastAPI will normally contain it to the single request that triggered the error. 🛡
+
+The client will get a **500 Internal Server Error** for that request, but the application will continue working for the next requests instead of just crashing completely.
+
+### Bigger Errors - Crashes
+
+Nevertheless, there might be cases where we write some code that **crashes the entire application** making Uvicorn and Python crash. 💥
+
+And still, you would probably not want the application to stay dead because there was an error in one place, you probably want it to **continue running** at least for the *path operations* that are not broken.
+
+### Restart After Crash
+
+But in those cases with really bad errors that crash the running **process**, you would want an external component that is in charge of **restarting** the process, at least a couple of times...
+
+!!! tip
+ ...Although if the whole application is just **crashing immediately** it probably doesn't make sense to keep restarting it forever. But in those cases, you will probably notice it during development, or at least right after deployment.
+
+ So let's focus on the main cases, where it could crash entirely in some particular cases **in the future**, and it still makes sense to restart it.
+
+You would probably want to have the thing in charge of restarting your application as an **external component**, because by that point, the same application with Uvicorn and Python already crashed, so there's nothing in the same code of the same app that could do anything about it.
+
+### Example Tools to Restart Automatically
+
+In most cases, the same tool that is used to **run the program on startup** is also used to handle automatic **restarts**.
+
+For example, this could be handled by:
+
+* Docker
+* Kubernetes
+* Docker Compose
+* Docker in Swarm Mode
+* Systemd
+* Supervisor
+* Handled internally by a cloud provider as part of their services
+* Others...
+
+## Replication - Processes and Memory
+
+With a FastAPI application, using a server program like Uvicorn, running it once in **one process** can serve multiple clients concurrently.
+
+But in many cases, you will want to run several worker processes at the same time.
+
+### Multiple Processes - Workers
+
+If you have more clients than what a single process can handle (for example if the virtual machine is not too big) and you have **multiple cores** in the server's CPU, then you could have **multiple processes** running with the same application at the same time, and distribute all the requests among them.
+
+When you run **multiple processes** of the same API program, they are commonly called **workers**.
+
+### Worker Processes and Ports
+
+Remember from the docs [About HTTPS](./https.md){.internal-link target=_blank} that only one process can be listening on one combination of port and IP address in a server?
+
+This is still true.
+
+So, to be able to have **multiple processes** at the same time, there has to be a **single process listening on a port** that then transmits the communication to each worker process in some way.
+
+### Memory per Process
+
+Now, when the program loads things in memory, for example, a machine learning model in a variable, or the contents of a large file in a variable, all that **consumes a bit of the memory (RAM)** of the server.
+
+And multiple processes normally **don't share any memory**. This means that each running process has its own things, variables, and memory. And if you are consuming a large amount of memory in your code, **each process** will consume an equivalent amount of memory.
+
+### Server Memory
+
+For example, if your code loads a Machine Learning model with **1 GB in size**, when you run one process with your API, it will consume at least 1 GB of RAM. And if you start **4 processes** (4 workers), each will consume 1 GB of RAM. So in total, your API will consume **4 GB of RAM**.
+
+And if your remote server or virtual machine only has 3 GB of RAM, trying to load more than 4 GB of RAM will cause problems. 🚨
+
+### Multiple Processes - An Example
+
+In this example, there's a **Manager Process** that starts and controls two **Worker Processes**.
+
+This Manager Process would probably be the one listening on the **port** in the IP. And it would transmit all the communication to the worker processes.
+
+Those worker processes would be the ones running your application, they would perform the main computations to receive a **request** and return a **response**, and they would load anything you put in variables in RAM.
+
+
+
+Now run `space login` from the Space CLI. Upon pasting the token into the CLI prompt and pressing enter, you should see a confirmation message.
+
+
+
+Click on the new app called `fastapi-deta`, and it will open your API in a new browser tab on a URL like `https://fastapi-deta-gj7ka8.deta.app/`.
+
+You will get a JSON response from your FastAPI app:
+
+```JSON
+{
+ "Hello": "World"
+}
+```
+
+And now you can head over to the `/docs` of your API. For this example, it would be `https://fastapi-deta-gj7ka8.deta.app/docs`.
+
+
+
+## Enable public access
+
+Deta will handle authentication for your account using cookies. By default, every app or API that you `push` or install to your Space is personal - it's only accessible to you.
+
+But you can also make your API public using the `Spacefile` from earlier.
+
+With a `public_routes` parameter, you can specify which paths of your API should be available to the public.
+
+Set your `public_routes` to `"*"` to open every route of your API to the public:
+
+```yaml
+v: 0
+micros:
+ - name: fastapi-deta
+ src: .
+ engine: python3.9
+ public_routes:
+ - "/*"
+```
+
+Then run `space push` again to update your live API on Deta Space.
+
+Once it deploys, you can share your URL with anyone and they will be able to access your API. 🚀
+
+## HTTPS
+
+Congrats! You deployed your FastAPI app to Deta Space! 🎉 🍰
+
+Also, notice that Deta Space correctly handles HTTPS for you, so you don't have to take care of that and can be sure that your users will have a secure encrypted connection. ✅ 🔒
+
+## Create a release
+
+Space also allows you to publish your API. When you publish it, anyone else can install their own copy of your API, in their own Deta Space cloud.
+
+To do so, run `space release` in the Space CLI to create an **unlisted release**:
+
+
+
+## Learn more
+
+At some point, you will probably want to store some data for your app in a way that persists through time. For that you can use Deta Base and Deta Drive, both of which have a generous **free tier**.
+
+You can also read more in the Deta Space Documentation.
+
+!!! tip
+ If you have any Deta related questions, comments, or feedback, head to the Deta Discord server.
+
+
+## Deployment Concepts
+
+Coming back to the concepts we discussed in [Deployments Concepts](./concepts.md){.internal-link target=_blank}, here's how each of them would be handled with Deta Space:
+
+- **HTTPS**: Handled by Deta Space, they will give you a subdomain and handle HTTPS automatically.
+- **Running on startup**: Handled by Deta Space, as part of their service.
+- **Restarts**: Handled by Deta Space, as part of their service.
+- **Replication**: Handled by Deta Space, as part of their service.
+- **Authentication**: Handled by Deta Space, as part of their service.
+- **Memory**: Limit predefined by Deta Space, you could contact them to increase it.
+- **Previous steps before starting**: Can be configured using the `Spacefile`.
+
+!!! note
+ Deta Space is designed to make it easy and free to build cloud applications for yourself. Then you can optionally share them with anyone.
+
+ It can simplify several use cases, but at the same time, it doesn't support others, like using external databases (apart from Deta's own NoSQL database system), custom virtual machines, etc.
+
+ You can read more details in the Deta Space Documentation to see if it's the right choice for you.
From a85f630a855b891070a777b66abcf3ead7935bc4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:07 +0800
Subject: [PATCH 045/163] New translations docker.md (Chinese Simplified)
---
docs/zh/docs/deployment/docker.md | 698 ++++++++++++++++++++++++++++++
1 file changed, 698 insertions(+)
create mode 100644 docs/zh/docs/deployment/docker.md
diff --git a/docs/zh/docs/deployment/docker.md b/docs/zh/docs/deployment/docker.md
new file mode 100644
index 0000000000000..fac4650a2626e
--- /dev/null
+++ b/docs/zh/docs/deployment/docker.md
@@ -0,0 +1,698 @@
+# FastAPI in Containers - Docker
+
+When deploying FastAPI applications a common approach is to build a **Linux container image**. It's normally done using **Docker**. You can then deploy that container image in one of a few possible ways.
+
+Using Linux containers has several advantages including **security**, **replicability**, **simplicity**, and others.
+
+!!! tip
+ In a hurry and already know this stuff? Jump to the [`Dockerfile` below 👇](#build-a-docker-image-for-fastapi).
+
++ **FastAPI** wouldn't exist if not for the previous work of others. + + There have been many tools created before that have helped inspire its creation. + + I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools. + + But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints). ++ +## Investigation + +By using all the previous alternatives I had the chance to learn from all of them, take ideas, and combine them in the best way I could find for myself and the teams of developers I have worked with. + +For example, it was clear that ideally it should be based on standard Python type hints. + +Also, the best approach was to use already existing standards. + +So, before even starting to code **FastAPI**, I spent several months studying the specs for OpenAPI, JSON Schema, OAuth2, etc. Understanding their relationship, overlap, and differences. + +## Design + +Then I spent some time designing the developer "API" I wanted to have as a user (as a developer using FastAPI). + +I tested several ideas in the most popular Python editors: PyCharm, VS Code, Jedi based editors. + +By the last Python Developer Survey, that covers about 80% of the users. + +It means that **FastAPI** was specifically tested with the editors used by 80% of the Python developers. And as most of the other editors tend to work similarly, all its benefits should work for virtually all editors. + +That way I could find the best ways to reduce code duplication as much as possible, to have completion everywhere, type and error checks, etc. + +All in a way that provided the best development experience for all the developers. + +## Requirements + +After testing several alternatives, I decided that I was going to use **Pydantic** for its advantages. + +Then I contributed to it, to make it fully compliant with JSON Schema, to support different ways to define constraint declarations, and to improve editor support (type checks, autocompletion) based on the tests in several editors. + +During the development, I also contributed to **Starlette**, the other key requirement. + +## Development + +By the time I started creating **FastAPI** itself, most of the pieces were already in place, the design was defined, the requirements and tools were ready, and the knowledge about the standards and specifications was clear and fresh. + +## Future + +By this point, it's already clear that **FastAPI** with its ideas is being useful for many people. + +It is being chosen over previous alternatives for suiting many use cases better. + +Many developers and teams already depend on **FastAPI** for their projects (including me and my team). + +But still, there are many improvements and features to come. + +**FastAPI** has a great future ahead. + +And [your help](help-fastapi.md){.internal-link target=_blank} is greatly appreciated. From 9797d5b5715ccd2435b4283cacfcd74da12658c3 Mon Sep 17 00:00:00 2001 From: Sefank <12670778+Sefank@users.noreply.github.com> Date: Wed, 26 Jul 2023 16:37:18 +0800 Subject: [PATCH 056/163] New translations index.md (Chinese Simplified) --- docs/zh/docs/index.md | 345 ++++++++++++++++++++++-------------------- 1 file changed, 177 insertions(+), 168 deletions(-) diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index 1de2a8d36d09a..ebd74bc8f00d2 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -2,43 +2,45 @@
- FastAPI 框架,高性能,易于学习,高效编码,生产可用 + FastAPI framework, high performance, easy to learn, fast to code, ready for production
--- -**文档**: https://fastapi.tiangolo.com +**Documentation**: https://fastapi.tiangolo.com -**源码**: https://github.com/tiangolo/fastapi +**Source Code**: https://github.com/tiangolo/fastapi --- -FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。 +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints. -关键特性: +The key features are: -* **快速**:可与 **NodeJS** 和 **Go** 并肩的极高性能(归功于 Starlette 和 Pydantic)。[最快的 Python web 框架之一](#_11)。 +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Easy**: Designed to be easy to use and learn. Less time reading docs. +* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. -* **高效编码**:提高功能开发速度约 200% 至 300%。* -* **更少 bug**:减少约 40% 的人为(开发者)导致错误。* -* **智能**:极佳的编辑器支持。处处皆可自动补全,减少调试时间。 -* **简单**:设计的易于使用和学习,阅读文档的时间更短。 -* **简短**:使代码重复最小化。通过不同的参数声明实现丰富功能。bug 更少。 -* **健壮**:生产可用级别的代码。还有自动生成的交互式文档。 -* **标准化**:基于(并完全兼容)API 的相关开放标准:OpenAPI (以前被称为 Swagger) 和 JSON Schema。 - -* 根据对某个构建线上应用的内部开发团队所进行的测试估算得出。 +* estimation based on tests on an internal development team, building production applications. ## Sponsors @@ -57,64 +59,70 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框 Other sponsors -## 评价 +## Opinions -「_[...] 最近我一直在使用 **FastAPI**。[...] 实际上我正在计划将其用于我所在的**微软**团队的所有**机器学习服务**。其中一些服务正被集成进核心 **Windows** 产品和一些 **Office** 产品。_」 +"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" -async def...async def...uvicorn main:app --reload 命令......uvicorn main:app --reload...email_validator - 用于 email 校验。
+* email_validator - for email validation.
+* pydantic-settings - for settings management.
+* pydantic-extra-types - for extra types to be used with Pydantic.
-用于 Starlette:
+Used by Starlette:
-* httpx - 使用 `TestClient` 时安装。
-* jinja2 - 使用默认模板配置时安装。
-* python-multipart - 需要通过 `request.form()` 对表单进行「解析」时安装。
-* itsdangerous - 需要 `SessionMiddleware` 支持时安装。
-* pyyaml - 使用 Starlette 提供的 `SchemaGenerator` 时安装(有 FastAPI 你可能并不需要它)。
-* graphene - 需要 `GraphQLApp` 支持时安装。
-* ujson - 使用 `UJSONResponse` 时安装。
+* httpx - Required if you want to use the `TestClient`.
+* jinja2 - Required if you want to use the default template configuration.
+* python-multipart - Required if you want to support form "parsing", with `request.form()`.
+* itsdangerous - Required for `SessionMiddleware` support.
+* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
+* ujson - Required if you want to use `UJSONResponse`.
-用于 FastAPI / Starlette:
+Used by FastAPI / Starlette:
-* uvicorn - 用于加载和运行你的应用程序的服务器。
-* orjson - 使用 `ORJSONResponse` 时安装。
+* uvicorn - for the server that loads and serves your application.
+* orjson - Required if you want to use `ORJSONResponse`.
-你可以通过 `pip install fastapi[all]` 命令来安装以上所有依赖。
+You can install all of these with `pip install "fastapi[all]"`.
-## 许可协议
+## License
-该项目遵循 MIT 许可协议。
+This project is licensed under the terms of the MIT license.
From 91e9ecbde6b78e1646da95d8e0e337f86032118f Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:18 +0800
Subject: [PATCH 057/163] New translations newsletter.md (Chinese Simplified)
---
docs/zh/docs/newsletter.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 docs/zh/docs/newsletter.md
diff --git a/docs/zh/docs/newsletter.md b/docs/zh/docs/newsletter.md
new file mode 100644
index 0000000000000..782db1353c8d0
--- /dev/null
+++ b/docs/zh/docs/newsletter.md
@@ -0,0 +1,5 @@
+# FastAPI and friends newsletter
+
+
+
+
From 7e4cf98c7dc8b295f9c3d222c8078d680206bc12 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:19 +0800
Subject: [PATCH 058/163] New translations project-generation.md (Chinese
Simplified)
---
docs/zh/docs/project-generation.md | 84 ++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
create mode 100644 docs/zh/docs/project-generation.md
diff --git a/docs/zh/docs/project-generation.md b/docs/zh/docs/project-generation.md
new file mode 100644
index 0000000000000..8ba34fa11200d
--- /dev/null
+++ b/docs/zh/docs/project-generation.md
@@ -0,0 +1,84 @@
+# Project Generation - Template
+
+You can use a project generator to get started, as it includes a lot of the initial set up, security, database and some API endpoints already done for you.
+
+A project generator will always have a very opinionated setup that you should update and adapt for your own needs, but it might be a good starting point for your project.
+
+## Full Stack FastAPI PostgreSQL
+
+GitHub: https://github.com/tiangolo/full-stack-fastapi-postgresql
+
+### Full Stack FastAPI PostgreSQL - Features
+
+* Full **Docker** integration (Docker based).
+* Docker Swarm Mode deployment.
+* **Docker Compose** integration and optimization for local development.
+* **Production ready** Python web server using Uvicorn and Gunicorn.
+* Python **FastAPI** backend:
+ * **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic).
+ * **Intuitive**: Great editor support. Completion everywhere. Less time debugging.
+ * **Easy**: Designed to be easy to use and learn. Less time reading docs.
+ * **Short**: Minimize code duplication. Multiple features from each parameter declaration.
+ * **Robust**: Get production-ready code. With automatic interactive documentation.
+ * **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI and JSON Schema.
+ * **Many other features** including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
+* **Secure password** hashing by default.
+* **JWT token** authentication.
+* **SQLAlchemy** models (independent of Flask extensions, so they can be used with Celery workers directly).
+* Basic starting models for users (modify and remove as you need).
+* **Alembic** migrations.
+* **CORS** (Cross Origin Resource Sharing).
+* **Celery** worker that can import and use models and code from the rest of the backend selectively.
+* REST backend tests based on **Pytest**, integrated with Docker, so you can test the full API interaction, independent on the database. As it runs in Docker, it can build a new data store from scratch each time (so you can use ElasticSearch, MongoDB, CouchDB, or whatever you want, and just test that the API works).
+* Easy Python integration with **Jupyter Kernels** for remote or in-Docker development with extensions like Atom Hydrogen or Visual Studio Code Jupyter.
+* **Vue** frontend:
+ * Generated with Vue CLI.
+ * **JWT Authentication** handling.
+ * Login view.
+ * After login, main dashboard view.
+ * Main dashboard with user creation and edition.
+ * Self user edition.
+ * **Vuex**.
+ * **Vue-router**.
+ * **Vuetify** for beautiful material design components.
+ * **TypeScript**.
+ * Docker server based on **Nginx** (configured to play nicely with Vue-router).
+ * Docker multi-stage building, so you don't need to save or commit compiled code.
+ * Frontend tests ran at build time (can be disabled too).
+ * Made as modular as possible, so it works out of the box, but you can re-generate with Vue CLI or create it as you need, and re-use what you want.
+* **PGAdmin** for PostgreSQL database, you can modify it to use PHPMyAdmin and MySQL easily.
+* **Flower** for Celery jobs monitoring.
+* Load balancing between frontend and backend with **Traefik**, so you can have both under the same domain, separated by path, but served by different containers.
+* Traefik integration, including Let's Encrypt **HTTPS** certificates automatic generation.
+* GitLab **CI** (continuous integration), including frontend and backend testing.
+
+## Full Stack FastAPI Couchbase
+
+GitHub: https://github.com/tiangolo/full-stack-fastapi-couchbase
+
+⚠️ **WARNING** ⚠️
+
+If you are starting a new project from scratch, check the alternatives here.
+
+For example, the project generator Full Stack FastAPI PostgreSQL might be a better alternative, as it is actively maintained and used. And it includes all the new features and improvements.
+
+You are still free to use the Couchbase-based generator if you want to, it should probably still work fine, and if you already have a project generated with it that's fine as well (and you probably already updated it to suit your needs).
+
+You can read more about it in the docs for the repo.
+
+## Full Stack FastAPI MongoDB
+
+...might come later, depending on my time availability and other factors. 😅 🎉
+
+## Machine Learning models with spaCy and FastAPI
+
+GitHub: https://github.com/microsoft/cookiecutter-spacy-fastapi
+
+### Machine Learning models with spaCy and FastAPI - Features
+
+* **spaCy** NER model integration.
+* **Azure Cognitive Search** request format built in.
+* **Production ready** Python web server using Uvicorn and Gunicorn.
+* **Azure DevOps** Kubernetes (AKS) CI/CD deployment built in.
+* **Multilingual** Easily choose one of spaCy's built in languages during project setup.
+* **Easily extensible** to other model frameworks (Pytorch, Tensorflow), not just spaCy.
From f015c66f5dab1aa39e2110770c77ff844be329ca Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:21 +0800
Subject: [PATCH 059/163] New translations python-types.md (Chinese Simplified)
---
docs/zh/docs/python-types.md | 496 ++++++++++++++++++++++++++---------
1 file changed, 374 insertions(+), 122 deletions(-)
diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md
index 6cdb4b58838d7..34350d70befba 100644
--- a/docs/zh/docs/python-types.md
+++ b/docs/zh/docs/python-types.md
@@ -1,139 +1,139 @@
-# Python 类型提示简介
+# Python Types Intro
-**Python 3.6+ 版本**加入了对"类型提示"的支持。
+Python has support for optional "type hints" (also called "type annotations").
-这些**"类型提示"**是一种新的语法(在 Python 3.6 版本加入)用来声明一个变量的类型。
+These **"type hints"** or annotations are a special syntax that allow declaring the type of a variable.
-通过声明变量的类型,编辑器和一些工具能给你提供更好的支持。
+By declaring types for your variables, editors and tools can give you better support.
-这只是一个关于 Python 类型提示的**快速入门 / 复习**。它仅涵盖与 **FastAPI** 一起使用所需的最少部分...实际上只有很少一点。
+This is just a **quick tutorial / refresher** about Python type hints. It covers only the minimum necessary to use them with **FastAPI**... which is actually very little.
-整个 **FastAPI** 都基于这些类型提示构建,它们带来了许多优点和好处。
+**FastAPI** is all based on these type hints, they give it many advantages and benefits.
-但即使你不会用到 **FastAPI**,了解一下类型提示也会让你从中受益。
+But even if you never use **FastAPI**, you would benefit from learning a bit about them.
!!! note
- 如果你已经精通 Python,并且了解关于类型提示的一切知识,直接跳到下一章节吧。
+ If you are a Python expert, and you already know everything about type hints, skip to the next chapter.
-## 动机
+## Motivation
-让我们从一个简单的例子开始:
+Let's start with a simple example:
```Python
{!../../../docs_src/python_types/tutorial001.py!}
```
-运行这段程序将输出:
+Calling this program outputs:
```
John Doe
```
-这个函数做了下面这些事情:
+The function does the following:
-* 接收 `first_name` 和 `last_name` 参数。
-* 通过 `title()` 将每个参数的第一个字母转换为大写形式。
-* 中间用一个空格来拼接它们。
+* Takes a `first_name` and `last_name`.
+* Converts the first letter of each one to upper case with `title()`.
+* Concatenates them with a space in the middle.
```Python hl_lines="2"
{!../../../docs_src/python_types/tutorial001.py!}
```
-### 修改示例
+### Edit it
-这是一个非常简单的程序。
+It's a very simple program.
-现在假设你将从头开始编写这段程序。
+But now imagine that you were writing it from scratch.
-在某一时刻,你开始定义函数,并且准备好了参数...。
+At some point you would have started the definition of the function, you had the parameters ready...
-现在你需要调用一个"将第一个字母转换为大写形式的方法"。
+But then you have to call "that method that converts the first letter to upper case".
-等等,那个方法是什么来着?`upper`?还是 `uppercase`?`first_uppercase`?`capitalize`?
+Was it `upper`? Was it `uppercase`? `first_uppercase`? `capitalize`?
-然后你尝试向程序员老手的朋友——编辑器自动补全寻求帮助。
+Then, you try with the old programmer's friend, editor autocompletion.
-输入函数的第一个参数 `first_name`,输入点号(`.`)然后敲下 `Ctrl+Space` 来触发代码补全。
+You type the first parameter of the function, `first_name`, then a dot (`.`) and then hit `Ctrl+Space` to trigger the completion.
-但遗憾的是并没有起什么作用:
+But, sadly, you get nothing useful:
-
+
-### 添加类型
+### Add types
-让我们来修改上面例子的一行代码。
+Let's modify a single line from the previous version.
-我们将把下面这段代码中的函数参数从:
+We will change exactly this fragment, the parameters of the function, from:
```Python
first_name, last_name
```
-改成:
+to:
```Python
first_name: str, last_name: str
```
-就是这样。
+That's it.
-这些就是"类型提示":
+Those are the "type hints":
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial002.py!}
```
-这和声明默认值是不同的,例如:
+That is not the same as declaring default values like would be with:
```Python
first_name="john", last_name="doe"
```
-这两者不一样。
+It's a different thing.
-我们用的是冒号(`:`),不是等号(`=`)。
+We are using colons (`:`), not equals (`=`).
-而且添加类型提示一般不会改变原来的运行结果。
+And adding type hints normally doesn't change what happens from what would happen without them.
-现在假设我们又一次正在创建这个函数,这次添加了类型提示。
+But now, imagine you are again in the middle of creating that function, but with type hints.
-在同样的地方,通过 `Ctrl+Space` 触发自动补全,你会发现:
+At the same point, you try to trigger the autocomplete with `Ctrl+Space` and you see:
-
+
-这样,你可以滚动查看选项,直到你找到看起来眼熟的那个:
+With that, you can scroll, seeing the options, until you find the one that "rings a bell":
-
+
-## 更多动机
+## More motivation
-下面是一个已经有类型提示的函数:
+Check this function, it already has type hints:
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial003.py!}
```
-因为编辑器已经知道了这些变量的类型,所以不仅能对代码进行补全,还能检查其中的错误:
+Because the editor knows the types of the variables, you don't only get completion, you also get error checks:
-
+
-现在你知道了必须先修复这个问题,通过 `str(age)` 把 `age` 转换成字符串:
+Now you know that you have to fix it, convert `age` to a string with `str(age)`:
```Python hl_lines="2"
{!../../../docs_src/python_types/tutorial004.py!}
```
-## 声明类型
+## Declaring types
-你刚刚看到的就是声明类型提示的主要场景。用于函数的参数。
+You just saw the main place to declare type hints. As function parameters.
-这也是你将在 **FastAPI** 中使用它们的主要场景。
+This is also the main place you would use them with **FastAPI**.
-### 简单类型
+### Simple types
-不只是 `str`,你能够声明所有的标准 Python 类型。
+You can declare all the standard Python types, not only `str`.
-比如以下类型:
+You can use, for example:
* `int`
* `float`
@@ -144,143 +144,395 @@ John Doe
{!../../../docs_src/python_types/tutorial005.py!}
```
-### 嵌套类型
+### Generic types with type parameters
-有些容器数据结构可以包含其他的值,比如 `dict`、`list`、`set` 和 `tuple`。它们内部的值也会拥有自己的类型。
+There are some data structures that can contain other values, like `dict`, `list`, `set` and `tuple`. And the internal values can have their own type too.
-你可以使用 Python 的 `typing` 标准库来声明这些类型以及子类型。
+These types that have internal types are called "**generic**" types. And it's possible to declare them, even with their internal types.
-它专门用来支持这些类型提示。
+To declare those types and the internal types, you can use the standard Python module `typing`. It exists specifically to support these type hints.
-#### 列表
+#### Newer versions of Python
-例如,让我们来定义一个由 `str` 组成的 `list` 变量。
+The syntax using `typing` is **compatible** with all versions, from Python 3.6 to the latest ones, including Python 3.9, Python 3.10, etc.
-从 `typing` 模块导入 `List`(注意是大写的 `L`):
+As Python advances, **newer versions** come with improved support for these type annotations and in many cases you won't even need to import and use the `typing` module to declare the type annotations.
-```Python hl_lines="1"
-{!../../../docs_src/python_types/tutorial006.py!}
-```
+If you can choose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity.
-同样以冒号(`:`)来声明这个变量。
+In all the docs there are examples compatible with each version of Python (when there's a difference).
-输入 `List` 作为类型。
+For example "**Python 3.6+**" means it's compatible with Python 3.6 or above (including 3.7, 3.8, 3.9, 3.10, etc). And "**Python 3.9+**" means it's compatible with Python 3.9 or above (including 3.10, etc).
-由于列表是带有"子类型"的类型,所以我们把子类型放在方括号中:
+If you can use the **latest versions of Python**, use the examples for the latest version, those will have the **best and simplest syntax**, for example, "**Python 3.10+**".
-```Python hl_lines="4"
-{!../../../docs_src/python_types/tutorial006.py!}
-```
+#### List
+
+For example, let's define a variable to be a `list` of `str`.
+
+=== "Python 3.9+"
+
+ Declare the variable, with the same colon (`:`) syntax.
+
+ As the type, put `list`.
+
+ As the list is a type that contains some internal types, you put them in square brackets:
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial006_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ From `typing`, import `List` (with a capital `L`):
+
+ ``` Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial006.py!}
+ ```
+
+
+ Declare the variable, with the same colon (`:`) syntax.
+
+ As the type, put the `List` that you imported from `typing`.
+
+ As the list is a type that contains some internal types, you put them in square brackets:
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/python_types/tutorial006.py!}
+ ```
+
+!!! info
+ Those internal types in the square brackets are called "type parameters".
+
+ In this case, `str` is the type parameter passed to `List` (or `list` in Python 3.9 and above).
+
+That means: "the variable `items` is a `list`, and each of the items in this list is a `str`".
+
+!!! tip
+ If you use Python 3.9 or above, you don't have to import `List` from `typing`, you can use the same regular `list` type instead.
+
+By doing that, your editor can provide support even while processing items from the list:
+
+
+
+Without types, that's almost impossible to achieve.
+
+Notice that the variable `item` is one of the elements in the list `items`.
+
+And still, the editor knows it is a `str`, and provides support for that.
+
+#### Tuple and Set
+
+You would do the same to declare `tuple`s and `set`s:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial007_py39.py!}
+ ```
-这表示:"变量 `items` 是一个 `list`,并且这个列表里的每一个元素都是 `str`"。
+=== "Python 3.6+"
-这样,即使在处理列表中的元素时,你的编辑器也可以提供支持。
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial007.py!}
+ ```
-没有类型,几乎是不可能实现下面这样:
+This means:
-
+* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
+* The variable `items_s` is a `set`, and each of its items is of type `bytes`.
-注意,变量 `item` 是列表 `items` 中的元素之一。
+#### Dict
-而且,编辑器仍然知道它是一个 `str`,并为此提供了支持。
+To define a `dict`, you pass 2 type parameters, separated by commas.
-#### 元组和集合
+The first type parameter is for the keys of the `dict`.
-声明 `tuple` 和 `set` 的方法也是一样的:
+The second type parameter is for the values of the `dict`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial008_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial008.py!}
+ ```
+
+This means:
+
+* The variable `prices` is a `dict`:
+ * The keys of this `dict` are of type `str` (let's say, the name of each item).
+ * The values of this `dict` are of type `float` (let's say, the price of each item).
+
+#### Union
+
+You can declare that a variable can be any of **several types**, for example, an `int` or a `str`.
+
+In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept.
+
+In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a vertical bar (`|`).
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial008b_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial008b.py!}
+ ```
+
+In both cases this means that `item` could be an `int` or a `str`.
+
+#### Possibly `None`
+
+You can declare that a value could have a type, like `str`, but that it could also be `None`.
+
+In Python 3.6 and above (including Python 3.10) you can declare it by importing and using `Optional` from the `typing` module.
```Python hl_lines="1 4"
-{!../../../docs_src/python_types/tutorial007.py!}
+{!../../../docs_src/python_types/tutorial009.py!}
```
-这表示:
+Using `Optional[str]` instead of just `str` will let the editor help you detecting errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
+
+`Optional[Something]` is actually a shortcut for `Union[Something, None]`, they are equivalent.
+
+This also means that in Python 3.10, you can use `Something | None`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/python_types/tutorial009_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial009.py!}
+ ```
+
+=== "Python 3.6+ alternative"
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial009b.py!}
+ ```
+
+#### Using `Union` or `Optional`
-* 变量 `items_t` 是一个 `tuple`,其中的前两个元素都是 `int` 类型, 最后一个元素是 `str` 类型。
-* 变量 `items_s` 是一个 `set`,其中的每个元素都是 `bytes` 类型。
+If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:
-#### 字典
+* 🚨 Avoid using `Optional[SomeType]`
+* Instead ✨ **use `Union[SomeType, None]`** ✨.
-定义 `dict` 时,需要传入两个子类型,用逗号进行分隔。
+Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required.
-第一个子类型声明 `dict` 的所有键。
+I think `Union[SomeType, None]` is more explicit about what it means.
-第二个子类型声明 `dict` 的所有值:
+It's just about the words and names. But those words can affect how you and your teammates think about the code.
+
+As an example, let's take this function:
+
+```Python hl_lines="1 4"
+{!../../../docs_src/python_types/tutorial009c.py!}
+```
+
+The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter:
+
+```Python
+say_hi() # Oh, no, this throws an error! 😱
+```
+
+The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value:
+
+```Python
+say_hi(name=None) # This works, None is valid 🎉
+```
+
+The good news is, once you are on Python 3.10 you won't have to worry about that, as you will be able to simply use `|` to define unions of types:
```Python hl_lines="1 4"
-{!../../../docs_src/python_types/tutorial008.py!}
+{!../../../docs_src/python_types/tutorial009c_py310.py!}
```
-这表示:
+And then you won't have to worry about names like `Optional` and `Union`. 😎
+
+#### Generic types
+
+These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
+
+=== "Python 3.10+"
+
+ You can use the same builtin types as generics (with square brackets and types inside):
+
+ * `list`
+ * `tuple`
+ * `set`
+ * `dict`
+
+ And the same as with Python 3.6, from the `typing` module:
+
+ * `Union`
+ * `Optional` (the same as with Python 3.6)
+ * ...and others.
+
+ In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the vertical bar (`|`) to declare unions of types, that's a lot better and simpler.
+
+=== "Python 3.9+"
+
+ You can use the same builtin types as generics (with square brackets and types inside):
+
+ * `list`
+ * `tuple`
+ * `set`
+ * `dict`
+
+ And the same as with Python 3.6, from the `typing` module:
+
+ * `Union`
+ * `Optional`
+ * ...and others.
+
+=== "Python 3.6+"
-* 变量 `prices` 是一个 `dict`:
- * 这个 `dict` 的所有键为 `str` 类型(可以看作是字典内每个元素的名称)。
- * 这个 `dict` 的所有值为 `float` 类型(可以看作是字典内每个元素的价格)。
+ * `List`
+ * `Tuple`
+ * `Set`
+ * `Dict`
+ * `Union`
+ * `Optional`
+ * ...and others.
-### 类作为类型
+### Classes as types
-你也可以将类声明为变量的类型。
+You can also declare a class as the type of a variable.
-假设你有一个名为 `Person` 的类,拥有 name 属性:
+Let's say you have a class `Person`, with a name:
```Python hl_lines="1-3"
{!../../../docs_src/python_types/tutorial010.py!}
```
-接下来,你可以将一个变量声明为 `Person` 类型:
+Then you can declare a variable to be of type `Person`:
```Python hl_lines="6"
{!../../../docs_src/python_types/tutorial010.py!}
```
-然后,你将再次获得所有的编辑器支持:
+And then, again, you get all the editor support:
-
+
-## Pydantic 模型
+Notice that this means "`one_person` is an **instance** of the class `Person`".
-Pydantic 是一个用来用来执行数据校验的 Python 库。
+It doesn't mean "`one_person` is the **class** called `Person`".
-你可以将数据的"结构"声明为具有属性的类。
+## Pydantic models
-每个属性都拥有类型。
+Pydantic is a Python library to perform data validation.
-接着你用一些值来创建这个类的实例,这些值会被校验,并被转换为适当的类型(在需要的情况下),返回一个包含所有数据的对象。
+You declare the "shape" of the data as classes with attributes.
-然后,你将获得这个对象的所有编辑器支持。
+And each attribute has a type.
-下面的例子来自 Pydantic 官方文档:
+Then you create an instance of that class with some values and it will validate the values, convert them to the appropriate type (if that's the case) and give you an object with all the data.
-```Python
-{!../../../docs_src/python_types/tutorial010.py!}
-```
+And you get all the editor support with that resulting object.
+
+An example from the official Pydantic docs:
+
+=== "Python 3.10+"
+
+ ```Python
+ {!> ../../../docs_src/python_types/tutorial011_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python
+ {!> ../../../docs_src/python_types/tutorial011_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ {!> ../../../docs_src/python_types/tutorial011.py!}
+ ```
!!! info
- 想进一步了解 Pydantic,请阅读其文档.
+ To learn more about Pydantic, check its docs.
+
+**FastAPI** is all based on Pydantic.
+
+You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
+
+!!! tip
+ Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about Required Optional fields.
+
+## Type Hints with Metadata Annotations
+
+Python also has a feature that allows putting **additional metadata** in these type hints using `Annotated`.
+
+=== "Python 3.9+"
+
+ In Python 3.9, `Annotated` is part of the standard library, so you can import it from `typing`.
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial013_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ In versions below Python 3.9, you import `Annotated` from `typing_extensions`.
+
+ It will already be installed with **FastAPI**.
+
+ ```Python hl_lines="1 4"
+ {!> ../../../docs_src/python_types/tutorial013.py!}
+ ```
+
+Python itself doesn't do anything with this `Annotated`. And for editors and other tools, the type is still `str`.
+
+But you can use this space in `Annotated` to provide **FastAPI** with additional metadata about how you want your application to behave.
+
+The important thing to remember is that ***the first ***type parameter****** you pass to `Annotated` is the **actual type**. The rest, is just metadata for other tools.
+
+For now, you just need to know that `Annotated` exists, and that it's standard Python. 😎
+
+Later you will see how **powerful** it can be.
-整个 **FastAPI** 建立在 Pydantic 的基础之上。
+!!! tip
+ The fact that this is **standard Python** means that you will still get the **best possible developer experience** in your editor, with the tools you use to analyze and refactor your code, etc. ✨
-实际上你将在 [教程 - 用户指南](tutorial/index.md){.internal-link target=_blank} 看到很多这种情况。
+ And also that your code will be very compatible with many other Python tools and libraries. 🚀
-## **FastAPI** 中的类型提示
+## Type hints in **FastAPI**
-**FastAPI** 利用这些类型提示来做下面几件事。
+**FastAPI** takes advantage of these type hints to do several things.
-使用 **FastAPI** 时用类型提示声明参数可以获得:
+With **FastAPI** you declare parameters with type hints and you get:
-* **编辑器支持**。
-* **类型检查**。
+* **Editor support**.
+* **Type checks**.
-...并且 **FastAPI** 还会用这些类型声明来:
+...and **FastAPI** uses the same declarations to:
-* **定义参数要求**:声明对请求路径参数、查询参数、请求头、请求体、依赖等的要求。
-* **转换数据**:将来自请求的数据转换为需要的类型。
-* **校验数据**: 对于每一个请求:
- * 当数据校验失败时自动生成**错误信息**返回给客户端。
-* 使用 OpenAPI **记录** API:
- * 然后用于自动生成交互式文档的用户界面。
+* **Define requirements**: from request path parameters, query parameters, headers, bodies, dependencies, etc.
+* **Convert data**: from the request to the required type.
+* **Validate data**: coming from each request:
+ * Generating **automatic errors** returned to the client when the data is invalid.
+* **Document** the API using OpenAPI:
+ * which is then used by the automatic interactive documentation user interfaces.
-听上去有点抽象。不过不用担心。你将在 [教程 - 用户指南](tutorial/index.md){.internal-link target=_blank} 中看到所有的实战。
+This might all sound abstract. Don't worry. You'll see all this in action in the [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank}.
-最重要的是,通过使用标准的 Python 类型,只需要在一个地方声明(而不是添加更多的类、装饰器等),**FastAPI** 会为你完成很多的工作。
+The important thing is that by using standard Python types, in a single place (instead of adding more classes, decorators, etc), **FastAPI** will do a lot of the work for you.
!!! info
- 如果你已经阅读了所有教程,回过头来想了解有关类型的更多信息,来自 `mypy` 的"速查表"是不错的资源。
+ If you already went through all the tutorial and came back to see more about types, a good resource is the "cheat sheet" from `mypy`.
From 254be13bc5753c47dff19e9525d74a6aec0a97a5 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:21 +0800
Subject: [PATCH 060/163] New translations background-tasks.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/background-tasks.md | 126 ++++++++++++++++++++++
1 file changed, 126 insertions(+)
create mode 100644 docs/zh/docs/tutorial/background-tasks.md
diff --git a/docs/zh/docs/tutorial/background-tasks.md b/docs/zh/docs/tutorial/background-tasks.md
new file mode 100644
index 0000000000000..1782971922ab2
--- /dev/null
+++ b/docs/zh/docs/tutorial/background-tasks.md
@@ -0,0 +1,126 @@
+# Background Tasks
+
+You can define background tasks to be run *after* returning a response.
+
+This is useful for operations that need to happen after a request, but that the client doesn't really have to be waiting for the operation to complete before receiving the response.
+
+This includes, for example:
+
+* Email notifications sent after performing an action:
+ * As connecting to an email server and sending an email tends to be "slow" (several seconds), you can return the response right away and send the email notification in the background.
+* Processing data:
+ * For example, let's say you receive a file that must go through a slow process, you can return a response of "Accepted" (HTTP 202) and process it in the background.
+
+## Using `BackgroundTasks`
+
+First, import `BackgroundTasks` and define a parameter in your *path operation function* with a type declaration of `BackgroundTasks`:
+
+```Python hl_lines="1 13"
+{!../../../docs_src/background_tasks/tutorial001.py!}
+```
+
+**FastAPI** will create the object of type `BackgroundTasks` for you and pass it as that parameter.
+
+## Create a task function
+
+Create a function to be run as the background task.
+
+It is just a standard function that can receive parameters.
+
+It can be an `async def` or normal `def` function, **FastAPI** will know how to handle it correctly.
+
+In this case, the task function will write to a file (simulating sending an email).
+
+And as the write operation doesn't use `async` and `await`, we define the function with normal `def`:
+
+```Python hl_lines="6-9"
+{!../../../docs_src/background_tasks/tutorial001.py!}
+```
+
+## Add the background task
+
+Inside of your *path operation function*, pass your task function to the *background tasks* object with the method `.add_task()`:
+
+```Python hl_lines="14"
+{!../../../docs_src/background_tasks/tutorial001.py!}
+```
+
+`.add_task()` receives as arguments:
+
+* A task function to be run in the background (`write_notification`).
+* Any sequence of arguments that should be passed to the task function in order (`email`).
+* Any keyword arguments that should be passed to the task function (`message="some notification"`).
+
+## Dependency Injection
+
+Using `BackgroundTasks` also works with the dependency injection system, you can declare a parameter of type `BackgroundTasks` at multiple levels: in a *path operation function*, in a dependency (dependable), in a sub-dependency, etc.
+
+**FastAPI** knows what to do in each case and how to re-use the same object, so that all the background tasks are merged together and are run in the background afterwards:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="13 15 22 25"
+ {!> ../../../docs_src/background_tasks/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="13 15 22 25"
+ {!> ../../../docs_src/background_tasks/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="14 16 23 26"
+ {!> ../../../docs_src/background_tasks/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11 13 20 23"
+ {!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="13 15 22 25"
+ {!> ../../../docs_src/background_tasks/tutorial002.py!}
+ ```
+
+In this example, the messages will be written to the `log.txt` file *after* the response is sent.
+
+If there was a query in the request, it will be written to the log in a background task.
+
+And then another background task generated at the *path operation function* will write a message using the `email` path parameter.
+
+## Technical Details
+
+The class `BackgroundTasks` comes directly from `starlette.background`.
+
+It is imported/included directly into FastAPI so that you can import it from `fastapi` and avoid accidentally importing the alternative `BackgroundTask` (without the `s` at the end) from `starlette.background`.
+
+By only using `BackgroundTasks` (and not `BackgroundTask`), it's then possible to use it as a *path operation function* parameter and have **FastAPI** handle the rest for you, just like when using the `Request` object directly.
+
+It's still possible to use `BackgroundTask` alone in FastAPI, but you have to create the object in your code and return a Starlette `Response` including it.
+
+You can see more details in Starlette's official docs for Background Tasks.
+
+## Caveat
+
+If you need to perform heavy background computation and you don't necessarily need it to be run by the same process (for example, you don't need to share memory, variables, etc), you might benefit from using other bigger tools like Celery.
+
+They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers.
+
+To see an example, check the [Project Generators](../project-generation.md){.internal-link target=_blank}, they all include Celery already configured.
+
+But if you need to access variables and objects from the same **FastAPI** app, or you need to perform small background tasks (like sending an email notification), you can simply just use `BackgroundTasks`.
+
+## Recap
+
+Import and use `BackgroundTasks` with parameters in *path operation functions* and dependencies to add background tasks.
From 958cf2f344e204a86a032d45c1805ea890c27c7e Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:22 +0800
Subject: [PATCH 061/163] New translations bigger-applications.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/bigger-applications.md | 413 ++++++++++---------
1 file changed, 216 insertions(+), 197 deletions(-)
diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md
index 9f0134f683c9e..0f990e3367f4f 100644
--- a/docs/zh/docs/tutorial/bigger-applications.md
+++ b/docs/zh/docs/tutorial/bigger-applications.md
@@ -1,15 +1,15 @@
-# 更大的应用 - 多个文件
+# Bigger Applications - Multiple Files
-如果你正在开发一个应用程序或 Web API,很少会将所有的内容都放在一个文件中。
+If you are building an application or a web API, it's rarely the case that you can put everything on a single file.
-**FastAPI** 提供了一个方便的工具,可以在保持所有灵活性的同时构建你的应用程序。
+**FastAPI** provides a convenience tool to structure your application while keeping all the flexibility.
!!! info
- 如果你来自 Flask,那这将相当于 Flask 的 Blueprints。
+ If you come from Flask, this would be the equivalent of Flask's Blueprints.
-## 一个文件结构示例
+## An example file structure
-假设你的文件结构如下:
+Let's say you have a file structure like this:
```
.
@@ -27,127 +27,144 @@
```
!!! tip
- 上面有几个 `__init__.py` 文件:每个目录或子目录中都有一个。
+ There are several `__init__.py` files: one in each directory or subdirectory.
- 这就是能将代码从一个文件导入到另一个文件的原因。
-
- 例如,在 `app/main.py` 中,你可以有如下一行:
+ This is what allows importing code from one file into another.
+
+ For example, in `app/main.py` you could have a line like:
```
from app.routers import items
```
-* `app` 目录包含了所有内容。并且它有一个空文件 `app/__init__.py`,因此它是一个「Python 包」(「Python 模块」的集合):`app`。
-* 它包含一个 `app/main.py` 文件。由于它位于一个 Python 包(一个包含 `__init__.py` 文件的目录)中,因此它是该包的一个「模块」:`app.main`。
-* 还有一个 `app/dependencies.py` 文件,就像 `app/main.py` 一样,它是一个「模块」:`app.dependencies`。
-* 有一个子目录 `app/routers/` 包含另一个 `__init__.py` 文件,因此它是一个「Python 子包」:`app.routers`。
-* 文件 `app/routers/items.py` 位于 `app/routers/` 包中,因此它是一个子模块:`app.routers.items`。
-* 同样适用于 `app/routers/users.py`,它是另一个子模块:`app.routers.users`。
-* 还有一个子目录 `app/internal/` 包含另一个 `__init__.py` 文件,因此它是又一个「Python 子包」:`app.internal`。
-* `app/internal/admin.py` 是另一个子模块:`app.internal.admin`。
+* The `app` directory contains everything. And it has an empty file `app/__init__.py`, so it is a "Python package" (a collection of "Python modules"): `app`.
+* It contains an `app/main.py` file. As it is inside a Python package (a directory with a file `__init__.py`), it is a "module" of that package: `app.main`.
+* There's also an `app/dependencies.py` file, just like `app/main.py`, it is a "module": `app.dependencies`.
+* There's a subdirectory `app/routers/` with another file `__init__.py`, so it's a "Python subpackage": `app.routers`.
+* The file `app/routers/items.py` is inside a package, `app/routers/`, so, it's a submodule: `app.routers.items`.
+* The same with `app/routers/users.py`, it's another submodule: `app.routers.users`.
+* There's also a subdirectory `app/internal/` with another file `__init__.py`, so it's another "Python subpackage": `app.internal`.
+* And the file `app/internal/admin.py` is another submodule: `app.internal.admin`.
-
+
-## 多次使用不同的 `prefix` 包含同一个路由器
+## Include the same router multiple times with different `prefix`
-你也可以在*同一*路由器上使用不同的前缀来多次使用 `.include_router()`。
+You can also use `.include_router()` multiple times with the *same* router using different prefixes.
-在有些场景这可能有用,例如以不同的前缀公开同一个的 API,比方说 `/api/v1` 和 `/api/latest`。
+This could be useful, for example, to expose the same API under different prefixes, e.g. `/api/v1` and `/api/latest`.
-这是一个你可能并不真正需要的高级用法,但万一你有需要了就能够用上。
+This is an advanced usage that you might not really need, but it's there in case you do.
-## 在另一个 `APIRouter` 中包含一个 `APIRouter`
+## Include an `APIRouter` in another
-与在 `FastAPI` 应用程序中包含 `APIRouter` 的方式相同,你也可以在另一个 `APIRouter` 中包含 `APIRouter`,通过:
+The same way you can include an `APIRouter` in a `FastAPI` application, you can include an `APIRouter` in another `APIRouter` using:
```Python
router.include_router(other_router)
```
-请确保在你将 `router` 包含到 `FastAPI` 应用程序之前进行此操作,以便 `other_router` 中的`路径操作`也能被包含进来。
+Make sure you do it before including `router` in the `FastAPI` app, so that the *path operations* from `other_router` are also included.
From 833551e7721fbbb861dc919ab2f21b4ce7eddd09 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:23 +0800
Subject: [PATCH 062/163] New translations body-fields.md (Chinese Simplified)
---
docs/zh/docs/tutorial/body-fields.md | 119 +++++++++++++++++++++------
1 file changed, 93 insertions(+), 26 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-fields.md b/docs/zh/docs/tutorial/body-fields.md
index 053cae71c7c6f..36039020923ba 100644
--- a/docs/zh/docs/tutorial/body-fields.md
+++ b/docs/zh/docs/tutorial/body-fields.md
@@ -1,48 +1,115 @@
-# 请求体 - 字段
+# Body - Fields
-与使用 `Query`、`Path` 和 `Body` 在*路径操作函数*中声明额外的校验和元数据的方式相同,你可以使用 Pydantic 的 `Field` 在 Pydantic 模型内部声明校验和元数据。
+The same way you can declare additional validation and metadata in *path operation function* parameters with `Query`, `Path` and `Body`, you can declare validation and metadata inside of Pydantic models using Pydantic's `Field`.
-## 导入 `Field`
+## Import `Field`
-首先,你必须导入它:
+First, you have to import it:
-```Python hl_lines="2"
-{!../../../docs_src/body_fields/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="2"
+ {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
!!! warning
- 注意,`Field` 是直接从 `pydantic` 导入的,而不是像其他的(`Query`,`Path`,`Body` 等)都从 `fastapi` 导入。
+ Notice that `Field` is imported directly from `pydantic`, not from `fastapi` as are all the rest (`Query`, `Path`, `Body`, etc).
-## 声明模型属性
+## Declare model attributes
-然后,你可以对模型属性使用 `Field`:
+You can then use `Field` with model attributes:
-```Python hl_lines="9-10"
-{!../../../docs_src/body_fields/tutorial001.py!}
-```
+=== "Python 3.10+"
-`Field` 的工作方式和 `Query`、`Path` 和 `Body` 相同,包括它们的参数等等也完全相同。
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
+ ```
-!!! note "技术细节"
- 实际上,`Query`、`Path` 和其他你将在之后看到的类,创建的是由一个共同的 `Params` 类派生的子类的对象,该共同类本身又是 Pydantic 的 `FieldInfo` 类的子类。
+=== "Python 3.9+"
- Pydantic 的 `Field` 也会返回一个 `FieldInfo` 的实例。
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
+ ```
- `Body` 也直接返回 `FieldInfo` 的一个子类的对象。还有其他一些你之后会看到的类是 `Body` 类的子类。
+=== "Python 3.6+"
- 请记住当你从 `fastapi` 导入 `Query`、`Path` 等对象时,他们实际上是返回特殊类的函数。
+ ```Python hl_lines="12-15"
+ {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9-12"
+ {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
+
+`Field` works the same way as `Query`, `Path` and `Body`, it has all the same parameters, etc.
+
+!!! note "Technical Details"
+ Actually, `Query`, `Path` and others you'll see next create objects of subclasses of a common `Param` class, which is itself a subclass of Pydantic's `FieldInfo` class.
+
+ And Pydantic's `Field` returns an instance of `FieldInfo` as well.
+
+ `Body` also returns objects of a subclass of `FieldInfo` directly. And there are others you will see later that are subclasses of the `Body` class.
+
+ Remember that when you import `Query`, `Path`, and others from `fastapi`, those are actually functions that return special classes.
!!! tip
- 注意每个模型属性如何使用类型、默认值和 `Field` 在代码结构上和*路径操作函数*的参数是相同的,区别是用 `Field` 替换`Path`、`Query` 和 `Body`。
+ Notice how each model's attribute with a type, default value and `Field` has the same structure as a *path operation function's* parameter, with `Field` instead of `Path`, `Query` and `Body`.
-## 添加额外信息
+## Add extra information
-你可以在 `Field`、`Query`、`Body` 中声明额外的信息。这些信息将包含在生成的 JSON Schema 中。
+You can declare extra information in `Field`, `Query`, `Body`, etc. And it will be included in the generated JSON Schema.
-你将在文档的后面部分学习声明示例时,了解到更多有关添加额外信息的知识。
+You will learn more about adding extra information later in the docs, when learning to declare examples.
+
+!!! warning
+ Extra keys passed to `Field` will also be present in the resulting OpenAPI schema for your application. As these keys may not necessarily be part of the OpenAPI specification, some OpenAPI tools, for example [the OpenAPI validator](https://validator.swagger.io/), may not work with your generated schema.
-## 总结
+## Recap
-你可以使用 Pydantic 的 `Field` 为模型属性声明额外的校验和元数据。
+You can use Pydantic's `Field` to declare extra validations and metadata for model attributes.
-你还可以使用额外的关键字参数来传递额外的 JSON Schema 元数据。
+You can also use the extra keyword arguments to pass additional JSON Schema metadata.
From fd156c89bdf657dca92c1ed425344b6bfdfc56e6 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:24 +0800
Subject: [PATCH 063/163] New translations body-multiple-params.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/body-multiple-params.md | 247 ++++++++++++++----
1 file changed, 193 insertions(+), 54 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-multiple-params.md b/docs/zh/docs/tutorial/body-multiple-params.md
index 34fa5b638ff1d..b214092c9b175 100644
--- a/docs/zh/docs/tutorial/body-multiple-params.md
+++ b/docs/zh/docs/tutorial/body-multiple-params.md
@@ -1,23 +1,55 @@
-# 请求体 - 多个参数
+# Body - Multiple Parameters
-既然我们已经知道了如何使用 `Path` 和 `Query`,下面让我们来了解一下请求体声明的更高级用法。
+Now that we have seen how to use `Path` and `Query`, let's see more advanced uses of request body declarations.
-## 混合使用 `Path`、`Query` 和请求体参数
+## Mix `Path`, `Query` and body parameters
-首先,毫无疑问地,你可以随意地混合使用 `Path`、`Query` 和请求体参数声明,**FastAPI** 会知道该如何处理。
+First, of course, you can mix `Path`, `Query` and request body parameter declarations freely and **FastAPI** will know what to do.
-你还可以通过将默认值设置为 `None` 来将请求体参数声明为可选参数:
+And you can also declare body parameters as optional, by setting the default to `None`:
-```Python hl_lines="17-19"
-{!../../../docs_src/body_multiple_params/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="18-20"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-20"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="17-19"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001.py!}
+ ```
!!! note
- 请注意,在这种情况下,将从请求体获取的 `item` 是可选的。因为它的默认值为 `None`。
+ Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value.
-## 多个请求体参数
+## Multiple body parameters
-在上面的示例中,*路径操作*将期望一个具有 `Item` 的属性的 JSON 请求体,就像:
+In the previous example, the *path operations* would expect a JSON body with the attributes of an `Item`, like:
```JSON
{
@@ -28,15 +60,23 @@
}
```
-但是你也可以声明多个请求体参数,例如 `item` 和 `user`:
+But you can also declare multiple body parameters, e.g. `item` and `user`:
-```Python hl_lines="20"
-{!../../../docs_src/body_multiple_params/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
+ ```
-在这种情况下,**FastAPI** 将注意到该函数中有多个请求体参数(两个 Pydantic 模型参数)。
+=== "Python 3.6+"
-因此,它将使用参数名称作为请求体中的键(字段名称),并期望一个类似于以下内容的请求体:
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
+ ```
+
+In this case, **FastAPI** will notice that there are more than one body parameters in the function (two parameters that are Pydantic models).
+
+So, it will then use the parameter names as keys (field names) in the body, and expect a body like:
```JSON
{
@@ -54,30 +94,60 @@
```
!!! note
- 请注意,即使 `item` 的声明方式与之前相同,但现在它被期望通过 `item` 键内嵌在请求体中。
+ Notice that even though the `item` was declared the same way as before, it is now expected to be inside of the body with a key `item`.
-**FastAPI** 将自动对请求中的数据进行转换,因此 `item` 参数将接收指定的内容,`user` 参数也是如此。
+**FastAPI** will do the automatic conversion from the request, so that the parameter `item` receives it's specific content and the same for `user`.
-它将执行对复合数据的校验,并且像现在这样为 OpenAPI 模式和自动化文档对其进行记录。
+It will perform the validation of the compound data, and will document it like that for the OpenAPI schema and automatic docs.
-## 请求体中的单一值
+## Singular values in body
-与使用 `Query` 和 `Path` 为查询参数和路径参数定义额外数据的方式相同,**FastAPI** 提供了一个同等的 `Body`。
+The same way there is a `Query` and `Path` to define extra data for query and path parameters, **FastAPI** provides an equivalent `Body`.
-例如,为了扩展先前的模型,你可能决定除了 `item` 和 `user` 之外,还想在同一请求体中具有另一个键 `importance`。
+For example, extending the previous model, you could decide that you want to have another key `importance` in the same body, besides the `item` and `user`.
-如果你就按原样声明它,因为它是一个单一值,**FastAPI** 将假定它是一个查询参数。
+If you declare it as is, because it is a singular value, **FastAPI** will assume that it is a query parameter.
-但是你可以使用 `Body` 指示 **FastAPI** 将其作为请求体的另一个键进行处理。
+But you can instruct **FastAPI** to treat it as another body key using `Body`:
+=== "Python 3.10+"
-```Python hl_lines="22"
-{!../../../docs_src/body_multiple_params/tutorial003.py!}
-```
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
+ ```
-在这种情况下,**FastAPI** 将期望像这样的请求体:
+=== "Python 3.10+ non-Annotated"
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial003.py!}
+ ```
+
+In this case, **FastAPI** will expect a body like:
```JSON
{
@@ -95,47 +165,116 @@
}
```
-同样的,它将转换数据类型,校验,生成文档等。
+Again, it will convert the data types, validate, document, etc.
-## 多个请求体参数和查询参数
+## Multiple body params and query
-当然,除了请求体参数外,你还可以在任何需要的时候声明额外的查询参数。
+Of course, you can also declare additional query parameters whenever you need, additional to any body parameters.
-由于默认情况下单一值被解释为查询参数,因此你不必显式地添加 `Query`,你可以仅执行以下操作:
+As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
```Python
-q: str = None
+q: Union[str, None] = None
```
-比如:
+Or in Python 3.10 and above:
-```Python hl_lines="25"
-{!../../../docs_src/body_multiple_params/tutorial004.py!}
+```Python
+q: str | None = None
```
-!!! info
- `Body` 同样具有与 `Query`、`Path` 以及其他后面将看到的类完全相同的额外校验和元数据参数。
+For example:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="28"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004.py!}
+ ```
+!!! info
+ `Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later.
-## 嵌入单个请求体参数
+## Embed a single body parameter
-假设你只有一个来自 Pydantic 模型 `Item` 的请求体参数 `item`。
+Let's say you only have a single `item` body parameter from a Pydantic model `Item`.
-默认情况下,**FastAPI** 将直接期望这样的请求体。
+By default, **FastAPI** will then expect its body directly.
-但是,如果你希望它期望一个拥有 `item` 键并在值中包含模型内容的 JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的 `Body` 参数 `embed`:
+But if you want it to expect a JSON with a key `item` and inside of it the model contents, as it does when you declare extra body parameters, you can use the special `Body` parameter `embed`:
```Python
item: Item = Body(embed=True)
```
-比如:
+as in:
-```Python hl_lines="15"
-{!../../../docs_src/body_multiple_params/tutorial005.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005.py!}
+ ```
-在这种情况下,**FastAPI** 将期望像这样的请求体:
+In this case **FastAPI** will expect a body like:
```JSON hl_lines="2"
{
@@ -148,7 +287,7 @@ item: Item = Body(embed=True)
}
```
-而不是:
+instead of:
```JSON
{
@@ -159,12 +298,12 @@ item: Item = Body(embed=True)
}
```
-## 总结
+## Recap
-你可以添加多个请求体参数到*路径操作函数*中,即使一个请求只能有一个请求体。
+You can add multiple body parameters to your *path operation function*, even though a request can only have a single body.
-但是 **FastAPI** 会处理它,在函数中为你提供正确的数据,并在*路径操作*中校验并记录正确的模式。
+But **FastAPI** will handle it, give you the correct data in your function, and validate and document the correct schema in the *path operation*.
-你还可以声明将作为请求体的一部分所接收的单一值。
+You can also declare singular values to be received as part of the body.
-你还可以指示 **FastAPI** 在仅声明了一个请求体参数的情况下,将原本的请求体嵌入到一个键中。
+And you can instruct **FastAPI** to embed the body in a key even when there is only a single parameter declared.
From 04ccb7b9d1cf9eb9ed9e8ea42f60fa90c7cca8d4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:25 +0800
Subject: [PATCH 064/163] New translations body-nested-models.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/body-nested-models.md | 356 ++++++++++++++------
1 file changed, 247 insertions(+), 109 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md
index 7649ee6feafed..7adfd8c03d396 100644
--- a/docs/zh/docs/tutorial/body-nested-models.md
+++ b/docs/zh/docs/tutorial/body-nested-models.md
@@ -1,35 +1,53 @@
-# 请求体 - 嵌套模型
+# Body - Nested Models
-使用 **FastAPI**,你可以定义、校验、记录文档并使用任意深度嵌套的模型(归功于Pydantic)。
+With **FastAPI**, you can define, validate, document, and use arbitrarily deeply nested models (thanks to Pydantic).
-## List 字段
+## List fields
-你可以将一个属性定义为拥有子元素的类型。例如 Python `list`:
+You can define an attribute to be a subtype. For example, a Python `list`:
-```Python hl_lines="12"
-{!../../../docs_src/body_nested_models/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial001.py!}
+ ```
-这将使 `tags` 成为一个由元素组成的列表。不过它没有声明每个元素的类型。
+This will make `tags` be a list, although it doesn't declare the type of the elements of the list.
-## 具有子类型的 List 字段
+## List fields with type parameter
-但是 Python 有一种特定的方法来声明具有子类型的列表:
+But Python has a specific way to declare lists with internal types, or "type parameters":
-### 从 typing 导入 `List`
+### Import typing's `List`
-首先,从 Python 的标准库 `typing` 模块中导入 `List`:
+In Python 3.9 and above you can use the standard `list` to declare these type annotations as we'll see below. 💡
+
+But in Python versions before 3.9 (3.6 and above), you first need to import `List` from standard Python's `typing` module:
```Python hl_lines="1"
-{!../../../docs_src/body_nested_models/tutorial002.py!}
+{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
-### 声明具有子类型的 List
+### Declare a `list` with a type parameter
+
+To declare types that have type parameters (internal types), like `list`, `dict`, `tuple`:
+
+* If you are in a Python version lower than 3.9, import their equivalent version from the `typing` module
+* Pass the internal type(s) as "type parameters" using square brackets: `[` and `]`
+
+In Python 3.9 it would be:
-要声明具有子类型的类型,例如 `list`、`dict`、`tuple`:
+```Python
+my_list: list[str]
+```
-* 从 `typing` 模块导入它们
-* 使用方括号 `[` 和 `]` 将子类型作为「类型参数」传入
+In versions of Python before 3.9, it would be:
```Python
from typing import List
@@ -37,61 +55,117 @@ from typing import List
my_list: List[str]
```
-这完全是用于类型声明的标准 Python 语法。
+That's all standard Python syntax for type declarations.
-对具有子类型的模型属性也使用相同的标准语法。
+Use that same standard syntax for model attributes with internal types.
-因此,在我们的示例中,我们可以将 `tags` 明确地指定为一个「字符串列表」:
+So, in our example, we can make `tags` be specifically a "list of strings":
-```Python hl_lines="14"
-{!../../../docs_src/body_nested_models/tutorial002.py!}
-```
+=== "Python 3.10+"
-## Set 类型
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
+ ```
-但是随后我们考虑了一下,意识到标签不应该重复,它们很大可能会是唯一的字符串。
+=== "Python 3.9+"
-Python 具有一种特殊的数据类型来保存一组唯一的元素,即 `set`。
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
+ ```
-然后我们可以导入 `Set` 并将 `tag` 声明为一个由 `str` 组成的 `set`:
+=== "Python 3.6+"
-```Python hl_lines="1 14"
-{!../../../docs_src/body_nested_models/tutorial003.py!}
-```
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial002.py!}
+ ```
-这样,即使你收到带有重复数据的请求,这些数据也会被转换为一组唯一项。
+## Set types
-而且,每当你输出该数据时,即使源数据有重复,它们也将作为一组唯一项输出。
+But then we think about it, and realize that tags shouldn't repeat, they would probably be unique strings.
-并且还会被相应地标注 / 记录文档。
+And Python has a special data type for sets of unique items, the `set`.
-## 嵌套模型
+Then we can declare `tags` as a set of strings:
-Pydantic 模型的每个属性都具有类型。
+=== "Python 3.10+"
-但是这个类型本身可以是另一个 Pydantic 模型。
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
+ ```
-因此,你可以声明拥有特定属性名称、类型和校验的深度嵌套的 JSON 对象。
+=== "Python 3.9+"
-上述这些都可以任意的嵌套。
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
+ ```
-### 定义子模型
+=== "Python 3.6+"
-例如,我们可以定义一个 `Image` 模型:
+ ```Python hl_lines="1 14"
+ {!> ../../../docs_src/body_nested_models/tutorial003.py!}
+ ```
-```Python hl_lines="9 10 11"
-{!../../../docs_src/body_nested_models/tutorial004.py!}
-```
+With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
-### 将子模型用作类型
+And whenever you output that data, even if the source had duplicates, it will be output as a set of unique items.
-然后我们可以将其用作一个属性的类型:
+And it will be annotated / documented accordingly too.
-```Python hl_lines="20"
-{!../../../docs_src/body_nested_models/tutorial004.py!}
-```
+## Nested Models
+
+Each attribute of a Pydantic model has a type.
+
+But that type can itself be another Pydantic model.
+
+So, you can declare deeply nested JSON "objects" with specific attribute names, types and validations.
+
+All that, arbitrarily nested.
+
+### Define a submodel
+
+For example, we can define an `Image` model:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7-9"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```
+
+### Use the submodel as a type
+
+And then we can use it as the type of an attribute:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.9+"
-这意味着 **FastAPI** 将期望类似于以下内容的请求体:
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```
+
+This would mean that **FastAPI** would expect a body similar to:
```JSON
{
@@ -107,36 +181,64 @@ Pydantic 模型的每个属性都具有类型。
}
```
-再一次,仅仅进行这样的声明,你将通过 **FastAPI** 获得:
+Again, doing just that declaration, with **FastAPI** you get:
-* 对被嵌入的模型也适用的编辑器支持(自动补全等)
-* 数据转换
-* 数据校验
-* 自动生成文档
+* Editor support (completion, etc), even for nested models
+* Data conversion
+* Data validation
+* Automatic documentation
-## 特殊的类型和校验
+## Special types and validation
-除了普通的单一值类型(如 `str`、`int`、`float` 等)外,你还可以使用从 `str` 继承的更复杂的单一值类型。
+Apart from normal singular types like `str`, `int`, `float`, etc. You can use more complex singular types that inherit from `str`.
-要了解所有的可用选项,请查看关于 来自 Pydantic 的外部类型 的文档。你将在下一章节中看到一些示例。
+To see all the options you have, checkout the docs for Pydantic's exotic types. You will see some examples in the next chapter.
-例如,在 `Image` 模型中我们有一个 `url` 字段,我们可以把它声明为 Pydantic 的 `HttpUrl`,而不是 `str`:
+For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `HttpUrl`:
-```Python hl_lines="4 10"
-{!../../../docs_src/body_nested_models/tutorial005.py!}
-```
+=== "Python 3.10+"
-该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。
+ ```Python hl_lines="2 8"
+ {!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
+ ```
-## 带有一组子模型的属性
+=== "Python 3.9+"
-你还可以将 Pydantic 模型用作 `list`、`set` 等的子类型:
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
+ ```
-```Python hl_lines="20"
-{!../../../docs_src/body_nested_models/tutorial006.py!}
-```
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/body_nested_models/tutorial005.py!}
+ ```
+
+The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
+
+## Attributes with lists of submodels
-这将期望(转换,校验,记录文档等)下面这样的 JSON 请求体:
+You can also use Pydantic models as subtypes of `list`, `set`, etc:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial006.py!}
+ ```
+
+This will expect (convert, validate, document, etc) a JSON body like:
```JSON hl_lines="11"
{
@@ -163,82 +265,118 @@ Pydantic 模型的每个属性都具有类型。
```
!!! info
- 请注意 `images` 键现在具有一组 image 对象是如何发生的。
+ Notice how the `images` key now has a list of image objects.
-## 深度嵌套模型
+## Deeply nested models
-你可以定义任意深度的嵌套模型:
+You can define arbitrarily deeply nested models:
-```Python hl_lines="9 14 20 23 27"
-{!../../../docs_src/body_nested_models/tutorial007.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 12 18 21 25"
+ {!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9 14 20 23 27"
+ {!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 14 20 23 27"
+ {!> ../../../docs_src/body_nested_models/tutorial007.py!}
+ ```
!!! info
- 请注意 `Offer` 拥有一组 `Item` 而反过来 `Item` 又是一个可选的 `Image` 列表是如何发生的。
+ Notice how `Offer` has a list of `Item`s, which in turn have an optional list of `Image`s
-## 纯列表请求体
+## Bodies of pure lists
-如果你期望的 JSON 请求体的最外层是一个 JSON `array`(即 Python `list`),则可以在路径操作函数的参数中声明此类型,就像声明 Pydantic 模型一样:
+If the top level value of the JSON body you expect is a JSON `array` (a Python `list`), you can declare the type in the parameter of the function, the same as in Pydantic models:
```Python
images: List[Image]
```
-例如:
+or in Python 3.9 and above:
-```Python hl_lines="15"
-{!../../../docs_src/body_nested_models/tutorial008.py!}
+```Python
+images: list[Image]
```
-## 无处不在的编辑器支持
+as in:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
+ ```
-你可以随处获得编辑器支持。
+=== "Python 3.6+"
-即使是列表中的元素:
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/body_nested_models/tutorial008.py!}
+ ```
-
+## Editor support everywhere
-如果你直接使用 `dict` 而不是 Pydantic 模型,那你将无法获得这种编辑器支持。
+And you get editor support everywhere.
-但是你根本不必担心这两者,传入的字典会自动被转换,你的输出也会自动被转换为 JSON。
+Even for items inside of lists:
-## 任意 `dict` 构成的请求体
+
-你也可以将请求体声明为使用某类型的键和其他类型值的 `dict`。
+You couldn't get this kind of editor support if you were working directly with `dict` instead of Pydantic models.
-无需事先知道有效的字段/属性(在使用 Pydantic 模型的场景)名称是什么。
+But you don't have to worry about them either, incoming dicts are converted automatically and your output is converted automatically to JSON too.
-如果你想接收一些尚且未知的键,这将很有用。
+## Bodies of arbitrary `dict`s
+
+You can also declare a body as a `dict` with keys of some type and values of other type.
+
+Without having to know beforehand what are the valid field/attribute names (as would be the case with Pydantic models).
+
+This would be useful if you want to receive keys that you don't already know.
---
-其他有用的场景是当你想要接收其他类型的键时,例如 `int`。
+Other useful case is when you want to have keys of other type, e.g. `int`.
-这也是我们在接下来将看到的。
+That's what we are going to see here.
-在下面的例子中,你将接受任意键为 `int` 类型并且值为 `float` 类型的 `dict`:
+In this case, you would accept any `dict` as long as it has `int` keys with `float` values:
-```Python hl_lines="15"
-{!../../../docs_src/body_nested_models/tutorial009.py!}
-```
+=== "Python 3.9+"
-!!! tip
- 请记住 JSON 仅支持将 `str` 作为键。
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
+ ```
+
+=== "Python 3.6+"
- 但是 Pydantic 具有自动转换数据的功能。
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/body_nested_models/tutorial009.py!}
+ ```
- 这意味着,即使你的 API 客户端只能将字符串作为键发送,只要这些字符串内容仅包含整数,Pydantic 就会对其进行转换并校验。
+!!! tip
+ Have in mind that JSON only supports `str` as keys.
- 然后你接收的名为 `weights` 的 `dict` 实际上将具有 `int` 类型的键和 `float` 类型的值。
+ But Pydantic has automatic data conversion.
+
+ This means that, even though your API clients can only send strings as keys, as long as those strings contain pure integers, Pydantic will convert them and validate them.
+
+ And the `dict` you receive as `weights` will actually have `int` keys and `float` values.
-## 总结
+## Recap
-使用 **FastAPI** 你可以拥有 Pydantic 模型提供的极高灵活性,同时保持代码的简单、简短和优雅。
+With **FastAPI** you have the maximum flexibility provided by Pydantic models, while keeping your code simple, short and elegant.
-而且还具有下列好处:
+But with all the benefits:
-* 编辑器支持(处处皆可自动补全!)
-* 数据转换(也被称为解析/序列化)
-* 数据校验
-* 模式文档
-* 自动生成的文档
+* Editor support (completion everywhere!)
+* Data conversion (a.k.a. parsing / serialization)
+* Data validation
+* Schema documentation
+* Automatic docs
From 19941983ca0656d07c6a1ead25108532126d7d6e Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:26 +0800
Subject: [PATCH 065/163] New translations body-updates.md (Chinese Simplified)
---
docs/zh/docs/tutorial/body-updates.md | 166 +++++++++++++++++---------
1 file changed, 110 insertions(+), 56 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-updates.md b/docs/zh/docs/tutorial/body-updates.md
index 43f20f8fcbd9c..1c1dfea522e7d 100644
--- a/docs/zh/docs/tutorial/body-updates.md
+++ b/docs/zh/docs/tutorial/body-updates.md
@@ -1,20 +1,34 @@
-# 请求体 - 更新数据
+# Body - Updates
-## 用 `PUT` 更新数据
+## Update replacing with `PUT`
-更新数据请用 HTTP `PUT` 操作。
+To update an item you can use the HTTP `PUT` operation.
-把输入数据转换为以 JSON 格式存储的数据(比如,使用 NoSQL 数据库时),可以使用 `jsonable_encoder`。例如,把 `datetime` 转换为 `str`。
+You can use the `jsonable_encoder` to convert the input data to data that can be stored as JSON (e.g. with a NoSQL database). For example, converting `datetime` to `str`.
-```Python hl_lines="30-35"
-{!../../../docs_src/body_updates/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="28-33"
+ {!> ../../../docs_src/body_updates/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="30-35"
+ {!> ../../../docs_src/body_updates/tutorial001_py39.py!}
+ ```
+
+=== "Python 3.6+"
-`PUT` 用于接收替换现有数据的数据。
+ ```Python hl_lines="30-35"
+ {!> ../../../docs_src/body_updates/tutorial001.py!}
+ ```
-### 关于更新数据的警告
+`PUT` is used to receive data that should replace the existing data.
-用 `PUT` 把数据项 `bar` 更新为以下内容时:
+### Warning about replacing
+
+That means that if you want to update the item `bar` using `PUT` with a body containing:
```Python
{
@@ -24,78 +38,118 @@
}
```
-因为上述数据未包含已存储的属性 `"tax": 20.2`,新的输入模型会把 `"tax": 10.5` 作为默认值。
+because it doesn't include the already stored attribute `"tax": 20.2`, the input model would take the default value of `"tax": 10.5`.
-因此,本次操作把 `tax` 的值「更新」为 `10.5`。
+And the data would be saved with that "new" `tax` of `10.5`.
-## 用 `PATCH` 进行部分更新
+## Partial updates with `PATCH`
-HTTP `PATCH` 操作用于更新 *部分* 数据。
+You can also use the HTTP `PATCH` operation to *partially* update data.
-即,只发送要更新的数据,其余数据保持不变。
+This means that you can send only the data that you want to update, leaving the rest intact.
-!!! Note "笔记"
+!!! Note
+ `PATCH` is less commonly used and known than `PUT`.
- `PATCH` 没有 `PUT` 知名,也怎么不常用。
+ And many teams use only `PUT`, even for partial updates.
+
+ You are **free** to use them however you want, **FastAPI** doesn't impose any restrictions.
+
+ But this guide shows you, more or less, how they are intended to be used.
- 很多人甚至只用 `PUT` 实现部分更新。
+### Using Pydantic's `exclude_unset` parameter
- **FastAPI** 对此没有任何限制,可以**随意**互换使用这两种操作。
+If you want to receive partial updates, it's very useful to use the parameter `exclude_unset` in Pydantic's model's `.dict()`.
- 但本指南也会分别介绍这两种操作各自的用途。
+Like `item.dict(exclude_unset=True)`.
-### 使用 Pydantic 的 `exclude_unset` 参数
+That would generate a `dict` with only the data that was set when creating the `item` model, excluding default values.
-更新部分数据时,可以在 Pydantic 模型的 `.dict()` 中使用 `exclude_unset` 参数。
+Then you can use this to generate a `dict` with only the data that was set (sent in the request), omitting default values:
-比如,`item.dict(exclude_unset=True)`。
+=== "Python 3.10+"
-这段代码生成的 `dict` 只包含创建 `item` 模型时显式设置的数据,而不包括默认值。
+ ```Python hl_lines="32"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```
-然后再用它生成一个只含已设置(在请求中所发送)数据,且省略了默认值的 `dict`:
+=== "Python 3.9+"
-```Python hl_lines="34"
-{!../../../docs_src/body_updates/tutorial002.py!}
-```
+ ```Python hl_lines="34"
+ {!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+ ```
-### 使用 Pydantic 的 `update` 参数
+=== "Python 3.6+"
-接下来,用 `.copy()` 为已有模型创建调用 `update` 参数的副本,该参数为包含更新数据的 `dict`。
+ ```Python hl_lines="34"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```
-例如,`stored_item_model.copy(update=update_data)`:
+### Using Pydantic's `update` parameter
-```Python hl_lines="35"
-{!../../../docs_src/body_updates/tutorial002.py!}
-```
+Now, you can create a copy of the existing model using `.copy()`, and pass the `update` parameter with a `dict` containing the data to update.
-### 更新部分数据小结
+Like `stored_item_model.copy(update=update_data)`:
-简而言之,更新部分数据应:
+=== "Python 3.10+"
-* 使用 `PATCH` 而不是 `PUT` (可选,也可以用 `PUT`);
-* 提取存储的数据;
-* 把数据放入 Pydantic 模型;
-* 生成不含输入模型默认值的 `dict` (使用 `exclude_unset` 参数);
- * 只更新用户设置过的值,不用模型中的默认值覆盖已存储过的值。
-* 为已存储的模型创建副本,用接收的数据更新其属性 (使用 `update` 参数)。
-* 把模型副本转换为可存入数据库的形式(比如,使用 `jsonable_encoder`)。
- * 这种方式与 Pydantic 模型的 `.dict()` 方法类似,但能确保把值转换为适配 JSON 的数据类型,例如, 把 `datetime` 转换为 `str` 。
-* 把数据保存至数据库;
-* 返回更新后的模型。
+ ```Python hl_lines="33"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```
-```Python hl_lines="30-37"
-{!../../../docs_src/body_updates/tutorial002.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="35"
+ {!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="35"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```
+
+### Partial updates recap
+
+In summary, to apply partial updates you would:
+
+* (Optionally) use `PATCH` instead of `PUT`.
+* Retrieve the stored data.
+* Put that data in a Pydantic model.
+* Generate a `dict` without default values from the input model (using `exclude_unset`).
+ * This way you can update only the values actually set by the user, instead of overriding values already stored with default values in your model.
+* Create a copy of the stored model, updating it's attributes with the received partial updates (using the `update` parameter).
+* Convert the copied model to something that can be stored in your DB (for example, using the `jsonable_encoder`).
+ * This is comparable to using the model's `.dict()` method again, but it makes sure (and converts) the values to data types that can be converted to JSON, for example, `datetime` to `str`.
+* Save the data to your DB.
+* Return the updated model.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="28-35"
+ {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="30-37"
+ {!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+ ```
-!!! tip "提示"
+=== "Python 3.6+"
- 实际上,HTTP `PUT` 也可以完成相同的操作。
- 但本节以 `PATCH` 为例的原因是,该操作就是为了这种用例创建的。
+ ```Python hl_lines="30-37"
+ {!> ../../../docs_src/body_updates/tutorial002.py!}
+ ```
-!!! note "笔记"
+!!! tip
+ You can actually use this same technique with an HTTP `PUT` operation.
- 注意,输入模型仍需验证。
+ But the example here uses `PATCH` because it was created for these use cases.
- 因此,如果希望接收的部分更新数据可以省略其他所有属性,则要把模型中所有的属性标记为可选(使用默认值或 `None`)。
+!!! note
+ Notice that the input model is still validated.
- 为了区分用于**更新**所有可选值的模型与用于**创建**包含必选值的模型,请参照[更多模型](extra-models.md){.internal-link target=_blank} 一节中的思路。
+ So, if you want to receive partial updates that can omit all the attributes, you need to have a model with all the attributes marked as optional (with default values or `None`).
+
+ To distinguish from the models with all optional values for **updates** and models with required values for **creation**, you can use the ideas described in [Extra Models](extra-models.md){.internal-link target=_blank}.
From fb1fa4a4fb94249ccc919619735623c3d927e0d7 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:27 +0800
Subject: [PATCH 066/163] New translations body.md (Chinese Simplified)
---
docs/zh/docs/tutorial/body.md | 218 ++++++++++++++++++++++------------
1 file changed, 142 insertions(+), 76 deletions(-)
diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md
index f80ab5bf59069..9462df2c65f86 100644
--- a/docs/zh/docs/tutorial/body.md
+++ b/docs/zh/docs/tutorial/body.md
@@ -1,39 +1,57 @@
-# 请求体
+# Request Body
-当你需要将数据从客户端(例如浏览器)发送给 API 时,你将其作为「请求体」发送。
+When you need to send data from a client (let's say, a browser) to your API, you send it as a **request body**.
-**请求**体是客户端发送给 API 的数据。**响应**体是 API 发送给客户端的数据。
+A **request** body is data sent by the client to your API. A **response** body is the data your API sends to the client.
-你的 API 几乎总是要发送**响应**体。但是客户端并不总是需要发送**请求**体。
+Your API almost always has to send a **response** body. But clients don't necessarily need to send **request** bodies all the time.
-我们使用 Pydantic 模型来声明**请求**体,并能够获得它们所具有的所有能力和优点。
+To declare a **request** body, you use Pydantic models with all their power and benefits.
!!! info
- 你不能使用 `GET` 操作(HTTP 方法)发送请求体。
+ To send data, you should use one of: `POST` (the more common), `PUT`, `DELETE` or `PATCH`.
- 要发送数据,你必须使用下列方法之一:`POST`(较常见)、`PUT`、`DELETE` 或 `PATCH`。
+ Sending a body with a `GET` request has an undefined behavior in the specifications, nevertheless, it is supported by FastAPI, only for very complex/extreme use cases.
+
+ As it is discouraged, the interactive docs with Swagger UI won't show the documentation for the body when using `GET`, and proxies in the middle might not support it.
-## 导入 Pydantic 的 `BaseModel`
+## Import Pydantic's `BaseModel`
-首先,你需要从 `pydantic` 中导入 `BaseModel`:
+First, you need to import `BaseModel` from `pydantic`:
-```Python hl_lines="2"
-{!../../../docs_src/body/tutorial001.py!}
-```
+=== "Python 3.10+"
-## 创建数据模型
+ ```Python hl_lines="2"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
-然后,将你的数据模型声明为继承自 `BaseModel` 的类。
+=== "Python 3.6+"
-使用标准的 Python 类型来声明所有属性:
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
-```Python hl_lines="5-9"
-{!../../../docs_src/body/tutorial001.py!}
-```
+## Create your data model
+
+Then you declare your data model as a class that inherits from `BaseModel`.
+
+Use standard Python types for all the attributes:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="5-9"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="7-11"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
-和声明查询参数时一样,当一个模型属性具有默认值时,它不是必需的。否则它是一个必需属性。将默认值设为 `None` 可使其成为可选属性。
+The same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. Use `None` to make it just optional.
-例如,上面的模型声明了一个这样的 JSON「`object`」(或 Python `dict`):
+For example, this model above declares a JSON "`object`" (or Python `dict`) like:
```JSON
{
@@ -44,7 +62,7 @@
}
```
-...由于 `description` 和 `tax` 是可选的(它们的默认值为 `None`),下面的 JSON「`object`」也将是有效的:
+...as `description` and `tax` are optional (with a default value of `None`), this JSON "`object`" would also be valid:
```JSON
{
@@ -53,95 +71,143 @@
}
```
-## 声明为参数
+## Declare it as a parameter
-使用与声明路径和查询参数的相同方式声明请求体,即可将其添加到「路径操作」中:
+To add it to your *path operation*, declare it the same way you declared path and query parameters:
-```Python hl_lines="16"
-{!../../../docs_src/body/tutorial001.py!}
-```
+=== "Python 3.10+"
-...并且将它的类型声明为你创建的 `Item` 模型。
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
-## 结果
+=== "Python 3.6+"
-仅仅使用了 Python 类型声明,**FastAPI** 将会:
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
-* 将请求体作为 JSON 读取。
-* 转换为相应的类型(在需要时)。
-* 校验数据。
- * 如果数据无效,将返回一条清晰易读的错误信息,指出不正确数据的确切位置和内容。
-* 将接收的数据赋值到参数 `item` 中。
- * 由于你已经在函数中将它声明为 `Item` 类型,你还将获得对于所有属性及其类型的一切编辑器支持(代码补全等)。
-* 为你的模型生成 JSON 模式 定义,你还可以在其他任何对你的项目有意义的地方使用它们。
-* 这些模式将成为生成的 OpenAPI 模式的一部分,并且被自动化文档 UI 所使用。
+...and declare its type as the model you created, `Item`.
-## 自动化文档
+## Results
-你所定义模型的 JSON 模式将成为生成的 OpenAPI 模式的一部分,并且在交互式 API 文档中展示:
+With just that Python type declaration, **FastAPI** will:
-
+* Read the body of the request as JSON.
+* Convert the corresponding types (if needed).
+* Validate the data.
+ * If the data is invalid, it will return a nice and clear error, indicating exactly where and what was the incorrect data.
+* Give you the received data in the parameter `item`.
+ * As you declared it in the function to be of type `Item`, you will also have all the editor support (completion, etc) for all of the attributes and their types.
+* Generate JSON Schema definitions for your model, you can also use them anywhere else you like if it makes sense for your project.
+* Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentation UIs.
-而且还将在每一个需要它们的*路径操作*的 API 文档中使用:
+## Automatic docs
-
+The JSON Schemas of your models will be part of your OpenAPI generated schema, and will be shown in the interactive API docs:
-## 编辑器支持
+
-在你的编辑器中,你会在函数内部的任意地方得到类型提示和代码补全(如果你接收的是一个 `dict` 而不是 Pydantic 模型,则不会发生这种情况):
+And will be also used in the API docs inside each *path operation* that needs them:
-
+
-你还会获得对不正确的类型操作的错误检查:
+## Editor support
-
+In your editor, inside your function you will get type hints and completion everywhere (this wouldn't happen if you received a `dict` instead of a Pydantic model):
-这并非偶然,整个框架都是围绕该设计而构建。
+
-并且在进行任何实现之前,已经在设计阶段经过了全面测试,以确保它可以在所有的编辑器中生效。
+You also get error checks for incorrect type operations:
-Pydantic 本身甚至也进行了一些更改以支持此功能。
+
-上面的截图取自 Visual Studio Code。
+This is not by chance, the whole framework was built around that design.
-但是在 PyCharm 和绝大多数其他 Python 编辑器中你也会获得同样的编辑器支持:
+And it was thoroughly tested at the design phase, before any implementation, to ensure it would work with all the editors.
-
+There were even some changes to Pydantic itself to support this.
-## 使用模型
+The previous screenshots were taken with Visual Studio Code.
-在函数内部,你可以直接访问模型对象的所有属性:
+But you would get the same editor support with PyCharm and most of the other Python editors:
-```Python hl_lines="19"
-{!../../../docs_src/body/tutorial002.py!}
-```
+
-## 请求体 + 路径参数
+!!! tip
+ If you use PyCharm as your editor, you can use the Pydantic PyCharm Plugin.
-你可以同时声明路径参数和请求体。
+ It improves editor support for Pydantic models, with:
-**FastAPI** 将识别出与路径参数匹配的函数参数应**从路径中获取**,而声明为 Pydantic 模型的函数参数应**从请求体中获取**。
+ * auto-completion
+ * type checks
+ * refactoring
+ * searching
+ * inspections
-```Python hl_lines="15-16"
-{!../../../docs_src/body/tutorial003.py!}
-```
+## Use the model
-## 请求体 + 路径参数 + 查询参数
+Inside of the function, you can access all the attributes of the model object directly:
-你还可以同时声明**请求体**、**路径参数**和**查询参数**。
+=== "Python 3.10+"
-**FastAPI** 会识别它们中的每一个,并从正确的位置获取数据。
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/body/tutorial002_py310.py!}
+ ```
-```Python hl_lines="16"
-{!../../../docs_src/body/tutorial004.py!}
-```
+=== "Python 3.6+"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/body/tutorial002.py!}
+ ```
+
+## Request body + path parameters
+
+You can declare path parameters and request body at the same time.
+
+**FastAPI** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared to be Pydantic models should be **taken from the request body**.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="15-16"
+ {!> ../../../docs_src/body/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/body/tutorial003.py!}
+ ```
+
+## Request body + path + query parameters
+
+You can also declare **body**, **path** and **query** parameters, all at the same time.
+
+**FastAPI** will recognize each of them and take the data from the correct place.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/body/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial004.py!}
+ ```
+
+The function parameters will be recognized as follows:
+
+* If the parameter is also declared in the **path**, it will be used as a path parameter.
+* If the parameter is of a **singular type** (like `int`, `float`, `str`, `bool`, etc) it will be interpreted as a **query** parameter.
+* If the parameter is declared to be of the type of a **Pydantic model**, it will be interpreted as a request **body**.
-函数参数将依次按如下规则进行识别:
+!!! note
+ FastAPI will know that the value of `q` is not required because of the default value `= None`.
-* 如果在**路径**中也声明了该参数,它将被用作路径参数。
-* 如果参数属于**单一类型**(比如 `int`、`float`、`str`、`bool` 等)它将被解释为**查询**参数。
-* 如果参数的类型被声明为一个 **Pydantic 模型**,它将被解释为**请求体**。
+ The `Union` in `Union[str, None]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
-## 不使用 Pydantic
+## Without Pydantic
-如果你不想使用 Pydantic 模型,你还可以使用 **Body** 参数。请参阅文档 [请求体 - 多个参数:请求体中的单一值](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}。
+If you don't want to use Pydantic models, you can also use **Body** parameters. See the docs for [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
From a6c192d8dfc72afab606d747a1693ba731d58f8f Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:28 +0800
Subject: [PATCH 067/163] New translations cookie-params.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/cookie-params.md | 101 ++++++++++++++++++++-----
1 file changed, 82 insertions(+), 19 deletions(-)
diff --git a/docs/zh/docs/tutorial/cookie-params.md b/docs/zh/docs/tutorial/cookie-params.md
index d67daf0f9051e..111e93458e686 100644
--- a/docs/zh/docs/tutorial/cookie-params.md
+++ b/docs/zh/docs/tutorial/cookie-params.md
@@ -1,34 +1,97 @@
-# Cookie 参数
+# Cookie Parameters
-你可以像定义 `Query` 参数和 `Path` 参数一样来定义 `Cookie` 参数。
+You can define Cookie parameters the same way you define `Query` and `Path` parameters.
-## 导入 `Cookie`
+## Import `Cookie`
-首先,导入 `Cookie`:
+First import `Cookie`:
-```Python hl_lines="3"
-{!../../../docs_src/cookie_params/tutorial001.py!}
-```
+=== "Python 3.10+"
-## 声明 `Cookie` 参数
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
+ ```
-声明 `Cookie` 参数的结构与声明 `Query` 参数和 `Path` 参数时相同。
+=== "Python 3.9+"
-第一个值是参数的默认值,同时也可以传递所有验证参数或注释参数,来校验参数:
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
+ ```
+=== "Python 3.6+"
-```Python hl_lines="9"
-{!../../../docs_src/cookie_params/tutorial001.py!}
-```
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an.py!}
+ ```
-!!! note "技术细节"
- `Cookie` 、`Path` 、`Query`是兄弟类,它们都继承自公共的 `Param` 类
+=== "Python 3.10+ non-Annotated"
- 但请记住,当你从 `fastapi` 导入的 `Query`、`Path`、`Cookie` 或其他参数声明函数,这些实际上是返回特殊类的函数。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
+## Declare `Cookie` parameters
+
+Then declare the cookie parameters using the same structure as with `Path` and `Query`.
+
+The first value is the default value, you can pass all the extra validation or annotation parameters:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/cookie_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
+
+!!! note "Technical Details"
+ `Cookie` is a "sister" class of `Path` and `Query`. It also inherits from the same common `Param` class.
+
+ But remember that when you import `Query`, `Path`, `Cookie` and others from `fastapi`, those are actually functions that return special classes.
!!! info
- 你需要使用 `Cookie` 来声明 cookie 参数,否则参数将会被解释为查询参数。
+ To declare cookies, you need to use `Cookie`, because otherwise the parameters would be interpreted as query parameters.
-## 总结
+## Recap
-使用 `Cookie` 声明 cookie 参数,使用方式与 `Query` 和 `Path` 类似。
+Declare cookies with `Cookie`, using the same common pattern as `Query` and `Path`.
From ff6a7e191ae0bc55509ff956ff916e8c83d23a04 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:29 +0800
Subject: [PATCH 068/163] New translations cors.md (Chinese Simplified)
---
docs/zh/docs/tutorial/cors.md | 88 +++++++++++++++++------------------
1 file changed, 44 insertions(+), 44 deletions(-)
diff --git a/docs/zh/docs/tutorial/cors.md b/docs/zh/docs/tutorial/cors.md
index ddd4e76825366..33b11983b32b5 100644
--- a/docs/zh/docs/tutorial/cors.md
+++ b/docs/zh/docs/tutorial/cors.md
@@ -1,84 +1,84 @@
-# CORS(跨域资源共享)
+# CORS (Cross-Origin Resource Sharing)
-CORS 或者「跨域资源共享」 指浏览器中运行的前端拥有与后端通信的 JavaScript 代码,而后端处于与前端不同的「源」的情况。
+CORS or "Cross-Origin Resource Sharing" refers to the situations when a frontend running in a browser has JavaScript code that communicates with a backend, and the backend is in a different "origin" than the frontend.
-## 源
+## Origin
-源是协议(`http`,`https`)、域(`myapp.com`,`localhost`,`localhost.tiangolo.com`)以及端口(`80`、`443`、`8080`)的组合。
+An origin is the combination of protocol (`http`, `https`), domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`), and port (`80`, `443`, `8080`).
-因此,这些都是不同的源:
+So, all these are different origins:
* `http://localhost`
* `https://localhost`
* `http://localhost:8080`
-即使它们都在 `localhost` 中,但是它们使用不同的协议或者端口,所以它们都是不同的「源」。
+Even if they are all in `localhost`, they use different protocols or ports, so, they are different "origins".
-## 步骤
+## Steps
-假设你的浏览器中有一个前端运行在 `http://localhost:8080`,并且它的 JavaScript 正在尝试与运行在 `http://localhost` 的后端通信(因为我们没有指定端口,浏览器会采用默认的端口 `80`)。
+So, let's say you have a frontend running in your browser at `http://localhost:8080`, and its JavaScript is trying to communicate with a backend running at `http://localhost` (because we don't specify a port, the browser will assume the default port `80`).
-然后,浏览器会向后端发送一个 HTTP `OPTIONS` 请求,如果后端发送适当的 headers 来授权来自这个不同源(`http://localhost:8080`)的通信,浏览器将允许前端的 JavaScript 向后端发送请求。
+Then, the browser will send an HTTP `OPTIONS` request to the backend, and if the backend sends the appropriate headers authorizing the communication from this different origin (`http://localhost:8080`) then the browser will let the JavaScript in the frontend send its request to the backend.
-为此,后端必须有一个「允许的源」列表。
+To achieve this, the backend must have a list of "allowed origins".
-在这种情况下,它必须包含 `http://localhost:8080`,前端才能正常工作。
+In this case, it would have to include `http://localhost:8080` for the frontend to work correctly.
-## 通配符
+## Wildcards
-也可以使用 `"*"`(一个「通配符」)声明这个列表,表示全部都是允许的。
+It's also possible to declare the list as `"*"` (a "wildcard") to say that all are allowed.
-但这仅允许某些类型的通信,不包括所有涉及凭据的内容:像 Cookies 以及那些使用 Bearer 令牌的授权 headers 等。
+But that will only allow certain types of communication, excluding everything that involves credentials: Cookies, Authorization headers like those used with Bearer Tokens, etc.
-因此,为了一切都能正常工作,最好显式地指定允许的源。
+So, for everything to work correctly, it's better to specify explicitly the allowed origins.
-## 使用 `CORSMiddleware`
+## Use `CORSMiddleware`
-你可以在 **FastAPI** 应用中使用 `CORSMiddleware` 来配置它。
+You can configure it in your **FastAPI** application using the `CORSMiddleware`.
-* 导入 `CORSMiddleware`。
-* 创建一个允许的源列表(由字符串组成)。
-* 将其作为「中间件」添加到你的 **FastAPI** 应用中。
+* Import `CORSMiddleware`.
+* Create a list of allowed origins (as strings).
+* Add it as a "middleware" to your **FastAPI** application.
-你也可以指定后端是否允许:
+You can also specify if your backend allows:
-* 凭证(授权 headers,Cookies 等)。
-* 特定的 HTTP 方法(`POST`,`PUT`)或者使用通配符 `"*"` 允许所有方法。
-* 特定的 HTTP headers 或者使用通配符 `"*"` 允许所有 headers。
+* Credentials (Authorization headers, Cookies, etc).
+* Specific HTTP methods (`POST`, `PUT`) or all of them with the wildcard `"*"`.
+* Specific HTTP headers or all of them with the wildcard `"*"`.
```Python hl_lines="2 6-11 13-19"
{!../../../docs_src/cors/tutorial001.py!}
```
-默认情况下,这个 `CORSMiddleware` 实现所使用的默认参数较为保守,所以你需要显式地启用特定的源、方法或者 headers,以便浏览器能够在跨域上下文中使用它们。
+The default parameters used by the `CORSMiddleware` implementation are restrictive by default, so you'll need to explicitly enable particular origins, methods, or headers, in order for browsers to be permitted to use them in a Cross-Domain context.
-支持以下参数:
+The following arguments are supported:
-* `allow_origins` - 一个允许跨域请求的源列表。例如 `['https://example.org', 'https://www.example.org']`。你可以使用 `['*']` 允许任何源。
-* `allow_origin_regex` - 一个正则表达式字符串,匹配的源允许跨域请求。例如 `'https://.*\.example\.org'`。
-* `allow_methods` - 一个允许跨域请求的 HTTP 方法列表。默认为 `['GET']`。你可以使用 `['*']` 来允许所有标准方法。
-* `allow_headers` - 一个允许跨域请求的 HTTP 请求头列表。默认为 `[]`。你可以使用 `['*']` 允许所有的请求头。`Accept`、`Accept-Language`、`Content-Language` 以及 `Content-Type` 请求头总是允许 CORS 请求。
-* `allow_credentials` - 指示跨域请求支持 cookies。默认是 `False`。另外,允许凭证时 `allow_origins` 不能设定为 `['*']`,必须指定源。
-* `expose_headers` - 指示可以被浏览器访问的响应头。默认为 `[]`。
-* `max_age` - 设定浏览器缓存 CORS 响应的最长时间,单位是秒。默认为 `600`。
+* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. E.g. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
+* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`.
+* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
+* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for simple CORS requests.
+* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified.
+* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
+* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.
-中间件响应两种特定类型的 HTTP 请求……
+The middleware responds to two particular types of HTTP request...
-### CORS 预检请求
+### CORS preflight requests
-这是些带有 `Origin` 和 `Access-Control-Request-Method` 请求头的 `OPTIONS` 请求。
+These are any `OPTIONS` request with `Origin` and `Access-Control-Request-Method` headers.
-在这种情况下,中间件将拦截传入的请求并进行响应,出于提供信息的目的返回一个使用了适当的 CORS headers 的 `200` 或 `400` 响应。
+In this case the middleware will intercept the incoming request and respond with appropriate CORS headers, and either a `200` or `400` response for informational purposes.
-### 简单请求
+### Simple requests
-任何带有 `Origin` 请求头的请求。在这种情况下,中间件将像平常一样传递请求,但是在响应中包含适当的 CORS headers。
+Any request with an `Origin` header. In this case the middleware will pass the request through as normal, but will include appropriate CORS headers on the response.
-## 更多信息
+## More info
-更多关于 CORS 的信息,请查看 Mozilla CORS 文档。
+For more info about CORS, check the Mozilla CORS documentation.
-!!! note "技术细节"
- 你也可以使用 `from starlette.middleware.cors import CORSMiddleware`。
+!!! note "Technical Details"
+ You could also use `from starlette.middleware.cors import CORSMiddleware`.
- 出于方便,**FastAPI** 在 `fastapi.middleware` 中为开发者提供了几个中间件。但是大多数可用的中间件都是直接来自 Starlette。
+ **FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette.
From fdbb610d63746b87f31cfb48b224973566062f55 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:30 +0800
Subject: [PATCH 069/163] New translations debugging.md (Chinese Simplified)
---
docs/zh/docs/tutorial/debugging.md | 74 ++++++++++++++++--------------
1 file changed, 39 insertions(+), 35 deletions(-)
diff --git a/docs/zh/docs/tutorial/debugging.md b/docs/zh/docs/tutorial/debugging.md
index 51801d4984b9e..8d76347cffcba 100644
--- a/docs/zh/docs/tutorial/debugging.md
+++ b/docs/zh/docs/tutorial/debugging.md
@@ -1,18 +1,18 @@
-# 调试
+# Debugging
-你可以在编辑器中连接调试器,例如使用 Visual Studio Code 或 PyCharm。
+You can connect the debugger in your editor, for example with Visual Studio Code or PyCharm.
-## 调用 `uvicorn`
+## Call `uvicorn`
-在你的 FastAPI 应用中直接导入 `uvicorn` 并运行:
+In your FastAPI application, import and run `uvicorn` directly:
```Python hl_lines="1 15"
{!../../../docs_src/debugging/tutorial001.py!}
```
-### 关于 `__name__ == "__main__"`
+### About `__name__ == "__main__"`
-`__name__ == "__main__"` 的主要目的是使用以下代码调用文件时执行一些代码:
+The main purpose of the `__name__ == "__main__"` is to have some code that is executed when your file is called with:
+
---
-如果使用 Pycharm,你可以:
+If you use Pycharm, you can:
-* 打开「运行」菜单。
-* 选中「调试...」。
-* 然后出现一个上下文菜单。
-* 选择要调试的文件(本例中的 `main.py`)。
+* Open the "Run" menu.
+* Select the option "Debug...".
+* Then a context menu shows up.
+* Select the file to debug (in this case, `main.py`).
-然后它会使用你的 **FastAPI** 代码开启服务器,停在断点处,等等。
+It will then start the server with your **FastAPI** code, stop at your breakpoints, etc.
-看起来可能是这样:
+Here's how it might look:
-
+
From 8c6d11dcb0c1a8e481d5e43ecc42ad172feafa0c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:31 +0800
Subject: [PATCH 070/163] New translations classes-as-dependencies.md (Chinese
Simplified)
---
.../dependencies/classes-as-dependencies.md | 406 ++++++++++++++----
1 file changed, 320 insertions(+), 86 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
index f404820df0119..a1409c8f88701 100644
--- a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
+++ b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -1,58 +1,82 @@
-# 类作为依赖项
+# Classes as Dependencies
-在深入探究 **依赖注入** 系统之前,让我们升级之前的例子。
+Before diving deeper into the **Dependency Injection** system, let's upgrade the previous example.
-## 来自前一个例子的`dict`
+## A `dict` from the previous example
-在前面的例子中, 我们从依赖项 ("可依赖对象") 中返回了一个 `dict`:
+In the previous example, we were returning a `dict` from our dependency ("dependable"):
=== "Python 3.10+"
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
- ```Python hl_lines="9"
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
-但是后面我们在路径操作函数的参数 `commons` 中得到了一个 `dict`。
+But then we get a `dict` in the parameter `commons` of the *path operation function*.
-我们知道编辑器不能为 `dict` 提供很多支持(比如补全),因为编辑器不知道 `dict` 的键和值类型。
+And we know that editors can't provide a lot of support (like completion) for `dict`s, because they can't know their keys and value types.
-对此,我们可以做的更好...
+We can do better...
-## 什么构成了依赖项?
+## What makes a dependency
-到目前为止,您看到的依赖项都被声明为函数。
+Up to now you have seen dependencies declared as functions.
-但这并不是声明依赖项的唯一方法(尽管它可能是更常见的方法)。
+But that's not the only way to declare dependencies (although it would probably be the more common).
-关键因素是依赖项应该是 "可调用对象"。
+The key factor is that a dependency should be a "callable".
-Python 中的 "**可调用对象**" 是指任何 Python 可以像函数一样 "调用" 的对象。
+A "**callable**" in Python is anything that Python can "call" like a function.
-所以,如果你有一个对象 `something` (可能*不是*一个函数),你可以 "调用" 它(执行它),就像:
+So, if you have an object `something` (that might _not_ be a function) and you can "call" it (execute it) like:
```Python
something()
```
-或者
+or
```Python
something(some_argument, some_keyword_argument="foo")
```
-这就是 "可调用对象"。
+then it is a "callable".
-## 类作为依赖项
+## Classes as dependencies
-您可能会注意到,要创建一个 Python 类的实例,您可以使用相同的语法。
+You might notice that to create an instance of a Python class, you use that same syntax.
-举个例子:
+For example:
```Python
class Cat:
@@ -63,185 +87,395 @@ class Cat:
fluffy = Cat(name="Mr Fluffy")
```
-在这个例子中, `fluffy` 是一个 `Cat` 类的实例。
+In this case, `fluffy` is an instance of the class `Cat`.
-为了创建 `fluffy`,你调用了 `Cat` 。
+And to create `fluffy`, you are "calling" `Cat`.
-所以,Python 类也是 **可调用对象**。
+So, a Python class is also a **callable**.
-因此,在 **FastAPI** 中,你可以使用一个 Python 类作为一个依赖项。
+Then, in **FastAPI**, you could use a Python class as a dependency.
-实际上 FastAPI 检查的是它是一个 "可调用对象"(函数,类或其他任何类型)以及定义的参数。
+What FastAPI actually checks is that it is a "callable" (function, class or anything else) and the parameters defined.
-如果您在 **FastAPI** 中传递一个 "可调用对象" 作为依赖项,它将分析该 "可调用对象" 的参数,并以处理路径操作函数的参数的方式来处理它们。包括子依赖项。
+If you pass a "callable" as a dependency in **FastAPI**, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a *path operation function*. Including sub-dependencies.
-这也适用于完全没有参数的可调用对象。这与不带参数的路径操作函数一样。
+That also applies to callables with no parameters at all. The same as it would be for *path operation functions* with no parameters.
-所以,我们可以将上面的依赖项 "可依赖对象" `common_parameters` 更改为类 `CommonQueryParams`:
+Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParams`:
=== "Python 3.10+"
+ ```Python hl_lines="11-15"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11-15"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12-16"
+ {!> ../../../docs_src/dependencies/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="9-13"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-注意用于创建类实例的 `__init__` 方法:
+Pay attention to the `__init__` method used to create the instance of the class:
=== "Python 3.10+"
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-...它与我们以前的 `common_parameters` 具有相同的参数:
+...it has the same parameters as our previous `common_parameters`:
=== "Python 3.10+"
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
-这些参数就是 **FastAPI** 用来 "处理" 依赖项的。
+Those parameters are what **FastAPI** will use to "solve" the dependency.
-在两个例子下,都有:
+In both cases, it will have:
-* 一个可选的 `q` 查询参数,是 `str` 类型。
-* 一个 `skip` 查询参数,是 `int` 类型,默认值为 `0`。
-* 一个 `limit` 查询参数,是 `int` 类型,默认值为 `100`。
+* An optional `q` query parameter that is a `str`.
+* A `skip` query parameter that is an `int`, with a default of `0`.
+* A `limit` query parameter that is an `int`, with a default of `100`.
-在两个例子下,数据都将被转换、验证、在 OpenAPI schema 上文档化,等等。
+In both cases the data will be converted, validated, documented on the OpenAPI schema, etc.
-## 使用它
+## Use it
-现在,您可以使用这个类来声明你的依赖项了。
+Now you can declare your dependency using this class.
=== "Python 3.10+"
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/dependencies/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-**FastAPI** 调用 `CommonQueryParams` 类。这将创建该类的一个 "实例",该实例将作为参数 `commons` 被传递给你的函数。
+**FastAPI** calls the `CommonQueryParams` class. This creates an "instance" of that class and the instance will be passed as the parameter `commons` to your function.
-## 类型注解 vs `Depends`
+## Type annotation vs `Depends`
-注意,我们在上面的代码中编写了两次`CommonQueryParams`:
+Notice how we write `CommonQueryParams` twice in the above code:
-```Python
-commons: CommonQueryParams = Depends(CommonQueryParams)
-```
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams = Depends(CommonQueryParams)
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
+ ```
-最后的 `CommonQueryParams`:
+The last `CommonQueryParams`, in:
```Python
-... = Depends(CommonQueryParams)
+... Depends(CommonQueryParams)
```
-...实际上是 **Fastapi** 用来知道依赖项是什么的。
+...is what **FastAPI** will actually use to know what is the dependency.
-FastAPI 将从依赖项中提取声明的参数,这才是 FastAPI 实际调用的。
+From it is that FastAPI will extract the declared parameters and that is what FastAPI will actually call.
---
-在本例中,第一个 `CommonQueryParams` :
+In this case, the first `CommonQueryParams`, in:
-```Python
-commons: CommonQueryParams ...
-```
+=== "Python 3.6+"
-...对于 **FastAPI** 没有任何特殊的意义。FastAPI 不会使用它进行数据转换、验证等 (因为对于这,它使用 `= Depends(CommonQueryParams)`)。
+ ```Python
+ commons: Annotated[CommonQueryParams, ...
+ ```
-你实际上可以只这样编写:
+=== "Python 3.6+ non-Annotated"
-```Python
-commons = Depends(CommonQueryParams)
-```
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams ...
+ ```
+
+...doesn't have any special meaning for **FastAPI**. FastAPI won't use it for data conversion, validation, etc. (as it is using the `Depends(CommonQueryParams)` for that).
+
+You could actually write just:
+
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[Any, Depends(CommonQueryParams)]
+ ```
+
+=== "Python 3.6+ non-Annotated"
-..就像:
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons = Depends(CommonQueryParams)
+ ```
+
+..as in:
=== "Python 3.10+"
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/dependencies/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003.py!}
```
-但是声明类型是被鼓励的,因为那样你的编辑器就会知道将传递什么作为参数 `commons` ,然后它可以帮助你完成代码,类型检查,等等:
+But declaring the type is encouraged as that way your editor will know what will be passed as the parameter `commons`, and then it can help you with code completion, type checks, etc:
-
+
-## 快捷方式
+## Shortcut
-但是您可以看到,我们在这里有一些代码重复了,编写了`CommonQueryParams`两次:
+But you see that we are having some code repetition here, writing `CommonQueryParams` twice:
-```Python
-commons: CommonQueryParams = Depends(CommonQueryParams)
-```
+=== "Python 3.6+ non-Annotated"
-**FastAPI** 为这些情况提供了一个快捷方式,在这些情况下,依赖项 *明确地* 是一个类,**FastAPI** 将 "调用" 它来创建类本身的一个实例。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-对于这些特定的情况,您可以跟随以下操作:
+ ```Python
+ commons: CommonQueryParams = Depends(CommonQueryParams)
+ ```
-不是写成这样:
+=== "Python 3.6+"
-```Python
-commons: CommonQueryParams = Depends(CommonQueryParams)
-```
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
+ ```
-...而是这样写:
+**FastAPI** provides a shortcut for these cases, in where the dependency is *specifically* a class that **FastAPI** will "call" to create an instance of the class itself.
-```Python
-commons: CommonQueryParams = Depends()
-```
+For those specific cases, you can do the following:
+
+Instead of writing:
+
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams = Depends(CommonQueryParams)
+ ```
+
+...you write:
+
+=== "Python 3.6+"
+
+ ```Python
+ commons: Annotated[CommonQueryParams, Depends()]
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python
+ commons: CommonQueryParams = Depends()
+ ```
-您声明依赖项作为参数的类型,并使用 `Depends()` 作为该函数的参数的 "默认" 值(在 `=` 之后),而在 `Depends()` 中没有任何参数,而不是在 `Depends(CommonQueryParams)` 编写完整的类。
+You declare the dependency as the type of the parameter, and you use `Depends()` without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
-同样的例子看起来像这样:
+The same example would then look like:
=== "Python 3.10+"
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial004_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/dependencies/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004.py!}
```
-... **FastAPI** 会知道怎么处理。
+...and **FastAPI** will know what to do.
!!! tip
- 如果这看起来更加混乱而不是更加有帮助,那么请忽略它,你不*需要*它。
+ If that seems more confusing than helpful, disregard it, you don't *need* it.
- 这只是一个快捷方式。因为 **FastAPI** 关心的是帮助您减少代码重复。
+ It is just a shortcut. Because **FastAPI** cares about helping you minimize code repetition.
From fcc5ba1f2385fed8ab44c671099947e380169e9d Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:31 +0800
Subject: [PATCH 071/163] New translations
dependencies-in-path-operation-decorators.md (Chinese Simplified)
---
...pendencies-in-path-operation-decorators.md | 148 +++++++++++++-----
1 file changed, 107 insertions(+), 41 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
index 61ea371e5453e..00a90424934af 100644
--- a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
+++ b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
@@ -1,73 +1,139 @@
-# 路径操作装饰器依赖项
+# Dependencies in path operation decorators
-有时,我们并不需要在*路径操作函数*中使用依赖项的返回值。
+In some cases you don't really need the return value of a dependency inside your *path operation function*.
-或者说,有些依赖项不返回值。
+Or the dependency doesn't return a value.
-但仍要执行或解析该依赖项。
+But you still need it to be executed/solved.
-对于这种情况,不必在声明*路径操作函数*的参数时使用 `Depends`,而是可以在*路径操作装饰器*中添加一个由 `dependencies` 组成的 `list`。
+For those cases, instead of declaring a *path operation function* parameter with `Depends`, you can add a `list` of `dependencies` to the *path operation decorator*.
-## 在*路径操作装饰器*中添加 `dependencies` 参数
+## Add `dependencies` to the *path operation decorator*
-*路径操作装饰器*支持可选参数 ~ `dependencies`。
+The *path operation decorator* receives an optional argument `dependencies`.
-该参数的值是由 `Depends()` 组成的 `list`:
+It should be a `list` of `Depends()`:
-```Python hl_lines="17"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+=== "Python 3.9+"
-路径操作装饰器依赖项(以下简称为**“路径装饰器依赖项”**)的执行或解析方式和普通依赖项一样,但就算这些依赖项会返回值,它们的值也不会传递给*路径操作函数*。
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
-!!! tip "提示"
+=== "Python 3.6+"
- 有些编辑器会检查代码中没使用过的函数参数,并显示错误提示。
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
- 在*路径操作装饰器*中使用 `dependencies` 参数,可以确保在执行依赖项的同时,避免编辑器显示错误提示。
+=== "Python 3.6 non-Annotated"
- 使用路径装饰器依赖项还可以避免开发新人误会代码中包含无用的未使用参数。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-!!! info "说明"
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
- 本例中,使用的是自定义响应头 `X-Key` 和 `X-Token`。
+These dependencies will be executed/solved the same way normal dependencies. But their value (if they return any) won't be passed to your *path operation function*.
- 但实际开发中,尤其是在实现安全措施时,最好使用 FastAPI 内置的[安全工具](../security/index.md){.internal-link target=_blank}(详见下一章)。
+!!! tip
+ Some editors check for unused function parameters, and show them as errors.
-## 依赖项错误和返回值
+ Using these `dependencies` in the *path operation decorator* you can make sure they are executed while avoiding editor/tooling errors.
+
+ It might also help avoid confusion for new developers that see an unused parameter in your code and could think it's unnecessary.
-路径装饰器依赖项也可以使用普通的依赖项*函数*。
+!!! info
+ In this example we use invented custom headers `X-Key` and `X-Token`.
-### 依赖项的需求项
+ But in real cases, when implementing security, you would get more benefits from using the integrated [Security utilities (the next chapter)](../security/index.md){.internal-link target=_blank}.
-路径装饰器依赖项可以声明请求的需求项(比如响应头)或其他子依赖项:
+## Dependencies errors and return values
-```Python hl_lines="6 11"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+You can use the same dependency *functions* you use normally.
-### 触发异常
+### Dependency requirements
-路径装饰器依赖项与正常的依赖项一样,可以 `raise` 异常:
+They can declare request requirements (like headers) or other sub-dependencies:
-```Python hl_lines="8 13"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+=== "Python 3.9+"
-### 返回值
+ ```Python hl_lines="8 13"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
-无论路径装饰器依赖项是否返回值,路径操作都不会使用这些值。
+=== "Python 3.6+"
-因此,可以复用在其他位置使用过的、(能返回值的)普通依赖项,即使没有使用这个值,也会执行该依赖项:
+ ```Python hl_lines="7 12"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
-```Python hl_lines="9 14"
-{!../../../docs_src/dependencies/tutorial006.py!}
-```
+=== "Python 3.6 non-Annotated"
-## 为一组路径操作定义依赖项
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md){.internal-link target=\_blank}一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,您将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。
+ ```Python hl_lines="6 11"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
-## 全局依赖项
+### Raise exceptions
-接下来,我们将学习如何为 `FastAPI` 应用程序添加全局依赖项,创建应用于每个*路径操作*的依赖项。
+These dependencies can `raise` exceptions, the same as normal dependencies:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 14"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8 13"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
+
+### Return values
+
+And they can return values or not, the values won't be used.
+
+So, you can re-use a normal dependency (that returns a value) you already use somewhere else, and even though the value won't be used, the dependency will be executed:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11 16"
+ {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9 14"
+ {!> ../../../docs_src/dependencies/tutorial006.py!}
+ ```
+
+## Dependencies for a group of *path operations*
+
+Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
+
+## Global Dependencies
+
+Next we will see how to add dependencies to the whole `FastAPI` application, so that they apply to each *path operation*.
From 61fb1f63e74892f10cdd4192beb7b5676cde6748 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:32 +0800
Subject: [PATCH 072/163] New translations dependencies-with-yield.md (Chinese
Simplified)
---
.../dependencies/dependencies-with-yield.md | 252 ++++++++++++++++++
1 file changed, 252 insertions(+)
create mode 100644 docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md
diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md
new file mode 100644
index 0000000000000..c0883364aff4c
--- /dev/null
+++ b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md
@@ -0,0 +1,252 @@
+# Dependencies with yield
+
+FastAPI supports dependencies that do some extra steps after finishing.
+
+To do this, use `yield` instead of `return`, and write the extra steps after.
+
+!!! tip
+ Make sure to use `yield` one single time.
+
+!!! note "Technical Details"
+ Any function that is valid to use with:
+
+ * `@contextlib.contextmanager` or
+ * `@contextlib.asynccontextmanager`
+
+ would be valid to use as a **FastAPI** dependency.
+
+ In fact, FastAPI uses those two decorators internally.
+
+## A database dependency with `yield`
+
+For example, you could use this to create a database session and close it after finishing.
+
+Only the code prior to and including the `yield` statement is executed before sending a response:
+
+```Python hl_lines="2-4"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+The yielded value is what is injected into *path operations* and other dependencies:
+
+```Python hl_lines="4"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+The code following the `yield` statement is executed after the response has been delivered:
+
+```Python hl_lines="5-6"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+!!! tip
+ You can use `async` or normal functions.
+
+ **FastAPI** will do the right thing with each, the same as with normal dependencies.
+
+## A dependency with `yield` and `try`
+
+If you use a `try` block in a dependency with `yield`, you'll receive any exception that was thrown when using the dependency.
+
+For example, if some code at some point in the middle, in another dependency or in a *path operation*, made a database transaction "rollback" or create any other error, you will receive the exception in your dependency.
+
+So, you can look for that specific exception inside the dependency with `except SomeException`.
+
+In the same way, you can use `finally` to make sure the exit steps are executed, no matter if there was an exception or not.
+
+```Python hl_lines="3 5"
+{!../../../docs_src/dependencies/tutorial007.py!}
+```
+
+## Sub-dependencies with `yield`
+
+You can have sub-dependencies and "trees" of sub-dependencies of any size and shape, and any or all of them can use `yield`.
+
+**FastAPI** will make sure that the "exit code" in each dependency with `yield` is run in the correct order.
+
+For example, `dependency_c` can have a dependency on `dependency_b`, and `dependency_b` on `dependency_a`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="6 14 22"
+ {!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="5 13 21"
+ {!> ../../../docs_src/dependencies/tutorial008_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4 12 20"
+ {!> ../../../docs_src/dependencies/tutorial008.py!}
+ ```
+
+And all of them can use `yield`.
+
+In this case `dependency_c`, to execute its exit code, needs the value from `dependency_b` (here named `dep_b`) to still be available.
+
+And, in turn, `dependency_b` needs the value from `dependency_a` (here named `dep_a`) to be available for its exit code.
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-19 26-27"
+ {!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="17-18 25-26"
+ {!> ../../../docs_src/dependencies/tutorial008_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="16-17 24-25"
+ {!> ../../../docs_src/dependencies/tutorial008.py!}
+ ```
+
+The same way, you could have dependencies with `yield` and `return` mixed.
+
+And you could have a single dependency that requires several other dependencies with `yield`, etc.
+
+You can have any combinations of dependencies that you want.
+
+**FastAPI** will make sure everything is run in the correct order.
+
+!!! note "Technical Details"
+ This works thanks to Python's Context Managers.
+
+ **FastAPI** uses them internally to achieve this.
+
+## Dependencies with `yield` and `HTTPException`
+
+You saw that you can use dependencies with `yield` and have `try` blocks that catch exceptions.
+
+It might be tempting to raise an `HTTPException` or similar in the exit code, after the `yield`. But **it won't work**.
+
+The exit code in dependencies with `yield` is executed *after* the response is sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} will have already run. There's nothing catching exceptions thrown by your dependencies in the exit code (after the `yield`).
+
+So, if you raise an `HTTPException` after the `yield`, the default (or any custom) exception handler that catches `HTTPException`s and returns an HTTP 400 response won't be there to catch that exception anymore.
+
+This is what allows anything set in the dependency (e.g. a DB session) to, for example, be used by background tasks.
+
+Background tasks are run *after* the response has been sent. So there's no way to raise an `HTTPException` because there's not even a way to change the response that is *already sent*.
+
+But if a background task creates a DB error, at least you can rollback or cleanly close the session in the dependency with `yield`, and maybe log the error or report it to a remote tracking system.
+
+If you have some code that you know could raise an exception, do the most normal/"Pythonic" thing and add a `try` block in that section of the code.
+
+If you have custom exceptions that you would like to handle *before* returning the response and possibly modifying the response, maybe even raising an `HTTPException`, create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
+
+!!! tip
+ You can still raise exceptions including `HTTPException` *before* the `yield`. But not after.
+
+The sequence of execution is more or less like this diagram. Time flows from top to bottom. And each column is one of the parts interacting or executing code.
+
+```mermaid
+sequenceDiagram
+
+participant client as Client
+participant handler as Exception handler
+participant dep as Dep with yield
+participant operation as Path Operation
+participant tasks as Background tasks
+
+ Note over client,tasks: Can raise exception for dependency, handled after response is sent
+ Note over client,operation: Can raise HTTPException and can change the response
+ client ->> dep: Start request
+ Note over dep: Run code up to yield
+ opt raise
+ dep -->> handler: Raise HTTPException
+ handler -->> client: HTTP error response
+ dep -->> dep: Raise other exception
+ end
+ dep ->> operation: Run dependency, e.g. DB session
+ opt raise
+ operation -->> dep: Raise HTTPException
+ dep -->> handler: Auto forward exception
+ handler -->> client: HTTP error response
+ operation -->> dep: Raise other exception
+ dep -->> handler: Auto forward exception
+ end
+ operation ->> client: Return response to client
+ Note over client,operation: Response is already sent, can't change it anymore
+ opt Tasks
+ operation -->> tasks: Send background tasks
+ end
+ opt Raise other exception
+ tasks -->> dep: Raise other exception
+ end
+ Note over dep: After yield
+ opt Handle other exception
+ dep -->> dep: Handle exception, can't change response. E.g. close DB session.
+ end
+```
+
+!!! info
+ Only **one response** will be sent to the client. It might be one of the error responses or it will be the response from the *path operation*.
+
+ After one of those responses is sent, no other response can be sent.
+
+!!! tip
+ This diagram shows `HTTPException`, but you could also raise any other exception for which you create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
+
+ If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`, and then **again** to the exception handlers. If there's no exception handler for that exception, it will then be handled by the default internal `ServerErrorMiddleware`, returning a 500 HTTP status code, to let the client know that there was an error in the server.
+
+## Context Managers
+
+### What are "Context Managers"
+
+"Context Managers" are any of those Python objects that you can use in a `with` statement.
+
+For example, you can use `with` to read a file:
+
+```Python
+with open("./somefile.txt") as f:
+ contents = f.read()
+ print(contents)
+```
+
+Underneath, the `open("./somefile.txt")` creates an object that is a called a "Context Manager".
+
+When the `with` block finishes, it makes sure to close the file, even if there were exceptions.
+
+When you create a dependency with `yield`, **FastAPI** will internally convert it to a context manager, and combine it with some other related tools.
+
+### Using context managers in dependencies with `yield`
+
+!!! warning
+ This is, more or less, an "advanced" idea.
+
+ If you are just starting with **FastAPI** you might want to skip it for now.
+
+In Python, you can create Context Managers by creating a class with two methods: `__enter__()` and `__exit__()`.
+
+You can also use them inside of **FastAPI** dependencies with `yield` by using `with` or `async with` statements inside of the dependency function:
+
+```Python hl_lines="1-9 13"
+{!../../../docs_src/dependencies/tutorial010.py!}
+```
+
+!!! tip
+ Another way to create a context manager is with:
+
+ * `@contextlib.contextmanager` or
+ * `@contextlib.asynccontextmanager`
+
+ using them to decorate a function with a single `yield`.
+
+ That's what **FastAPI** uses internally for dependencies with `yield`.
+
+ But you don't have to use the decorators for FastAPI dependencies (and you shouldn't).
+
+ FastAPI will do it for you internally.
From e4f0e477532a7048ee06b92105cb2167809a6d72 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:33 +0800
Subject: [PATCH 073/163] New translations global-dependencies.md (Chinese
Simplified)
---
.../dependencies/global-dependencies.md | 37 ++++++++++++++-----
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/global-dependencies.md b/docs/zh/docs/tutorial/dependencies/global-dependencies.md
index 3f7afa32cd1b3..0989b31d46205 100644
--- a/docs/zh/docs/tutorial/dependencies/global-dependencies.md
+++ b/docs/zh/docs/tutorial/dependencies/global-dependencies.md
@@ -1,17 +1,34 @@
-# 全局依赖项
+# Global Dependencies
-有时,我们要为整个应用添加依赖项。
+For some types of applications you might want to add dependencies to the whole application.
-通过与定义[*路径装饰器依赖项*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 类似的方式,可以把依赖项添加至整个 `FastAPI` 应用。
+Similar to the way you can [add `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, you can add them to the `FastAPI` application.
-这样一来,就可以为所有*路径操作*应用该依赖项:
+In that case, they will be applied to all the *path operations* in the application:
-```Python hl_lines="15"
-{!../../../docs_src/dependencies/tutorial012.py!}
-```
+=== "Python 3.9+"
-[*路径装饰器依赖项*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 一章的思路均适用于全局依赖项, 在本例中,这些依赖项可以用于应用中的所有*路径操作*。
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
+ ```
-## 为一组路径操作定义依赖项
+=== "Python 3.6+"
-稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md){.internal-link target=_blank}一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,您将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/dependencies/tutorial012_an.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/dependencies/tutorial012.py!}
+ ```
+
+And all the ideas in the section about [adding `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} still apply, but in this case, to all of the *path operations* in the app.
+
+## Dependencies for groups of *path operations*
+
+Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
From 52f653637c4b4eed8e5ed9f1cdada03422c00c51 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:34 +0800
Subject: [PATCH 074/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/tutorial/dependencies/index.md | 339 ++++++++++++++------
1 file changed, 240 insertions(+), 99 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/index.md b/docs/zh/docs/tutorial/dependencies/index.md
index 7a133061de797..a8679d1d8175a 100644
--- a/docs/zh/docs/tutorial/dependencies/index.md
+++ b/docs/zh/docs/tutorial/dependencies/index.md
@@ -1,89 +1,193 @@
-# 依赖项
+# Dependencies
-FastAPI 提供了简单易用,但功能强大的**依赖注入**系统。
+**FastAPI** has a very powerful but intuitive **Dependency Injection** system.
-这个依赖系统设计的简单易用,可以让开发人员轻松地把组件集成至 **FastAPI**。
+It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
-## 什么是「依赖注入」
+## What is "Dependency Injection"
-编程中的**「依赖注入」**是声明代码(本文中为*路径操作函数* )运行所需的,或要使用的「依赖」的一种方式。
+**"Dependency Injection"** means, in programming, that there is a way for your code (in this case, your *path operation functions*) to declare things that it requires to work and use: "dependencies".
-然后,由系统(本文中为 **FastAPI**)负责执行任意需要的逻辑,为代码提供这些依赖(「注入」依赖项)。
+And then, that system (in this case **FastAPI**) will take care of doing whatever is needed to provide your code with those needed dependencies ("inject" the dependencies).
-依赖注入常用于以下场景:
+This is very useful when you need to:
-* 共享业务逻辑(复用相同的代码逻辑)
-* 共享数据库连接
-* 实现安全、验证、角色权限
-* 等……
+* Have shared logic (the same code logic again and again).
+* Share database connections.
+* Enforce security, authentication, role requirements, etc.
+* And many other things...
-上述场景均可以使用**依赖注入**,将代码重复最小化。
+All these, while minimizing code repetition.
-## 第一步
+## First Steps
-接下来,我们学习一个非常简单的例子,尽管它过于简单,不是很实用。
+Let's see a very simple example. It will be so simple that it is not very useful, for now.
-但通过这个例子,您可以初步了解「依赖注入」的工作机制。
+But this way we can focus on how the **Dependency Injection** system works.
-### 创建依赖项
+### Create a dependency, or "dependable"
-首先,要关注的是依赖项。
+Let's first focus on the dependency.
-依赖项就是一个函数,且可以使用与*路径操作函数*相同的参数:
+It is just a function that can take all the same parameters that a *path operation function* can take:
-```Python hl_lines="8-11"
-{!../../../docs_src/dependencies/tutorial001.py!}
-```
+=== "Python 3.10+"
-大功告成。
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
-只用了**2 行**代码。
+=== "Python 3.9+"
-依赖项函数的形式和结构与*路径操作函数*一样。
+ ```Python hl_lines="8-11"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
-因此,可以把依赖项当作没有「装饰器」(即,没有 `@app.get("/some-path")` )的路径操作函数。
+=== "Python 3.6+"
-依赖项可以返回各种内容。
+ ```Python hl_lines="9-12"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
-本例中的依赖项预期接收如下参数:
+=== "Python 3.10+ non-Annotated"
-* 类型为 `str` 的可选查询参数 `q`
-* 类型为 `int` 的可选查询参数 `skip`,默认值是 `0`
-* 类型为 `int` 的可选查询参数 `limit`,默认值是 `100`
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-然后,依赖项函数返回包含这些值的 `dict`。
+ ```Python hl_lines="6-7"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
-### 导入 `Depends`
+=== "Python 3.6+ non-Annotated"
-```Python hl_lines="3"
-{!../../../docs_src/dependencies/tutorial001.py!}
-```
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-### 声明依赖项
+ ```Python hl_lines="8-11"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
-与在*路径操作函数*参数中使用 `Body`、`Query` 的方式相同,声明依赖项需要使用 `Depends` 和一个新的参数:
+That's it.
-```Python hl_lines="15 20"
-{!../../../docs_src/dependencies/tutorial001.py!}
-```
+**2 lines**.
+
+And it has the same shape and structure that all your *path operation functions* have.
+
+You can think of it as a *path operation function* without the "decorator" (without the `@app.get("/some-path")`).
+
+And it can return anything you want.
+
+In this case, this dependency expects:
+
+* An optional query parameter `q` that is a `str`.
+* An optional query parameter `skip` that is an `int`, and by default is `0`.
+* An optional query parameter `limit` that is an `int`, and by default is `100`.
+
+And then it just returns a `dict` containing those values.
+
+!!! info
+ FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0.
+
+ If you have an older version, you would get errors when trying to use `Annotated`.
+
+ Make sure you [Upgrade the FastAPI version](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
+
+### Import `Depends`
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+### Declare the dependency, in the "dependant"
+
+The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
-虽然,在路径操作函数的参数中使用 `Depends` 的方式与 `Body`、`Query` 相同,但 `Depends` 的工作方式略有不同。
+=== "Python 3.10+"
-这里只能传给 Depends 一个参数。
+ ```Python hl_lines="13 18"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ ```
-且该参数必须是可调用对象,比如函数。
+=== "Python 3.9+"
-该函数接收的参数和*路径操作函数*的参数一样。
+ ```Python hl_lines="15 20"
+ {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ ```
-!!! tip "提示"
+=== "Python 3.6+"
- 下一章介绍,除了函数还有哪些「对象」可以用作依赖项。
+ ```Python hl_lines="16 21"
+ {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ ```
-接收到新的请求时,**FastAPI** 执行如下操作:
+=== "Python 3.10+ non-Annotated"
-* 用正确的参数调用依赖项函数(「可依赖项」)
-* 获取函数返回的结果
-* 把函数返回的结果赋值给*路径操作函数*的参数
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11 16"
+ {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="15 20"
+ {!> ../../../docs_src/dependencies/tutorial001.py!}
+ ```
+
+Although you use `Depends` in the parameters of your function the same way you use `Body`, `Query`, etc, `Depends` works a bit differently.
+
+You only give `Depends` a single parameter.
+
+This parameter must be something like a function.
+
+You **don't call it** directly (don't add the parenthesis at the end), you just pass it as a parameter to `Depends()`.
+
+And that function takes parameters in the same way that *path operation functions* do.
+
+!!! tip
+ You'll see what other "things", apart from functions, can be used as dependencies in the next chapter.
+
+Whenever a new request arrives, **FastAPI** will take care of:
+
+* Calling your dependency ("dependable") function with the correct parameters.
+* Get the result from your function.
+* Assign that result to the parameter in your *path operation function*.
```mermaid
graph TB
@@ -96,91 +200,128 @@ common_parameters --> read_items
common_parameters --> read_users
```
-这样,只编写一次代码,**FastAPI** 就可以为多个*路径操作*共享这段代码 。
+This way you write shared code once and **FastAPI** takes care of calling it for your *path operations*.
+
+!!! check
+ Notice that you don't have to create a special class and pass it somewhere to **FastAPI** to "register" it or anything similar.
+
+ You just pass it to `Depends` and **FastAPI** knows how to do the rest.
+
+## Share `Annotated` dependencies
+
+In the examples above, you see that there's a tiny bit of **code duplication**.
+
+When you need to use the `common_parameters()` dependency, you have to write the whole parameter with the type annotation and `Depends()`:
+
+```Python
+commons: Annotated[dict, Depends(common_parameters)]
+```
+
+But because we are using `Annotated`, we can store that `Annotated` value in a variable and use it in multiple places:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="12 16 21"
+ {!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="14 18 23"
+ {!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="15 19 24"
+ {!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
+ ```
-!!! check "检查"
+!!! tip
+ This is just standard Python, it's called a "type alias", it's actually not specific to **FastAPI**.
- 注意,无需创建专门的类,并将之传递给 **FastAPI** 以进行「注册」或执行类似的操作。
+ But because **FastAPI** is based on the Python standards, including `Annotated`, you can use this trick in your code. 😎
- 只要把它传递给 `Depends`,**FastAPI** 就知道该如何执行后续操作。
+The dependencies will keep working as expected, and the **best part** is that the **type information will be preserved**, which means that your editor will be able to keep providing you with **autocompletion**, **inline errors**, etc. The same for other tools like `mypy`.
-## 要不要使用 `async`?
+This will be especially useful when you use it in a **large code base** where you use **the same dependencies** over and over again in ***many ***path operations******.
-**FastAPI** 调用依赖项的方式与*路径操作函数*一样,因此,定义依赖项函数,也要应用与路径操作函数相同的规则。
+## To `async` or not to `async`
-即,既可以使用异步的 `async def`,也可以使用普通的 `def` 定义依赖项。
+As dependencies will also be called by **FastAPI** (the same as your *path operation functions*), the same rules apply while defining your functions.
-在普通的 `def` *路径操作函数*中,可以声明异步的 `async def` 依赖项;也可以在异步的 `async def` *路径操作函数*中声明普通的 `def` 依赖项。
+You can use `async def` or normal `def`.
-上述这些操作都是可行的,**FastAPI** 知道该怎么处理。
+And you can declare dependencies with `async def` inside of normal `def` *path operation functions*, or `def` dependencies inside of `async def` *path operation functions*, etc.
-!!! note "笔记"
+It doesn't matter. **FastAPI** will know what to do.
- 如里不了解异步,请参阅[异步:*“着急了?”*](../../async.md){.internal-link target=_blank} 一章中 `async` 和 `await` 的内容。
+!!! note
+ If you don't know, check the [Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank} section about `async` and `await` in the docs.
-## 与 OpenAPI 集成
+## Integrated with OpenAPI
-依赖项及子依赖项的所有请求声明、验证和需求都可以集成至同一个 OpenAPI 概图。
+All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
-所以,交互文档里也会显示依赖项的所有信息:
+So, the interactive docs will have all the information from these dependencies too:
-
+
-## 简单用法
+## Simple usage
-观察一下就会发现,只要*路径* 和*操作*匹配,就可以使用声明的路径操作函数。然后,**FastAPI** 会用正确的参数调用函数,并提取请求中的数据。
+If you look at it, *path operation functions* are declared to be used whenever a *path* and *operation* matches, and then **FastAPI** takes care of calling the function with the correct parameters, extracting the data from the request.
-实际上,所有(或大多数)网络框架的工作方式都是这样的。
+Actually, all (or most) of the web frameworks work in this same way.
-开发人员永远都不需要直接调用这些函数,这些函数是由框架(在此为 **FastAPI** )调用的。
+You never call those functions directly. They are called by your framework (in this case, **FastAPI**).
-通过依赖注入系统,只要告诉 **FastAPI** *路径操作函数* 还要「依赖」其他在*路径操作函数*之前执行的内容,**FastAPI** 就会执行函数代码,并「注入」函数返回的结果。
+With the Dependency Injection system, you can also tell **FastAPI** that your *path operation function* also "depends" on something else that should be executed before your *path operation function*, and **FastAPI** will take care of executing it and "injecting" the results.
-其他与「依赖注入」概念相同的术语为:
+Other common terms for this same idea of "dependency injection" are:
-* 资源(Resource)
-* 提供方(Provider)
-* 服务(Service)
-* 可注入(Injectable)
-* 组件(Component)
+* resources
+* providers
+* services
+* injectables
+* components
-## **FastAPI** 插件
+## **FastAPI** plug-ins
-**依赖注入**系统支持构建集成和「插件」。但实际上,FastAPI 根本**不需要创建「插件」**,因为使用依赖项可以声明不限数量的、可用于*路径操作函数*的集成与交互。
+Integrations and "plug-in"s can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your *path operation functions*.
-创建依赖项非常简单、直观,并且还支持导入 Python 包。毫不夸张地说,只要几行代码就可以把需要的 Python 包与 API 函数集成在一起。
+And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, *literally*.
-下一章将详细介绍在关系型数据库、NoSQL 数据库、安全等方面使用依赖项的例子。
+You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
-## **FastAPI** 兼容性
+## **FastAPI** compatibility
-依赖注入系统如此简洁的特性,让 **FastAPI** 可以与下列系统兼容:
+The simplicity of the dependency injection system makes **FastAPI** compatible with:
-* 关系型数据库
-* NoSQL 数据库
-* 外部支持库
-* 外部 API
-* 认证和鉴权系统
-* API 使用监控系统
-* 响应数据注入系统
-* 等等……
+* all the relational databases
+* NoSQL databases
+* external packages
+* external APIs
+* authentication and authorization systems
+* API usage monitoring systems
+* response data injection systems
+* etc.
-## 简单而强大
+## Simple and Powerful
-虽然,**层级式依赖注入系统**的定义与使用十分简单,但它却非常强大。
+Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
-比如,可以定义依赖其他依赖项的依赖项。
+You can define dependencies that in turn can define dependencies themselves.
-最后,依赖项层级树构建后,**依赖注入系统**会处理所有依赖项及其子依赖项,并为每一步操作提供(注入)结果。
+In the end, a hierarchical tree of dependencies is built, and the **Dependency Injection** system takes care of solving all these dependencies for you (and their sub-dependencies) and providing (injecting) the results at each step.
-比如,下面有 4 个 API 路径操作(*端点*):
+For example, let's say you have 4 API endpoints (*path operations*):
* `/items/public/`
* `/items/private/`
* `/users/{user_id}/activate`
* `/items/pro/`
-开发人员可以使用依赖项及其子依赖项为这些路径操作添加不同的权限:
+then you could add different permission requirements for each of them just with dependencies and sub-dependencies:
```mermaid
graph TB
@@ -205,8 +346,8 @@ admin_user --> activate_user
paying_user --> pro_items
```
-## 与 **OpenAPI** 集成
+## Integrated with **OpenAPI**
-在声明需求时,所有这些依赖项还会把参数、验证等功能添加至路径操作。
+All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your *path operations*.
-**FastAPI** 负责把上述内容全部添加到 OpenAPI 概图,并显示在交互文档中。
+**FastAPI** will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.
From be1ff5b12fe35d55795bc1a02fe15aa48d89a621 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:35 +0800
Subject: [PATCH 075/163] New translations sub-dependencies.md (Chinese
Simplified)
---
.../tutorial/dependencies/sub-dependencies.md | 196 ++++++++++++++----
1 file changed, 151 insertions(+), 45 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md
index 58377bbfecd8d..b89844a1ffd66 100644
--- a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md
+++ b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md
@@ -1,51 +1,146 @@
-# 子依赖项
+# Sub-dependencies
-FastAPI 支持创建含**子依赖项**的依赖项。
+You can create dependencies that have **sub-dependencies**.
-并且,可以按需声明任意**深度**的子依赖项嵌套层级。
+They can be as **deep** as you need them to be.
-**FastAPI** 负责处理解析不同深度的子依赖项。
+**FastAPI** will take care of solving them.
-### 第一层依赖项
+## First dependency "dependable"
-下列代码创建了第一层依赖项:
+You could create a first dependency ("dependable") like:
-```Python hl_lines="8-9"
-{!../../../docs_src/dependencies/tutorial005.py!}
-```
+=== "Python 3.10+"
-这段代码声明了类型为 `str` 的可选查询参数 `q`,然后返回这个查询参数。
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
+ ```
-这个函数很简单(不过也没什么用),但却有助于让我们专注于了解子依赖项的工作方式。
+=== "Python 3.9+"
-### 第二层依赖项
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ ```
-接下来,创建另一个依赖项函数,并同时用该依赖项自身再声明一个依赖项(所以这也是一个「依赖项」):
+=== "Python 3.6+"
-```Python hl_lines="13"
-{!../../../docs_src/dependencies/tutorial005.py!}
-```
+ ```Python hl_lines="9-10"
+ {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ ```
-这里重点说明一下声明的参数:
+=== "Python 3.10 non-Annotated"
-* 尽管该函数自身是依赖项,但还声明了另一个依赖项(它「依赖」于其他对象)
- * 该函数依赖 `query_extractor`, 并把 `query_extractor` 的返回值赋给参数 `q`
-* 同时,该函数还声明了类型是 `str` 的可选 cookie(`last_query`)
- * 用户未提供查询参数 `q` 时,则使用上次使用后保存在 cookie 中的查询
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-### 使用依赖项
+ ```Python hl_lines="6-7"
+ {!> ../../../docs_src/dependencies/tutorial005_py310.py!}
+ ```
-接下来,就可以使用依赖项:
+=== "Python 3.6 non-Annotated"
-```Python hl_lines="22"
-{!../../../docs_src/dependencies/tutorial005.py!}
-```
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8-9"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
+It declares an optional query parameter `q` as a `str`, and then it just returns it.
+
+This is quite simple (not very useful), but will help us focus on how the sub-dependencies work.
+
+## Second dependency, "dependable" and "dependant"
+
+Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/dependencies/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-!!! info "信息"
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
- 注意,这里在*路径操作函数*中只声明了一个依赖项,即 `query_or_cookie_extractor` 。
+Let's focus on the parameters declared:
- 但 **FastAPI** 必须先处理 `query_extractor`,以便在调用 `query_or_cookie_extractor` 时使用 `query_extractor` 返回的结果。
+* Even though this function is a dependency ("dependable") itself, it also declares another dependency (it "depends" on something else).
+ * It depends on the `query_extractor`, and assigns the value returned by it to the parameter `q`.
+* It also declares an optional `last_query` cookie, as a `str`.
+ * If the user didn't provide any query `q`, we use the last query used, which we saved to a cookie before.
+
+## Use the dependency
+
+Then we can use the dependency with:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/dependencies/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/dependencies/tutorial005.py!}
+ ```
+
+!!! info
+ Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`.
+
+ But **FastAPI** will know that it has to solve `query_extractor` first, to pass the results of that to `query_or_cookie_extractor` while calling it.
```mermaid
graph TB
@@ -58,31 +153,42 @@ read_query["/items/"]
query_extractor --> query_or_cookie_extractor --> read_query
```
-## 多次使用同一个依赖项
+## Using the same dependency multiple times
-如果在同一个*路径操作* 多次声明了同一个依赖项,例如,多个依赖项共用一个子依赖项,**FastAPI** 在处理同一请求时,只调用一次该子依赖项。
+If one of your dependencies is declared multiple times for the same *path operation*, for example, multiple dependencies have a common sub-dependency, **FastAPI** will know to call that sub-dependency only once per request.
-FastAPI 不会为同一个请求多次调用同一个依赖项,而是把依赖项的返回值进行「缓存」,并把它传递给同一请求中所有需要使用该返回值的「依赖项」。
+And it will save the returned value in a "cache" and pass it to all the "dependants" that need it in that specific request, instead of calling the dependency multiple times for the same request.
-在高级使用场景中,如果不想使用「缓存」值,而是为需要在同一请求的每一步操作(多次)中都实际调用依赖项,可以把 `Depends` 的参数 `use_cache` 的值设置为 `False` :
+In an advanced scenario where you know you need the dependency to be called at every step (possibly multiple times) in the same request instead of using the "cached" value, you can set the parameter `use_cache=False` when using `Depends`:
-```Python hl_lines="1"
-async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
- return {"fresh_value": fresh_value}
-```
+=== "Python 3.6+"
+
+ ```Python hl_lines="1"
+ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
+ return {"fresh_value": fresh_value}
+ ```
+
+=== "Python 3.6+ non-Annotated"
-## 小结
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-千万别被本章里这些花里胡哨的词藻吓倒了,其实**依赖注入**系统非常简单。
+ ```Python hl_lines="1"
+ async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
+ return {"fresh_value": fresh_value}
+ ```
-依赖注入无非是与*路径操作函数*一样的函数罢了。
+## Recap
-但它依然非常强大,能够声明任意嵌套深度的「图」或树状的依赖结构。
+Apart from all the fancy words used here, the **Dependency Injection** system is quite simple.
-!!! tip "提示"
+Just functions that look the same as the *path operation functions*.
- 这些简单的例子现在看上去虽然没有什么实用价值,
+But still, it is very powerful, and allows you to declare arbitrarily deeply nested dependency "graphs" (trees).
- 但在**安全**一章中,您会了解到这些例子的用途,
+!!! tip
+ All this might not seem as useful with these simple examples.
- 以及这些例子所能节省的代码量。
+ But you will see how useful it is in the chapters about **security**.
+
+ And you will also see the amounts of code it will save you.
From f5f3098503738daed25d92745689ea9cf6047b22 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:36 +0800
Subject: [PATCH 076/163] New translations encoder.md (Chinese Simplified)
---
docs/zh/docs/tutorial/encoder.md | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/docs/zh/docs/tutorial/encoder.md b/docs/zh/docs/tutorial/encoder.md
index 76ed846ce35e4..735aa2209ffed 100644
--- a/docs/zh/docs/tutorial/encoder.md
+++ b/docs/zh/docs/tutorial/encoder.md
@@ -1,24 +1,24 @@
-# JSON 兼容编码器
+# JSON Compatible Encoder
-在某些情况下,您可能需要将数据类型(如Pydantic模型)转换为与JSON兼容的数据类型(如`dict`、`list`等)。
+There are some cases where you might need to convert a data type (like a Pydantic model) to something compatible with JSON (like a `dict`, `list`, etc).
-比如,如果您需要将其存储在数据库中。
+For example, if you need to store it in a database.
-对于这种要求, **FastAPI**提供了`jsonable_encoder()`函数。
+For that, **FastAPI** provides a `jsonable_encoder()` function.
-## 使用`jsonable_encoder`
+## Using the `jsonable_encoder`
-让我们假设你有一个数据库名为`fake_db`,它只能接收与JSON兼容的数据。
+Let's imagine that you have a database `fake_db` that only receives JSON compatible data.
-例如,它不接收`datetime`这类的对象,因为这些对象与JSON不兼容。
+For example, it doesn't receive `datetime` objects, as those are not compatible with JSON.
-因此,`datetime`对象必须将转换为包含ISO格式化的`str`类型对象。
+So, a `datetime` object would have to be converted to a `str` containing the data in ISO format.
-同样,这个数据库也不会接收Pydantic模型(带有属性的对象),而只接收`dict`。
+The same way, this database wouldn't receive a Pydantic model (an object with attributes), only a `dict`.
-对此你可以使用`jsonable_encoder`。
+You can use `jsonable_encoder` for that.
-它接收一个对象,比如Pydantic模型,并会返回一个JSON兼容的版本:
+It receives an object, like a Pydantic model, and returns a JSON compatible version:
=== "Python 3.10+"
@@ -32,11 +32,11 @@
{!> ../../../docs_src/encoder/tutorial001.py!}
```
-在这个例子中,它将Pydantic模型转换为`dict`,并将`datetime`转换为`str`。
+In this example, it would convert the Pydantic model to a `dict`, and the `datetime` to a `str`.
-调用它的结果后就可以使用Python标准编码中的`json.dumps()`。
+The result of calling it is something that can be encoded with the Python standard `json.dumps()`.
-这个操作不会返回一个包含JSON格式(作为字符串)数据的庞大的`str`。它将返回一个Python标准数据结构(例如`dict`),其值和子值都与JSON兼容。
+It doesn't return a large `str` containing the data in JSON format (as a string). It returns a Python standard data structure (e.g. a `dict`) with values and sub-values that are all compatible with JSON.
!!! note
- `jsonable_encoder`实际上是FastAPI内部用来转换数据的。但是它在许多其他场景中也很有用。
+ `jsonable_encoder` is actually used by **FastAPI** internally to convert data. But it is useful in many other scenarios.
From 5e77094a1c861a9fdf841b0bdaa2c8443c139abe Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:37 +0800
Subject: [PATCH 077/163] New translations extra-data-types.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/extra-data-types.md | 144 ++++++++++++++++------
1 file changed, 104 insertions(+), 40 deletions(-)
diff --git a/docs/zh/docs/tutorial/extra-data-types.md b/docs/zh/docs/tutorial/extra-data-types.md
index ac3e076545f48..7d6ffbc780cb0 100644
--- a/docs/zh/docs/tutorial/extra-data-types.md
+++ b/docs/zh/docs/tutorial/extra-data-types.md
@@ -1,66 +1,130 @@
-# 额外数据类型
+# Extra Data Types
-到目前为止,您一直在使用常见的数据类型,如:
+Up to now, you have been using common data types, like:
* `int`
* `float`
* `str`
* `bool`
-但是您也可以使用更复杂的数据类型。
+But you can also use more complex data types.
-您仍然会拥有现在已经看到的相同的特性:
+And you will still have the same features as seen up to now:
-* 很棒的编辑器支持。
-* 传入请求的数据转换。
-* 响应数据转换。
-* 数据验证。
-* 自动补全和文档。
+* Great editor support.
+* Data conversion from incoming requests.
+* Data conversion for response data.
+* Data validation.
+* Automatic annotation and documentation.
-## 其他数据类型
+## Other data types
-下面是一些你可以使用的其他数据类型:
+Here are some of the additional data types you can use:
* `UUID`:
- * 一种标准的 "通用唯一标识符" ,在许多数据库和系统中用作ID。
- * 在请求和响应中将以 `str` 表示。
+ * A standard "Universally Unique Identifier", common as an ID in many databases and systems.
+ * In requests and responses will be represented as a `str`.
* `datetime.datetime`:
- * 一个 Python `datetime.datetime`.
- * 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `2008-09-15T15:53:00+05:00`.
+ * A Python `datetime.datetime`.
+ * In requests and responses will be represented as a `str` in ISO 8601 format, like: `2008-09-15T15:53:00+05:00`.
* `datetime.date`:
* Python `datetime.date`.
- * 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `2008-09-15`.
+ * In requests and responses will be represented as a `str` in ISO 8601 format, like: `2008-09-15`.
* `datetime.time`:
- * 一个 Python `datetime.time`.
- * 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `14:23:55.003`.
+ * A Python `datetime.time`.
+ * In requests and responses will be represented as a `str` in ISO 8601 format, like: `14:23:55.003`.
* `datetime.timedelta`:
- * 一个 Python `datetime.timedelta`.
- * 在请求和响应中将表示为 `float` 代表总秒数。
- * Pydantic 也允许将其表示为 "ISO 8601 时间差异编码", 查看文档了解更多信息。
+ * A Python `datetime.timedelta`.
+ * In requests and responses will be represented as a `float` of total seconds.
+ * Pydantic also allows representing it as a "ISO 8601 time diff encoding", see the docs for more info.
* `frozenset`:
- * 在请求和响应中,作为 `set` 对待:
- * 在请求中,列表将被读取,消除重复,并将其转换为一个 `set`。
- * 在响应中 `set` 将被转换为 `list` 。
- * 产生的模式将指定那些 `set` 的值是唯一的 (使用 JSON 模式的 `uniqueItems`)。
+ * In requests and responses, treated the same as a `set`:
+ * In requests, a list will be read, eliminating duplicates and converting it to a `set`.
+ * In responses, the `set` will be converted to a `list`.
+ * The generated schema will specify that the `set` values are unique (using JSON Schema's `uniqueItems`).
* `bytes`:
- * 标准的 Python `bytes`。
- * 在请求和相应中被当作 `str` 处理。
- * 生成的模式将指定这个 `str` 是 `binary` "格式"。
+ * Standard Python `bytes`.
+ * In requests and responses will be treated as `str`.
+ * The generated schema will specify that it's a `str` with `binary` "format".
* `Decimal`:
- * 标准的 Python `Decimal`。
- * 在请求和相应中被当做 `float` 一样处理。
-* 您可以在这里检查所有有效的pydantic数据类型: Pydantic data types.
+ * Standard Python `Decimal`.
+ * In requests and responses, handled the same as a `float`.
+* You can check all the valid pydantic data types here: Pydantic data types.
-## 例子
+## Example
-下面是一个*路径操作*的示例,其中的参数使用了上面的一些类型。
+Here's an example *path operation* with parameters using some of the above types.
-```Python hl_lines="1 3 12-16"
-{!../../../docs_src/extra_data_types/tutorial001.py!}
-```
+=== "Python 3.10+"
-注意,函数内的参数有原生的数据类型,你可以,例如,执行正常的日期操作,如:
+ ```Python hl_lines="1 3 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
+ ```
-```Python hl_lines="18-19"
-{!../../../docs_src/extra_data_types/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="1 3 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 3 13-17"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1 2 11-15"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1 2 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
+
+Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-20"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
From b0a0a0c49009fb67ebd08ae5d04dec48991335e9 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:38 +0800
Subject: [PATCH 078/163] New translations extra-models.md (Chinese Simplified)
---
docs/zh/docs/tutorial/extra-models.md | 193 ++++++++++++++++----------
1 file changed, 123 insertions(+), 70 deletions(-)
diff --git a/docs/zh/docs/tutorial/extra-models.md b/docs/zh/docs/tutorial/extra-models.md
index 1fbe77be8de70..e91e879e41672 100644
--- a/docs/zh/docs/tutorial/extra-models.md
+++ b/docs/zh/docs/tutorial/extra-models.md
@@ -1,55 +1,63 @@
-# 额外的模型
+# Extra Models
-我们从前面的示例继续,拥有多个相关的模型是很常见的。
+Continuing with the previous example, it will be common to have more than one related model.
-对用户模型来说尤其如此,因为:
+This is especially the case for user models, because:
-* **输入模型**需要拥有密码属性。
-* **输出模型**不应该包含密码。
-* **数据库模型**很可能需要保存密码的哈希值。
+* The **input model** needs to be able to have a password.
+* The **output model** should not have a password.
+* The **database model** would probably need to have a hashed password.
!!! danger
- 永远不要存储用户的明文密码。始终存储一个可以用于验证的「安全哈希值」。
+ Never store user's plaintext passwords. Always store a "secure hash" that you can then verify.
- 如果你尚未了解该知识,你可以在[安全章节](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}中学习何为「密码哈希值」。
+ If you don't know, you will learn what a "password hash" is in the [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.
-## 多个模型
+## Multiple models
-下面是应该如何根据它们的密码字段以及使用位置去定义模型的大概思路:
+Here's a general idea of how the models could look like with their password fields and the places where they are used:
-```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
-{!../../../docs_src/extra_models/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
+ {!> ../../../docs_src/extra_models/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
+ {!> ../../../docs_src/extra_models/tutorial001.py!}
+ ```
-### 关于 `**user_in.dict()`
+### About `**user_in.dict()`
-#### Pydantic 的 `.dict()`
+#### Pydantic's `.dict()`
-`user_in` 是一个 `UserIn` 类的 Pydantic 模型.
+`user_in` is a Pydantic model of class `UserIn`.
-Pydantic 模型具有 `.dict()` 方法,该方法返回一个拥有模型数据的 `dict`。
+Pydantic models have a `.dict()` method that returns a `dict` with the model's data.
-因此,如果我们像下面这样创建一个 Pydantic 对象 `user_in`:
+So, if we create a Pydantic object `user_in` like:
```Python
user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
```
-然后我们调用:
+and then we call:
```Python
user_dict = user_in.dict()
```
-现在我们有了一个数据位于变量 `user_dict` 中的 `dict`(它是一个 `dict` 而不是 Pydantic 模型对象)。
+we now have a `dict` with the data in the variable `user_dict` (it's a `dict` instead of a Pydantic model object).
-如果我们调用:
+And if we call:
```Python
print(user_dict)
```
-我们将获得一个这样的 Python `dict`:
+we would get a Python `dict` with:
```Python
{
@@ -60,17 +68,17 @@ print(user_dict)
}
```
-#### 解包 `dict`
+#### Unwrapping a `dict`
-如果我们将 `user_dict` 这样的 `dict` 以 `**user_dict` 形式传递给一个函数(或类),Python将对其进行「解包」。它会将 `user_dict` 的键和值作为关键字参数直接传递。
+If we take a `dict` like `user_dict` and pass it to a function (or class) with `**user_dict`, Python will "unwrap" it. It will pass the keys and values of the `user_dict` directly as key-value arguments.
-因此,从上面的 `user_dict` 继续,编写:
+So, continuing with the `user_dict` from above, writing:
```Python
UserInDB(**user_dict)
```
-会产生类似于以下的结果:
+Would result in something equivalent to:
```Python
UserInDB(
@@ -81,7 +89,7 @@ UserInDB(
)
```
-或者更确切地,直接使用 `user_dict` 来表示将来可能包含的任何内容:
+Or more exactly, using `user_dict` directly, with whatever contents it might have in the future:
```Python
UserInDB(
@@ -92,34 +100,34 @@ UserInDB(
)
```
-#### 来自于其他模型内容的 Pydantic 模型
+#### A Pydantic model from the contents of another
-如上例所示,我们从 `user_in.dict()` 中获得了 `user_dict`,此代码:
+As in the example above we got `user_dict` from `user_in.dict()`, this code:
```Python
user_dict = user_in.dict()
UserInDB(**user_dict)
```
-等同于:
+would be equivalent to:
```Python
UserInDB(**user_in.dict())
```
-...因为 `user_in.dict()` 是一个 `dict`,然后我们通过以`**`开头传递给 `UserInDB` 来使 Python「解包」它。
+...because `user_in.dict()` is a `dict`, and then we make Python "unwrap" it by passing it to `UserInDB` prepended with `**`.
-这样,我们获得了一个来自于其他 Pydantic 模型中的数据的 Pydantic 模型。
+So, we get a Pydantic model from the data in another Pydantic model.
-#### 解包 `dict` 和额外关键字
+#### Unwrapping a `dict` and extra keywords
-然后添加额外的关键字参数 `hashed_password=hashed_password`,例如:
+And then adding the extra keyword argument `hashed_password=hashed_password`, like in:
```Python
UserInDB(**user_in.dict(), hashed_password=hashed_password)
```
-...最终的结果如下:
+...ends up being like:
```Python
UserInDB(
@@ -132,68 +140,113 @@ UserInDB(
```
!!! warning
- 辅助性的额外函数只是为了演示可能的数据流,但它们显然不能提供任何真正的安全性。
+ The supporting additional functions are just to demo a possible flow of the data, but they of course are not providing any real security.
-## 减少重复
+## Reduce duplication
-减少代码重复是 **FastAPI** 的核心思想之一。
+Reducing code duplication is one of the core ideas in **FastAPI**.
-因为代码重复会增加出现 bug、安全性问题、代码失步问题(当你在一个位置更新了代码但没有在其他位置更新)等的可能性。
+As code duplication increments the chances of bugs, security issues, code desynchronization issues (when you update in one place but not in the others), etc.
-上面的这些模型都共享了大量数据,并拥有重复的属性名称和类型。
+And these models are all sharing a lot of the data and duplicating attribute names and types.
-我们可以做得更好。
+We could do better.
-我们可以声明一个 `UserBase` 模型作为其他模型的基类。然后我们可以创建继承该模型属性(类型声明,校验等)的子类。
+We can declare a `UserBase` model that serves as a base for our other models. And then we can make subclasses of that model that inherit its attributes (type declarations, validation, etc).
-所有的数据转换、校验、文档生成等仍将正常运行。
+All the data conversion, validation, documentation, etc. will still work as normally.
-这样,我们可以仅声明模型之间的差异部分(具有明文的 `password`、具有 `hashed_password` 以及不包括密码)。
+That way, we can declare just the differences between the models (with plaintext `password`, with `hashed_password` and without password):
-```Python hl_lines="9 15-16 19-20 23-24"
-{!../../../docs_src/extra_models/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 13-14 17-18 21-22"
+ {!> ../../../docs_src/extra_models/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
-## `Union` 或者 `anyOf`
+ ```Python hl_lines="9 15-16 19-20 23-24"
+ {!> ../../../docs_src/extra_models/tutorial002.py!}
+ ```
-你可以将一个响应声明为两种类型的 `Union`,这意味着该响应将是两种类型中的任何一种。
+## `Union` or `anyOf`
-这将在 OpenAPI 中使用 `anyOf` 进行定义。
+You can declare a response to be the `Union` of two types, that means, that the response would be any of the two.
-为此,请使用标准的 Python 类型提示 `typing.Union`:
+It will be defined in OpenAPI with `anyOf`.
+To do that, use the standard Python type hint `typing.Union`:
!!! note
- 定义一个 `Union` 类型时,首先包括最详细的类型,然后是不太详细的类型。在下面的示例中,更详细的 `PlaneItem` 位于 `Union[PlaneItem,CarItem]` 中的 `CarItem` 之前。
+ When defining a `Union`, include the most specific type first, followed by the less specific type. In the example below, the more specific `PlaneItem` comes before `CarItem` in `Union[PlaneItem, CarItem]`.
-```Python hl_lines="1 14-15 18-20 33"
-{!../../../docs_src/extra_models/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
-## 模型列表
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003.py!}
+ ```
-你可以用同样的方式声明由对象列表构成的响应。
+### `Union` in Python 3.10
-为此,请使用标准的 Python `typing.List`:
+In this example we pass `Union[PlaneItem, CarItem]` as the value of the argument `response_model`.
-```Python hl_lines="1 20"
-{!../../../docs_src/extra_models/tutorial004.py!}
+Because we are passing it as a **value to an argument** instead of putting it in a **type annotation**, we have to use `Union` even in Python 3.10.
+
+If it was in a type annotation we could have used the vertical bar, as:
+
+```Python
+some_variable: PlaneItem | CarItem
```
-## 任意 `dict` 构成的响应
+But if we put that in `response_model=PlaneItem | CarItem` we would get an error, because Python would try to perform an **invalid operation** between `PlaneItem` and `CarItem` instead of interpreting that as a type annotation.
-你还可以使用一个任意的普通 `dict` 声明响应,仅声明键和值的类型,而不使用 Pydantic 模型。
+## List of models
-如果你事先不知道有效的字段/属性名称(对于 Pydantic 模型是必需的),这将很有用。
+The same way, you can declare responses of lists of objects.
-在这种情况下,你可以使用 `typing.Dict`:
+For that, use the standard Python `typing.List` (or just `list` in Python 3.9 and above):
-```Python hl_lines="1 8"
-{!../../../docs_src/extra_models/tutorial005.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/extra_models/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 20"
+ {!> ../../../docs_src/extra_models/tutorial004.py!}
+ ```
+
+## Response with arbitrary `dict`
+
+You can also declare a response using a plain arbitrary `dict`, declaring just the type of the keys and values, without using a Pydantic model.
+
+This is useful if you don't know the valid field/attribute names (that would be needed for a Pydantic model) beforehand.
+
+In this case, you can use `typing.Dict` (or just `dict` in Python 3.9 and above):
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/extra_models/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 8"
+ {!> ../../../docs_src/extra_models/tutorial005.py!}
+ ```
-## 总结
+## Recap
-使用多个 Pydantic 模型,并针对不同场景自由地继承。
+Use multiple Pydantic models and inherit freely for each case.
-如果一个实体必须能够具有不同的「状态」,你无需为每个状态的实体定义单独的数据模型。以用户「实体」为例,其状态有包含 `password`、包含 `password_hash` 以及不含密码。
+You don't need to have a single data model per entity if that entity must be able to have different "states". As the case with the user "entity" with a state including `password`, `password_hash` and no password.
From 4f73128a714b1d00a3943283d8994a9091bf62ee Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:39 +0800
Subject: [PATCH 079/163] New translations first-steps.md (Chinese Simplified)
---
docs/zh/docs/tutorial/first-steps.md | 225 +++++++++++++--------------
1 file changed, 111 insertions(+), 114 deletions(-)
diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md
index 30fae99cf8fc2..1368b89c76081 100644
--- a/docs/zh/docs/tutorial/first-steps.md
+++ b/docs/zh/docs/tutorial/first-steps.md
@@ -1,14 +1,14 @@
-# 第一步
+# First Steps
-最简单的 FastAPI 文件可能像下面这样:
+The simplest FastAPI file could look like this:
```Python
{!../../../docs_src/first_steps/tutorial001.py!}
```
-将其复制到 `main.py` 文件中。
+Copy that to a file `main.py`.
-运行实时服务器:
+Run the live server:
get 操作
-
-!!! info "`@decorator` Info"
- `@something` 语法在 Python 中被称为「装饰器」。
+The `@app.get("/")` tells **FastAPI** that the function right below is in charge of handling requests that go to:
- 像一顶漂亮的装饰帽一样,将它放在一个函数的上方(我猜测这个术语的命名就是这么来的)。
+* the path `/`
+* using a get operation
- 装饰器接收位于其下方的函数并且用它完成一些工作。
+!!! info "`@decorator` Info" That `@something` syntax in Python is called a "decorator".
- 在我们的例子中,这个装饰器告诉 **FastAPI** 位于其下方的函数对应着**路径** `/` 加上 `get` **操作**。
+ You put it on top of a function. Like a pretty decorative hat (I guess that's where the term came from).
+
+ A "decorator" takes the function below and does something with it.
+
+ In our case, this decorator tells **FastAPI** that the function below corresponds to the **path** `/` with an **operation** `get`.
+
+ It is the "**path operation decorator**".
- 它是一个「**路径操作装饰器**」。
-
-你也可以使用其他的操作:
+You can also use the other operations:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
-以及更少见的:
+And the more exotic ones:
* `@app.options()`
* `@app.head()`
@@ -277,59 +274,59 @@ https://example.com/items/foo
* `@app.trace()`
!!! tip
- 您可以随意使用任何一个操作(HTTP方法)。
-
- **FastAPI** 没有强制要求操作有任何特定的含义。
-
- 此处提供的信息仅作为指导,而不是要求。
+ You are free to use each operation (HTTP method) as you wish.
- 比如,当使用 GraphQL 时通常你所有的动作都通过 `post` 一种方法执行。
+ **FastAPI** doesn't enforce any specific meaning.
+
+ The information here is presented as a guideline, not a requirement.
+
+ For example, when using GraphQL you normally perform all the actions using only `POST` operations.
-### 步骤 4:定义**路径操作函数**
+### Step 4: define the **path operation function**
-这是我们的「**路径操作函数**」:
+This is our "**path operation function**":
-* **路径**:是 `/`。
-* **操作**:是 `get`。
-* **函数**:是位于「装饰器」下方的函数(位于 `@app.get("/")` 下方)。
+* **path**: is `/`.
+* **operation**: is `get`.
+* **function**: is the function below the "decorator" (below `@app.get("/")`).
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial001.py!}
```
-这是一个 Python 函数。
+This is a Python function.
-每当 **FastAPI** 接收一个使用 `GET` 方法访问 URL「`/`」的请求时这个函数会被调用。
+It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using a `GET` operation.
-在这个例子中,它是一个 `async` 函数。
+In this case, it is an `async` function.
---
-你也可以将其定义为常规函数而不使用 `async def`:
+You could also define it as a normal function instead of `async def`:
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial003.py!}
```
!!! note
- 如果你不知道两者的区别,请查阅 [Async: *"In a hurry?"*](https://fastapi.tiangolo.com/async/#in-a-hurry){.internal-link target=_blank}。
+ If you don't know the difference, check the [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
-### 步骤 5:返回内容
+### Step 5: return the content
```Python hl_lines="8"
{!../../../docs_src/first_steps/tutorial001.py!}
```
-你可以返回一个 `dict`、`list`,像 `str`、`int` 一样的单个值,等等。
+You can return a `dict`, `list`, singular values as `str`, `int`, etc.
-你还可以返回 Pydantic 模型(稍后你将了解更多)。
+You can also return Pydantic models (you'll see more about that later).
-还有许多其他将会自动转换为 JSON 的对象和模型(包括 ORM 对象等)。尝试下使用你最喜欢的一种,它很有可能已经被支持。
+There are many other objects and models that will be automatically converted to JSON (including ORMs, etc). Try using your favorite ones, it's highly probable that they are already supported.
-## 总结
+## Recap
-* 导入 `FastAPI`。
-* 创建一个 `app` 实例。
-* 编写一个**路径操作装饰器**(如 `@app.get("/")`)。
-* 编写一个**路径操作函数**(如上面的 `def root(): ...`)。
-* 运行开发服务器(如 `uvicorn main:app --reload`)。
+* Import `FastAPI`.
+* Create an `app` instance.
+* Write a **path operation decorator** (like `@app.get("/")`).
+* Write a **path operation function** (like `def root(): ...` above).
+* Run the development server (like `uvicorn main:app --reload`).
From 7b4c777ae8a0ff1b40dd21353adcae6dd801a20c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:40 +0800
Subject: [PATCH 080/163] New translations handling-errors.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/handling-errors.md | 200 ++++++++++-------------
1 file changed, 86 insertions(+), 114 deletions(-)
diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md
index 9b066bc2cee65..b150201e797d3 100644
--- a/docs/zh/docs/tutorial/handling-errors.md
+++ b/docs/zh/docs/tutorial/handling-errors.md
@@ -1,151 +1,139 @@
-# 处理错误
+# Handling Errors
-某些情况下,需要向客户端返回错误提示。
+There are many situations in where you need to notify an error to a client that is using your API.
-这里所谓的客户端包括前端浏览器、其他应用程序、物联网设备等。
+This client could be a browser with a frontend, a code from someone else, an IoT device, etc.
-需要向客户端返回错误提示的场景主要如下:
+You could need to tell the client that:
-- 客户端没有执行操作的权限
-- 客户端没有访问资源的权限
-- 客户端要访问的项目不存在
-- 等等 ...
+* The client doesn't have enough privileges for that operation.
+* The client doesn't have access to that resource.
+* The item the client was trying to access doesn't exist.
+* etc.
-遇到这些情况时,通常要返回 **4XX**(400 至 499)**HTTP 状态码**。
+In these cases, you would normally return an **HTTP status code** in the range of **400** (from 400 to 499).
-**4XX** 状态码与表示请求成功的 **2XX**(200 至 299) HTTP 状态码类似。
+This is similar to the 200 HTTP status codes (from 200 to 299). Those "200" status codes mean that somehow there was a "success" in the request.
-只不过,**4XX** 状态码表示客户端发生的错误。
+The status codes in the 400 range mean that there was an error from the client.
-大家都知道**「404 Not Found」**错误,还有调侃这个错误的笑话吧?
+Remember all those **"404 Not Found"** errors (and jokes)?
-## 使用 `HTTPException`
+## Use `HTTPException`
-向客户端返回 HTTP 错误响应,可以使用 `HTTPException`。
+To return HTTP responses with errors to the client you use `HTTPException`.
-### 导入 `HTTPException`
+### Import `HTTPException`
```Python hl_lines="1"
{!../../../docs_src/handling_errors/tutorial001.py!}
-
```
-### 触发 `HTTPException`
+### Raise an `HTTPException` in your code
-`HTTPException` 是额外包含了和 API 有关数据的常规 Python 异常。
+`HTTPException` is a normal Python exception with additional data relevant for APIs.
-因为是 Python 异常,所以不能 `return`,只能 `raise`。
+Because it's a Python exception, you don't `return` it, you `raise` it.
-如在调用*路径操作函数*里的工具函数时,触发了 `HTTPException`,FastAPI 就不再继续执行*路径操作函数*中的后续代码,而是立即终止请求,并把 `HTTPException` 的 HTTP 错误发送至客户端。
+This also means that if you are inside a utility function that you are calling inside of your *path operation function*, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the *path operation function*, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client.
-在介绍依赖项与安全的章节中,您可以了解更多用 `raise` 异常代替 `return` 值的优势。
+The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security.
-本例中,客户端用 `ID` 请求的 `item` 不存在时,触发状态码为 `404` 的异常:
+In this example, when the client requests an item by an ID that doesn't exist, raise an exception with a status code of `404`:
```Python hl_lines="11"
{!../../../docs_src/handling_errors/tutorial001.py!}
-
```
-### 响应结果
+### The resulting response
-请求为 `http://example.com/items/foo`(`item_id` 为 `「foo」`)时,客户端会接收到 HTTP 状态码 - 200 及如下 JSON 响应结果:
+If the client requests `http://example.com/items/foo` (an `item_id` `"foo"`), that client will receive an HTTP status code of 200, and a JSON response of:
```JSON
{
"item": "The Foo Wrestlers"
}
-
```
-但如果客户端请求 `http://example.com/items/bar`(`item_id` `「bar」` 不存在时),则会接收到 HTTP 状态码 - 404(「未找到」错误)及如下 JSON 响应结果:
+But if the client requests `http://example.com/items/bar` (a non-existent `item_id` `"bar"`), that client will receive an HTTP status code of 404 (the "not found" error), and a JSON response of:
```JSON
{
"detail": "Item not found"
}
-
```
-!!! tip "提示"
-
- 触发 `HTTPException` 时,可以用参数 `detail` 传递任何能转换为 JSON 的值,不仅限于 `str`。
-
- 还支持传递 `dict`、`list` 等数据结构。
-
- **FastAPI** 能自动处理这些数据,并将之转换为 JSON。
+!!! tip
+ When raising an `HTTPException`, you can pass any value that can be converted to JSON as the parameter `detail`, not only `str`.
+ You could pass a `dict`, a `list`, etc.
+
+ They are handled automatically by **FastAPI** and converted to JSON.
-## 添加自定义响应头
+## Add custom headers
-有些场景下要为 HTTP 错误添加自定义响应头。例如,出于某些方面的安全需要。
+There are some situations in where it's useful to be able to add custom headers to the HTTP error. For example, for some types of security.
-一般情况下可能不会需要在代码中直接使用响应头。
+You probably won't need to use it directly in your code.
-但对于某些高级应用场景,还是需要添加自定义响应头:
+But in case you needed it for an advanced scenario, you can add custom headers:
```Python hl_lines="14"
{!../../../docs_src/handling_errors/tutorial002.py!}
-
```
-## 安装自定义异常处理器
+## Install custom exception handlers
-添加自定义处理器,要使用 [Starlette 的异常工具](https://www.starlette.io/exceptions/)。
+You can add custom exception handlers with the same exception utilities from Starlette.
-假设要触发的自定义异常叫作 `UnicornException`。
+Let's say you have a custom exception `UnicornException` that you (or a library you use) might `raise`.
-且需要 FastAPI 实现全局处理该异常。
+And you want to handle this exception globally with FastAPI.
-此时,可以用 `@app.exception_handler()` 添加自定义异常控制器:
+You could add a custom exception handler with `@app.exception_handler()`:
```Python hl_lines="5-7 13-18 24"
{!../../../docs_src/handling_errors/tutorial003.py!}
-
```
-请求 `/unicorns/yolo` 时,路径操作会触发 `UnicornException`。
+Here, if you request `/unicorns/yolo`, the *path operation* will `raise` a `UnicornException`.
-但该异常将会被 `unicorn_exception_handler` 处理。
+But it will be handled by the `unicorn_exception_handler`.
-接收到的错误信息清晰明了,HTTP 状态码为 `418`,JSON 内容如下:
+So, you will receive a clean error, with an HTTP status code of `418` and a JSON content of:
```JSON
{"message": "Oops! yolo did something. There goes a rainbow..."}
-
```
-!!! note "技术细节"
-
- `from starlette.requests import Request` 和 `from starlette.responses import JSONResponse` 也可以用于导入 `Request` 和 `JSONResponse`。
+!!! note "Technical Details"
+ You could also use `from starlette.requests import Request` and `from starlette.responses import JSONResponse`.
- **FastAPI** 提供了与 `starlette.responses` 相同的 `fastapi.responses` 作为快捷方式,但大部分响应操作都可以直接从 Starlette 导入。同理,`Request` 也是如此。
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `Request`.
+## Override the default exception handlers
-## 覆盖默认异常处理器
+**FastAPI** has some default exception handlers.
-**FastAPI** 自带了一些默认异常处理器。
+These handlers are in charge of returning the default JSON responses when you `raise` an `HTTPException` and when the request has invalid data.
-触发 `HTTPException` 或请求无效数据时,这些处理器返回默认的 JSON 响应结果。
+You can override these exception handlers with your own.
-不过,也可以使用自定义处理器覆盖默认异常处理器。
+### Override request validation exceptions
-### 覆盖请求验证异常
+When a request contains invalid data, **FastAPI** internally raises a `RequestValidationError`.
-请求中包含无效数据时,**FastAPI** 内部会触发 `RequestValidationError`。
+And it also includes a default exception handler for it.
-该异常也内置了默认异常处理器。
+To override it, import the `RequestValidationError` and use it with `@app.exception_handler(RequestValidationError)` to decorate the exception handler.
-覆盖默认异常处理器时需要导入 `RequestValidationError`,并用 `@app.excption_handler(RequestValidationError)` 装饰异常处理器。
-
-这样,异常处理器就可以接收 `Request` 与异常。
+The exception handler will receive a `Request` and the exception.
```Python hl_lines="2 14-16"
{!../../../docs_src/handling_errors/tutorial004.py!}
-
```
-访问 `/items/foo`,可以看到以下内容替换了默认 JSON 错误信息:
+Now, if you go to `/items/foo`, instead of getting the default JSON error with:
```JSON
{
@@ -160,75 +148,66 @@
}
]
}
-
```
-以下是文本格式的错误信息:
+you will get a text version, with:
```
1 validation error
path -> item_id
value is not a valid integer (type=type_error.integer)
-
```
-### `RequestValidationError` vs `ValidationError`
-
-!!! warning "警告"
+#### `RequestValidationError` vs `ValidationError`
- 如果您觉得现在还用不到以下技术细节,可以先跳过下面的内容。
+!!! warning
+ These are technical details that you might skip if it's not important for you now.
+`RequestValidationError` is a sub-class of Pydantic's `ValidationError`.
-`RequestValidationError` 是 Pydantic 的 `ValidationError` 的子类。
+**FastAPI** uses it so that, if you use a Pydantic model in `response_model`, and your data has an error, you will see the error in your log.
-**FastAPI** 调用的就是 `RequestValidationError` 类,因此,如果在 `response_model` 中使用 Pydantic 模型,且数据有错误时,在日志中就会看到这个错误。
+But the client/user will not see it. Instead, the client will receive an "Internal Server Error" with a HTTP status code `500`.
-但客户端或用户看不到这个错误。反之,客户端接收到的是 HTTP 状态码为 `500` 的「内部服务器错误」。
+It should be this way because if you have a Pydantic `ValidationError` in your *response* or anywhere in your code (not in the client's *request*), it's actually a bug in your code.
-这是因为在*响应*或代码(不是在客户端的请求里)中出现的 Pydantic `ValidationError` 是代码的 bug。
+And while you fix it, your clients/users shouldn't have access to internal information about the error, as that could expose a security vulnerability.
-修复错误时,客户端或用户不能访问错误的内部信息,否则会造成安全隐患。
+### Override the `HTTPException` error handler
-### 覆盖 `HTTPException` 错误处理器
+The same way, you can override the `HTTPException` handler.
-同理,也可以覆盖 `HTTPException` 处理器。
-
-例如,只为错误返回纯文本响应,而不是返回 JSON 格式的内容:
+For example, you could want to return a plain text response instead of JSON for these errors:
```Python hl_lines="3-4 9-11 22"
{!../../../docs_src/handling_errors/tutorial004.py!}
-
```
-!!! note "技术细节"
+!!! note "Technical Details"
+ You could also use `from starlette.responses import PlainTextResponse`.
- 还可以使用 `from starlette.responses import PlainTextResponse`。
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
- **FastAPI** 提供了与 `starlette.responses` 相同的 `fastapi.responses` 作为快捷方式,但大部分响应都可以直接从 Starlette 导入。
+### Use the `RequestValidationError` body
+The `RequestValidationError` contains the `body` it received with invalid data.
-### 使用 `RequestValidationError` 的请求体
-
-`RequestValidationError` 包含其接收到的无效数据请求的 `body` 。
-
-开发时,可以用这个请求体生成日志、调试错误,并返回给用户。
+You could use it while developing your app to log the body and debug it, return it to the user, etc.
```Python hl_lines="14"
{!../../../docs_src/handling_errors/tutorial005.py!}
-
```
-现在试着发送一个无效的 `item`,例如:
+Now try sending an invalid item like:
```JSON
{
"title": "towel",
"size": "XL"
}
-
```
-收到的响应包含 `body` 信息,并说明数据是无效的:
+You will receive a response telling you that the data is invalid containing the received body:
```JSON hl_lines="12-15"
{
@@ -247,43 +226,36 @@ path -> item_id
"size": "XL"
}
}
-
```
-### FastAPI `HTTPException` vs Starlette `HTTPException`
+#### FastAPI's `HTTPException` vs Starlette's `HTTPException`
-**FastAPI** 也提供了自有的 `HTTPException`。
+**FastAPI** has its own `HTTPException`.
-**FastAPI** 的 `HTTPException` 继承自 Starlette 的 `HTTPException` 错误类。
+And **FastAPI**'s `HTTPException` error class inherits from Starlette's `HTTPException` error class.
-它们之间的唯一区别是,**FastAPI** 的 `HTTPException` 可以在响应中添加响应头。
+The only difference, is that **FastAPI**'s `HTTPException` allows you to add headers to be included in the response.
-OAuth 2.0 等安全工具需要在内部调用这些响应头。
+This is needed/used internally for OAuth 2.0 and some security utilities.
-因此你可以继续像平常一样在代码中触发 **FastAPI** 的 `HTTPException` 。
+So, you can keep raising **FastAPI**'s `HTTPException` as normally in your code.
-但注册异常处理器时,应该注册到来自 Starlette 的 `HTTPException`。
+But when you register an exception handler, you should register it for Starlette's `HTTPException`.
-这样做是为了,当 Starlette 的内部代码、扩展或插件触发 Starlette `HTTPException` 时,处理程序能够捕获、并处理此异常。
+This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises a Starlette `HTTPException`, your handler will be able to catch and handle it.
-注意,本例代码中同时使用了这两个 `HTTPException`,此时,要把 Starlette 的 `HTTPException` 命名为 `StarletteHTTPException`:
+In this example, to be able to have both `HTTPException`s in the same code, Starlette's exceptions is renamed to `StarletteHTTPException`:
```Python
from starlette.exceptions import HTTPException as StarletteHTTPException
-
```
-### 复用 **FastAPI** 异常处理器
+### Re-use **FastAPI**'s exception handlers
-FastAPI 支持先对异常进行某些处理,然后再使用 **FastAPI** 中处理该异常的默认异常处理器。
-
-从 `fastapi.exception_handlers` 中导入要复用的默认异常处理器:
+If you want to use the exception along with the same default exception handlers from **FastAPI**, You can import and re-use the default exception handlers from `fastapi.exception_handlers`:
```Python hl_lines="2-5 15 21"
{!../../../docs_src/handling_errors/tutorial006.py!}
-
```
-虽然,本例只是输出了夸大其词的错误信息。
-
-但也足以说明,可以在处理异常之后再复用默认的异常处理器。
+In this example you are just `print`ing the error with a very expressive message, but you get the idea. You can use the exception and then just re-use the default exception handlers.
From d51695fc93eeca8030e65ed4397b9b76fde5b42c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:41 +0800
Subject: [PATCH 081/163] New translations header-params.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/header-params.md | 220 ++++++++++++++++++++-----
1 file changed, 178 insertions(+), 42 deletions(-)
diff --git a/docs/zh/docs/tutorial/header-params.md b/docs/zh/docs/tutorial/header-params.md
index c4b1c38ceecc8..9e928cdc6b482 100644
--- a/docs/zh/docs/tutorial/header-params.md
+++ b/docs/zh/docs/tutorial/header-params.md
@@ -1,79 +1,215 @@
-# Header 参数
+# Header Parameters
-你可以使用定义 `Query`, `Path` 和 `Cookie` 参数一样的方法定义 Header 参数。
+You can define Header parameters the same way you define `Query`, `Path` and `Cookie` parameters.
-## 导入 `Header`
+## Import `Header`
-首先导入 `Header`:
+First import `Header`:
-```Python hl_lines="3"
-{!../../../docs_src/header_params/tutorial001.py!}
-```
+=== "Python 3.10+"
-## 声明 `Header` 参数
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
+ ```
-然后使用和`Path`, `Query` and `Cookie` 一样的结构定义 header 参数
+=== "Python 3.9+"
-第一个值是默认值,你可以传递所有的额外验证或注释参数:
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
+ ```
-```Python hl_lines="9"
-{!../../../docs_src/header_params/tutorial001.py!}
-```
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/header_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
+## Declare `Header` parameters
+
+Then declare the header parameters using the same structure as with `Path`, `Query` and `Cookie`.
+
+The first value is the default value, you can pass all the extra validation or annotation parameters:
+
+=== "Python 3.10+"
-!!! note "技术细节"
- `Header` 是 `Path`, `Query` 和 `Cookie` 的兄弟类型。它也继承自通用的 `Param` 类.
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
+ ```
- 但是请记得,当你从`fastapi`导入 `Query`, `Path`, `Header`, 或其他时,实际上导入的是返回特定类型的函数。
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
+
+!!! note "Technical Details"
+ `Header` is a "sister" class of `Path`, `Query` and `Cookie`. It also inherits from the same common `Param` class.
+
+ But remember that when you import `Query`, `Path`, `Header`, and others from `fastapi`, those are actually functions that return special classes.
!!! info
- 为了声明headers, 你需要使用`Header`, 因为否则参数将被解释为查询参数。
+ To declare headers, you need to use `Header`, because otherwise the parameters would be interpreted as query parameters.
-## 自动转换
+## Automatic conversion
-`Header` 在 `Path`, `Query` 和 `Cookie` 提供的功能之上有一点额外的功能。
+`Header` has a little extra functionality on top of what `Path`, `Query` and `Cookie` provide.
-大多数标准的headers用 "连字符" 分隔,也称为 "减号" (`-`)。
+Most of the standard headers are separated by a "hyphen" character, also known as the "minus symbol" (`-`).
-但是像 `user-agent` 这样的变量在Python中是无效的。
+But a variable like `user-agent` is invalid in Python.
-因此, 默认情况下, `Header` 将把参数名称的字符从下划线 (`_`) 转换为连字符 (`-`) 来提取并记录 headers.
+So, by default, `Header` will convert the parameter names characters from underscore (`_`) to hyphen (`-`) to extract and document the headers.
-同时,HTTP headers 是大小写不敏感的,因此,因此可以使用标准Python样式(也称为 "snake_case")声明它们。
+Also, HTTP headers are case-insensitive, so, you can declare them with standard Python style (also known as "snake_case").
-因此,您可以像通常在Python代码中那样使用 `user_agent` ,而不需要将首字母大写为 `User_Agent` 或类似的东西。
+So, you can use `user_agent` as you normally would in Python code, instead of needing to capitalize the first letters as `User_Agent` or something similar.
-如果出于某些原因,你需要禁用下划线到连字符的自动转换,设置`Header`的参数 `convert_underscores` 为 `False`:
+If for some reason you need to disable automatic conversion of underscores to hyphens, set the parameter `convert_underscores` of `Header` to `False`:
-```Python hl_lines="10"
-{!../../../docs_src/header_params/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/header_params/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/header_params/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial002.py!}
+ ```
!!! warning
- 在设置 `convert_underscores` 为 `False` 之前,请记住,一些HTTP代理和服务器不允许使用带有下划线的headers。
+ Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores.
+## Duplicate headers
-## 重复的 headers
+It is possible to receive duplicate headers. That means, the same header with multiple values.
-有可能收到重复的headers。这意味着,相同的header具有多个值。
+You can define those cases using a list in the type declaration.
-您可以在类型声明中使用一个list来定义这些情况。
+You will receive all the values from the duplicate header as a Python `list`.
-你可以通过一个Python `list` 的形式获得重复header的所有值。
+For example, to declare a header of `X-Token` that can appear more than once, you can write:
-比如, 为了声明一个 `X-Token` header 可以出现多次,你可以这样写:
+=== "Python 3.10+"
-```Python hl_lines="9"
-{!../../../docs_src/header_params/tutorial003.py!}
-```
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003.py!}
+ ```
-如果你与*路径操作*通信时发送两个HTTP headers,就像:
+If you communicate with that *path operation* sending two HTTP headers like:
```
X-Token: foo
X-Token: bar
```
-响应会是:
+The response would be like:
```JSON
{
@@ -84,8 +220,8 @@ X-Token: bar
}
```
-## 回顾
+## Recap
-使用 `Header` 来声明 header , 使用和 `Query`, `Path` 与 `Cookie` 相同的模式。
+Declare headers with `Header`, using the same common pattern as `Query`, `Path` and `Cookie`.
-不用担心变量中的下划线,**FastAPI** 会负责转换它们。
+And don't worry about underscores in your variables, **FastAPI** will take care of converting them.
From 69088834ef4ea150e1e29894ef8de9584f1854fb Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:42 +0800
Subject: [PATCH 082/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/tutorial/index.md | 48 ++++++++++++++++++----------------
1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md
index 6180d3de399ae..d592f4744650a 100644
--- a/docs/zh/docs/tutorial/index.md
+++ b/docs/zh/docs/tutorial/index.md
@@ -1,18 +1,18 @@
-# 教程 - 用户指南
+# Tutorial - User Guide
-本教程将一步步向你展示如何使用 **FastAPI** 的绝大部分特性。
+This tutorial shows you how to use **FastAPI** with most of its features, step by step.
-各个章节的内容循序渐进,但是又围绕着单独的主题,所以你可以直接跳转到某个章节以解决你的特定需求。
+Each section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
-本教程同样可以作为将来的参考手册。
+It is also built to work as a future reference.
-你可以随时回到本教程并查阅你需要的内容。
+So you can come back and see exactly what you need.
-## 运行代码
+## Run the code
-所有代码片段都可以复制后直接使用(它们实际上是经过测试的 Python 文件)。
+All the code blocks can be copied and used directly (they are actually tested Python files).
-要运行任何示例,请将代码复制到 `main.py` 文件中,然后使用以下命令启动 `uvicorn`:
+To run any of the examples, copy the code to a file `main.py`, and start `uvicorn` with:
-
-## 标签元数据
-
-你也可以使用参数 `openapi_tags`,为用于分组路径操作的不同标签添加额外的元数据。
-
-它接受一个列表,这个列表包含每个标签对应的一个字典。
-
-每个字典可以包含:
-
-* `name`(**必要**):一个 `str`,它与*路径操作*和 `APIRouter` 中使用的 `tags` 参数有相同的标签名。
-* `description`:一个用于简短描述标签的 `str`。它支持 Markdown 并且会在文档用户界面中显示。
-* `externalDocs`:一个描述外部文档的 `dict`:
- * `description`:用于简短描述外部文档的 `str`。
- * `url`(**必要**):外部文档的 URL `str`。
-
-### 创建标签元数据
-
-让我们在带有标签的示例中为 `users` 和 `items` 试一下。
-
-创建标签元数据并把它传递给 `openapi_tags` 参数:
-
-```Python hl_lines="3-16 18"
-{!../../../docs_src/metadata/tutorial004.py!}
-```
-
-注意你可以在描述内使用 Markdown,例如「login」会显示为粗体(**login**)以及「fancy」会显示为斜体(_fancy_)。
-
-!!! 提示
- 不必为你使用的所有标签都添加元数据。
-
-### 使用你的标签
-
-将 `tags` 参数和*路径操作*(以及 `APIRouter`)一起使用,将其分配给不同的标签:
-
-```Python hl_lines="21 26"
-{!../../../docs_src/metadata/tutorial004.py!}
-```
-
-!!! 信息
- 阅读更多关于标签的信息[路径操作配置](../path-operation-configuration/#tags){.internal-link target=_blank}。
-
-### 查看文档
-
-如果你现在查看文档,它们会显示所有附加的元数据:
-
-
-
-### 标签顺序
-
-每个标签元数据字典的顺序也定义了在文档用户界面显示的顺序。
-
-例如按照字母顺序,即使 `users` 排在 `items` 之后,它也会显示在前面,因为我们将它的元数据添加为列表内的第一个字典。
-
-## OpenAPI URL
-
-默认情况下,OpenAPI 模式服务于 `/openapi.json`。
-
-但是你可以通过参数 `openapi_url` 对其进行配置。
-
-例如,将其设置为服务于 `/api/v1/openapi.json`:
-
-```Python hl_lines="3"
-{!../../../docs_src/metadata/tutorial002.py!}
-```
-
-如果你想完全禁用 OpenAPI 模式,可以将其设置为 `openapi_url=None`,这样也会禁用使用它的文档用户界面。
-
-## 文档 URLs
-
-你可以配置两个文档用户界面,包括:
-
-* **Swagger UI**:服务于 `/docs`。
- * 可以使用参数 `docs_url` 设置它的 URL。
- * 可以通过设置 `docs_url=None` 禁用它。
-* ReDoc:服务于 `/redoc`。
- * 可以使用参数 `redoc_url` 设置它的 URL。
- * 可以通过设置 `redoc_url=None` 禁用它。
-
-例如,设置 Swagger UI 服务于 `/documentation` 并禁用 ReDoc:
-
-```Python hl_lines="3"
-{!../../../docs_src/metadata/tutorial003.py!}
-```
+# Metadata and Docs URLs
+
+You can customize several metadata configurations in your **FastAPI** application.
+
+## Metadata for API
+
+You can set the following fields that are used in the OpenAPI specification and the automatic API docs UIs:
+
+| Parameter | Type | Description |
+| ------------------ | -------- | --------------------------------------------------------------------------------------------------------- |
+| `title` | `str` | The title of the API. |
+| `summary` | `str` | A short summary of the API. Available since OpenAPI 3.1.0, FastAPI 0.99.0. |
+| `description` | `str` | A short description of the API. It can use Markdown. |
+| `version` | `string` | The version of the API. This is the version of your own application, not of OpenAPI. For example `2.5.0`. |
+| `terms_of_service` | `str` | A URL to the Terms of Service for the API. If provided, this has to be a URL. |
+| `contact` | `dict` | The contact information for the exposed API. It can contain several fields. contact fields| Parameter | Type | Description |
|---|---|---|
name | str | The identifying name of the contact person/organization. |
url | str | The URL pointing to the contact information. MUST be in the format of a URL. |
email | str | The email address of the contact person/organization. MUST be in the format of an email address. |
license_info fields| Parameter | Type | Description |
|---|---|---|
name | str | REQUIRED (if a license_info is set). The license name used for the API. |
identifier | str | An SPDX license expression for the API. The identifier field is mutually exclusive of the url field. Available since OpenAPI 3.1.0, FastAPI 0.99.0. |
url | str | A URL to the license used for the API. MUST be in the format of a URL. |
+
+## License identifier
+
+Since OpenAPI 3.1.0 and FastAPI 0.99.0, you can also set the `license_info` with an `identifier` instead of a `url`.
+
+For example:
+
+```Python hl_lines="31"
+{!../../../docs_src/metadata/tutorial001_1.py!}
+```
+
+## Metadata for tags
+
+You can also add additional metadata for the different tags used to group your path operations with the parameter `openapi_tags`.
+
+It takes a list containing one dictionary for each tag.
+
+Each dictionary can contain:
+
+* `name` (**required**): a `str` with the same tag name you use in the `tags` parameter in your *path operations* and `APIRouter`s.
+* `description`: a `str` with a short description for the tag. It can have Markdown and will be shown in the docs UI.
+* `externalDocs`: a `dict` describing external documentation with:
+ * `description`: a `str` with a short description for the external docs.
+ * `url` (**required**): a `str` with the URL for the external documentation.
+
+### Create metadata for tags
+
+Let's try that in an example with tags for `users` and `items`.
+
+Create metadata for your tags and pass it to the `openapi_tags` parameter:
+
+```Python hl_lines="3-16 18"
+{!../../../docs_src/metadata/tutorial004.py!}
+```
+
+Notice that you can use Markdown inside of the descriptions, for example "login" will be shown in bold (**login**) and "fancy" will be shown in italics (_fancy_).
+
+!!! tip
+ You don't have to add metadata for all the tags that you use.
+
+### Use your tags
+
+Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assign them to different tags:
+
+```Python hl_lines="21 26"
+{!../../../docs_src/metadata/tutorial004.py!}
+```
+
+!!! info
+ Read more about tags in [Path Operation Configuration](../path-operation-configuration/#tags){.internal-link target=_blank}.
+
+### Check the docs
+
+Now, if you check the docs, they will show all the additional metadata:
+
+
+
+### Order of tags
+
+The order of each tag metadata dictionary also defines the order shown in the docs UI.
+
+For example, even though `users` would go after `items` in alphabetical order, it is shown before them, because we added their metadata as the first dictionary in the list.
+
+## OpenAPI URL
+
+By default, the OpenAPI schema is served at `/openapi.json`.
+
+But you can configure it with the parameter `openapi_url`.
+
+For example, to set it to be served at `/api/v1/openapi.json`:
+
+```Python hl_lines="3"
+{!../../../docs_src/metadata/tutorial002.py!}
+```
+
+If you want to disable the OpenAPI schema completely you can set `openapi_url=None`, that will also disable the documentation user interfaces that use it.
+
+## Docs URLs
+
+You can configure the two documentation user interfaces included:
+
+* **Swagger UI**: served at `/docs`.
+ * You can set its URL with the parameter `docs_url`.
+ * You can disable it by setting `docs_url=None`.
+* **ReDoc**: served at `/redoc`.
+ * You can set its URL with the parameter `redoc_url`.
+ * You can disable it by setting `redoc_url=None`.
+
+For example, to set Swagger UI to be served at `/documentation` and disable ReDoc:
+
+```Python hl_lines="3"
+{!../../../docs_src/metadata/tutorial003.py!}
+```
From 1bf9c82b4a30ff45bc3575996253af217a4a74fe Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:44 +0800
Subject: [PATCH 084/163] New translations middleware.md (Chinese Simplified)
---
docs/zh/docs/tutorial/middleware.md | 64 ++++++++++++++---------------
1 file changed, 32 insertions(+), 32 deletions(-)
diff --git a/docs/zh/docs/tutorial/middleware.md b/docs/zh/docs/tutorial/middleware.md
index c9a7e7725a120..3c6868fe4de73 100644
--- a/docs/zh/docs/tutorial/middleware.md
+++ b/docs/zh/docs/tutorial/middleware.md
@@ -1,61 +1,61 @@
-# 中间件
+# Middleware
-你可以向 **FastAPI** 应用添加中间件.
+You can add middleware to **FastAPI** applications.
-"中间件"是一个函数,它在每个**请求**被特定的*路径操作*处理之前,以及在每个**响应**返回之前工作.
+A "middleware" is a function that works with every **request** before it is processed by any specific *path operation*. And also with every **response** before returning it.
-* 它接收你的应用程序的每一个**请求**.
-* 然后它可以对这个**请求**做一些事情或者执行任何需要的代码.
-* 然后它将**请求**传递给应用程序的其他部分 (通过某种*路径操作*).
-* 然后它获取应用程序生产的**响应** (通过某种*路径操作*).
-* 它可以对该**响应**做些什么或者执行任何需要的代码.
-* 然后它返回这个 **响应**.
+* It takes each **request** that comes to your application.
+* It can then do something to that **request** or run any needed code.
+* Then it passes the **request** to be processed by the rest of the application (by some *path operation*).
+* It then takes the **response** generated by the application (by some *path operation*).
+* It can do something to that **response** or run any needed code.
+* Then it returns the **response**.
-!!! note "技术细节"
- 如果你使用了 `yield` 关键字依赖, 依赖中的退出代码将在执行中间件*后*执行.
+!!! note "Technical Details"
+ If you have dependencies with `yield`, the exit code will run *after* the middleware.
- 如果有任何后台任务(稍后记录), 它们将在执行中间件*后*运行.
+ If there were any background tasks (documented later), they will run *after* all the middleware.
-## 创建中间件
+## Create a middleware
-要创建中间件你可以在函数的顶部使用装饰器 `@app.middleware("http")`.
+To create a middleware you use the decorator `@app.middleware("http")` on top of a function.
-中间件参数接收如下参数:
+The middleware function receives:
-* `request`.
-* 一个函数 `call_next` 它将接收 `request` 作为参数.
- * 这个函数将 `request` 传递给相应的 *路径操作*.
- * 然后它将返回由相应的*路径操作*生成的 `response`.
-* 然后你可以在返回 `response` 前进一步修改它.
+* The `request`.
+* A function `call_next` that will receive the `request` as a parameter.
+ * This function will pass the `request` to the corresponding *path operation*.
+ * Then it returns the `response` generated by the corresponding *path operation*.
+* You can then modify further the `response` before returning it.
```Python hl_lines="8-9 11 14"
{!../../../docs_src/middleware/tutorial001.py!}
```
!!! tip
- 请记住可以 用'X-' 前缀添加专有自定义请求头.
+ Have in mind that custom proprietary headers can be added using the 'X-' prefix.
- 但是如果你想让浏览器中的客户端看到你的自定义请求头, 你需要把它们加到 CORS 配置 ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) 的 `expose_headers` 参数中,在 Starlette's CORS docs文档中.
+ But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in Starlette's CORS docs.
-!!! note "技术细节"
- 你也可以使用 `from starlette.requests import Request`.
+!!! note "Technical Details"
+ You could also use `from starlette.requests import Request`.
- **FastAPI** 为了开发者方便提供了该对象. 但其实它直接来自于 Starlette.
+ **FastAPI** provides it as a convenience for you, the developer. But it comes directly from Starlette.
-### 在 `response` 的前和后
+### Before and after the `response`
-在任何*路径操作*收到`request`前,可以添加要和请求一起运行的代码.
+You can add code to be run with the `request`, before any *path operation* receives it.
-也可以在*响应*生成但是返回之前添加代码.
+And also after the `response` is generated, before returning it.
-例如你可以添加自定义请求头 `X-Process-Time` 包含以秒为单位的接收请求和生成响应的时间:
+For example, you could add a custom header `X-Process-Time` containing the time in seconds that it took to process the request and generate a response:
```Python hl_lines="10 12-13"
{!../../../docs_src/middleware/tutorial001.py!}
```
-## 其他中间件
+## Other middlewares
-你可以稍后在 [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}阅读更多关于中间件的教程.
+You can later read more about other middlewares in the [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.
-你将在下一节中学习如何使用中间件处理 CORS .
+You will read about how to handle CORS with a middleware in the next section.
From 12374d8da47ccdd1de2ccbd447c44544f4267b54 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:44 +0800
Subject: [PATCH 085/163] New translations path-operation-configuration.md
(Chinese Simplified)
---
.../tutorial/path-operation-configuration.md | 184 +++++++++++++-----
1 file changed, 131 insertions(+), 53 deletions(-)
diff --git a/docs/zh/docs/tutorial/path-operation-configuration.md b/docs/zh/docs/tutorial/path-operation-configuration.md
index f79b0e692d8cd..ee3b5cd0ad9f6 100644
--- a/docs/zh/docs/tutorial/path-operation-configuration.md
+++ b/docs/zh/docs/tutorial/path-operation-configuration.md
@@ -1,101 +1,179 @@
-# 路径操作配置
+# Path Operation Configuration
-*路径操作装饰器*支持多种配置参数。
+There are several parameters that you can pass to your *path operation decorator* to configure it.
-!!! warning "警告"
+!!! warning
+ Notice that these parameters are passed directly to the *path operation decorator*, not to your *path operation function*.
- 注意:以下参数应直接传递给**路径操作装饰器**,不能传递给*路径操作函数*。
+## Response Status Code
-## `status_code` 状态码
+You can define the (HTTP) `status_code` to be used in the response of your *path operation*.
-`status_code` 用于定义*路径操作*响应中的 HTTP 状态码。
+You can pass directly the `int` code, like `404`.
-可以直接传递 `int` 代码, 比如 `404`。
+But if you don't remember what each number code is for, you can use the shortcut constants in `status`:
-如果记不住数字码的涵义,也可以用 `status` 的快捷常量:
+=== "Python 3.10+"
-```Python hl_lines="3 17"
-{!../../../docs_src/path_operation_configuration/tutorial001.py!}
-```
+ ```Python hl_lines="1 15"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
+ ```
-状态码在响应中使用,并会被添加到 OpenAPI 概图。
+=== "Python 3.9+"
-!!! note "技术细节"
+ ```Python hl_lines="3 17"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
+ ```
- 也可以使用 `from starlette import status` 导入状态码。
+=== "Python 3.6+"
- **FastAPI** 的`fastapi.status` 和 `starlette.status` 一样,只是快捷方式。实际上,`fastapi.status` 直接继承自 Starlette。
+ ```Python hl_lines="3 17"
+ {!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
+ ```
-## `tags` 参数
+That status code will be used in the response and will be added to the OpenAPI schema.
-`tags` 参数的值是由 `str` 组成的 `list` (一般只有一个 `str` ),`tags` 用于为*路径操作*添加标签:
+!!! note "Technical Details"
+ You could also use `from starlette import status`.
-```Python hl_lines="17 22 27"
-{!../../../docs_src/path_operation_configuration/tutorial002.py!}
-```
+ **FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
-OpenAPI 概图会自动添加标签,供 API 文档接口使用:
+## Tags
-
+You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
-## `summary` 和 `description` 参数
+=== "Python 3.10+"
-路径装饰器还支持 `summary` 和 `description` 这两个参数:
+ ```Python hl_lines="15 20 25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
+ ```
-```Python hl_lines="20-21"
-{!../../../docs_src/path_operation_configuration/tutorial003.py!}
-```
+=== "Python 3.9+"
-## 文档字符串(`docstring`)
+ ```Python hl_lines="17 22 27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
+ ```
-描述内容比较长且占用多行时,可以在函数的 docstring 中声明*路径操作*的描述,**FastAPI** 支持从文档字符串中读取描述内容。
+=== "Python 3.6+"
-文档字符串支持 Markdown,能正确解析和显示 Markdown 的内容,但要注意文档字符串的缩进。
+ ```Python hl_lines="17 22 27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
+ ```
-```Python hl_lines="19-27"
-{!../../../docs_src/path_operation_configuration/tutorial004.py!}
-```
+They will be added to the OpenAPI schema and used by the automatic documentation interfaces:
-下图为 Markdown 文本在 API 文档中的显示效果:
+
-
+### Tags with Enums
-## 响应描述
+If you have a big application, you might end up accumulating **several tags**, and you would want to make sure you always use the **same tag** for related *path operations*.
-`response_description` 参数用于定义响应的描述说明:
+In these cases, it could make sense to store the tags in an `Enum`.
-```Python hl_lines="21"
-{!../../../docs_src/path_operation_configuration/tutorial005.py!}
+**FastAPI** supports that the same way as with plain strings:
+
+```Python hl_lines="1 8-10 13 18"
+{!../../../docs_src/path_operation_configuration/tutorial002b.py!}
```
-!!! info "说明"
+## Summary and description
+
+You can add a `summary` and `description`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="20-21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20-21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
+ ```
+
+## Description from docstring
+
+As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function docstring and **FastAPI** will read it from there.
+
+You can write Markdown in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="17-25"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="19-27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-27"
+ {!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
+ ```
+
+It will be used in the interactive docs:
+
+
+
+## Response description
+
+You can specify the response description with the parameter `response_description`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+"
- 注意,`response_description` 只用于描述响应,`description` 一般则用于描述*路径操作*。
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
+ ```
-!!! check "检查"
+!!! info
+ Notice that `response_description` refers specifically to the response, the `description` refers to the *path operation* in general.
- OpenAPI 规定每个*路径操作*都要有响应描述。
+!!! check
+ OpenAPI specifies that each *path operation* requires a response description.
- 如果没有定义响应描述,**FastAPI** 则自动生成内容为 "Successful response" 的响应描述。
+ So, if you don't provide one, **FastAPI** will automatically generate one of "Successful response".
-
+
-## 弃用*路径操作*
+## Deprecate a *path operation*
-`deprecated` 参数可以把*路径操作*标记为弃用,无需直接删除:
+If you need to mark a *path operation* as deprecated, but without removing it, pass the parameter `deprecated`:
```Python hl_lines="16"
{!../../../docs_src/path_operation_configuration/tutorial006.py!}
```
-API 文档会把该路径操作标记为弃用:
+It will be clearly marked as deprecated in the interactive docs:
-
+
-下图显示了正常*路径操作*与弃用*路径操作* 的区别:
+Check how deprecated and non-deprecated *path operations* look like:
-
+
-## 小结
+## Recap
-通过传递参数给*路径操作装饰器* ,即可轻松地配置*路径操作*、添加元数据。
+You can configure and add metadata for your *path operations* easily by passing parameters to the *path operation decorators*.
From feaf33d2ed9e92f6c02ba45a45c6e62259f8d7d4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:45 +0800
Subject: [PATCH 086/163] New translations path-params-numeric-validations.md
(Chinese Simplified)
---
.../path-params-numeric-validations.md | 308 ++++++++++++++----
1 file changed, 240 insertions(+), 68 deletions(-)
diff --git a/docs/zh/docs/tutorial/path-params-numeric-validations.md b/docs/zh/docs/tutorial/path-params-numeric-validations.md
index 13512a08edf06..fd211224826c3 100644
--- a/docs/zh/docs/tutorial/path-params-numeric-validations.md
+++ b/docs/zh/docs/tutorial/path-params-numeric-validations.md
@@ -1,122 +1,294 @@
-# 路径参数和数值校验
+# Path Parameters and Numeric Validations
-与使用 `Query` 为查询参数声明更多的校验和元数据的方式相同,你也可以使用 `Path` 为路径参数声明相同类型的校验和元数据。
+In the same way that you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`.
-## 导入 Path
+## Import Path
-首先,从 `fastapi` 导入 `Path`:
+First, import `Path` from `fastapi`, and import `Annotated`:
-```Python hl_lines="1"
-{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
-```
+=== "Python 3.10+"
-## 声明元数据
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
+ ```
-你可以声明与 `Query` 相同的所有参数。
+=== "Python 3.9+"
-例如,要声明路径参数 `item_id`的 `title` 元数据值,你可以输入:
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
+ ```
-```Python hl_lines="8"
-{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
-```
+=== "Python 3.6+"
+
+ ```Python hl_lines="3-4"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
+
+!!! info
+ FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0.
+
+ If you have an older version, you would get errors when trying to use `Annotated`.
+
+ Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
+
+## Declare metadata
+
+You can declare all the same parameters as for `Query`.
+
+For example, to declare a `title` metadata value for the path parameter `item_id` you can type:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
!!! note
- 路径参数总是必需的,因为它必须是路径的一部分。
+ A path parameter is always required as it has to be part of the path.
- 所以,你应该在声明时使用 `...` 将其标记为必需参数。
+ So, you should declare it with `...` to mark it as required.
+
+ Nevertheless, even if you declared it with `None` or set a default value, it would not affect anything, it would still be always required.
- 然而,即使你使用 `None` 声明路径参数或设置一个其他默认值也不会有任何影响,它依然会是必需参数。
+## Order the parameters as you need
-## 按需对参数排序
+!!! tip
+ This is probably not as important or necessary if you use `Annotated`.
-假设你想要声明一个必需的 `str` 类型查询参数 `q`。
+Let's say that you want to declare the query parameter `q` as a required `str`.
-而且你不需要为该参数声明任何其他内容,所以实际上你并不需要使用 `Query`。
+And you don't need to declare anything else for that parameter, so you don't really need to use `Query`.
-但是你仍然需要使用 `Path` 来声明路径参数 `item_id`。
+But you still need to use `Path` for the `item_id` path parameter. And you don't want to use `Annotated` for some reason.
-如果你将带有「默认值」的参数放在没有「默认值」的参数之前,Python 将会报错。
+Python will complain if you put a value with a "default" before a value that doesn't have a "default".
-但是你可以对其重新排序,并将不带默认值的值(查询参数 `q`)放到最前面。
+But you can re-order them, and have the value without a default (the query parameter `q`) first.
-对 **FastAPI** 来说这无关紧要。它将通过参数的名称、类型和默认值声明(`Query`、`Path` 等)来检测参数,而不在乎参数的顺序。
+It doesn't matter for **FastAPI**. It will detect the parameters by their names, types and default declarations (`Query`, `Path`, etc), it doesn't care about the order.
-因此,你可以将函数声明为:
+So, you can declare your function as:
-```Python hl_lines="7"
-{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
-```
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
+ ```
+
+But have in mind that if you use `Annotated`, you won't have this problem, it won't matter as you're not using the function parameter default values for `Query()` or `Path()`.
+
+=== "Python 3.9+"
-## 按需对参数排序的技巧
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!}
+ ```
-如果你想不使用 `Query` 声明没有默认值的查询参数 `q`,同时使用 `Path` 声明路径参数 `item_id`,并使它们的顺序与上面不同,Python 对此有一些特殊的语法。
+=== "Python 3.6+"
-传递 `*` 作为函数的第一个参数。
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
+ ```
-Python 不会对该 `*` 做任何事情,但是它将知道之后的所有参数都应作为关键字参数(键值对),也被称为 kwargs,来调用。即使它们没有默认值。
+## Order the parameters as you need, tricks
+
+!!! tip
+ This is probably not as important or necessary if you use `Annotated`.
+
+Here's a **small trick** that can be handy, but you won't need it often.
+
+If you want to:
+
+* declare the `q` query parameter without a `Query` nor any default value
+* declare the path parameter `item_id` using `Path`
+* have them in a different order
+* not use `Annotated`
+
+...Python has a little special syntax for that.
+
+Pass `*`, as the first parameter of the function.
+
+Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as kwargs. Even if they don't have a default value.
```Python hl_lines="7"
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
```
-## 数值校验:大于等于
+### Better with `Annotated`
-使用 `Query` 和 `Path`(以及你将在后面看到的其他类)可以声明字符串约束,但也可以声明数值约束。
+Have in mind that if you use `Annotated`, as you are not using function parameter default values, you won't have this problem, and you probably won't need to use `*`.
-像下面这样,添加 `ge=1` 后,`item_id` 将必须是一个大于(`g`reater than)或等于(`e`qual)`1` 的整数。
+=== "Python 3.9+"
-```Python hl_lines="8"
-{!../../../docs_src/path_params_numeric_validations/tutorial004.py!}
-```
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!}
+ ```
-## 数值校验:大于和小于等于
+=== "Python 3.6+"
-同样的规则适用于:
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
+ ```
-* `gt`:大于(`g`reater `t`han)
-* `le`:小于等于(`l`ess than or `e`qual)
+## Number validations: greater than or equal
-```Python hl_lines="9"
-{!../../../docs_src/path_params_numeric_validations/tutorial005.py!}
-```
+With `Query` and `Path` (and others you'll see later) you can declare number constraints.
-## 数值校验:浮点数、大于和小于
+Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`.
-数值校验同样适用于 `float` 值。
+=== "Python 3.9+"
-能够声明 gt 而不仅仅是 ge 在这个前提下变得重要起来。例如,你可以要求一个值必须大于 `0`,即使它小于 `1`。
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!}
+ ```
-因此,`0.5` 将是有效值。但是 `0.0`或 `0` 不是。
+=== "Python 3.6+"
-对于 lt 也是一样的。
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
+ ```
-```Python hl_lines="11"
-{!../../../docs_src/path_params_numeric_validations/tutorial006.py!}
-```
+=== "Python 3.6+ non-Annotated"
-## 总结
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-你能够以与 [查询参数和字符串校验](query-params-str-validations.md){.internal-link target=_blank} 相同的方式使用 `Query`、`Path`(以及其他你还没见过的类)声明元数据和字符串校验。
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
+ ```
-而且你还可以声明数值校验:
+## Number validations: greater than and less than or equal
-* `gt`:大于(`g`reater `t`han)
-* `ge`:大于等于(`g`reater than or `e`qual)
-* `lt`:小于(`l`ess `t`han)
-* `le`:小于等于(`l`ess than or `e`qual)
+The same applies for:
-!!! info
- `Query`、`Path` 以及你后面会看到的其他类继承自一个共同的 `Param` 类(不需要直接使用它)。
+* `gt`: `g`reater `t`han
+* `le`: `l`ess than or `e`qual
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- 而且它们都共享相同的所有你已看到并用于添加额外校验和元数据的参数。
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
+ ```
-!!! note "技术细节"
- 当你从 `fastapi` 导入 `Query`、`Path` 和其他同类对象时,它们实际上是函数。
+## Number validations: floats, greater than and less than
- 当被调用时,它们返回同名类的实例。
+Number validations also work for `float` values.
+
+Here's where it becomes important to be able to declare gt and not just ge. As with it you can require, for example, that a value must be greater than `0`, even if it is less than `1`.
+
+So, `0.5` would be a valid value. But `0.0` or `0` would not.
+
+And the same for lt.
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!}
+ ```
+
+## Recap
+
+With `Query`, `Path` (and others you haven't seen yet) you can declare metadata and string validations in the same ways as with [Query Parameters and String Validations](query-params-str-validations.md){.internal-link target=_blank}.
+
+And you can also declare numeric validations:
+
+* `gt`: `g`reater `t`han
+* `ge`: `g`reater than or `e`qual
+* `lt`: `l`ess `t`han
+* `le`: `l`ess than or `e`qual
+
+!!! info
+ `Query`, `Path`, and other classes you will see later are subclasses of a common `Param` class.
- 如此,你导入 `Query` 这个函数。当你调用它时,它将返回一个同样命名为 `Query` 的类的实例。
+ All of them share the same parameters for additional validation and metadata you have seen.
- 因为使用了这些函数(而不是直接使用类),所以你的编辑器不会标记有关其类型的错误。
+!!! note "Technical Details"
+ When you import `Query`, `Path` and others from `fastapi`, they are actually functions.
- 这样,你可以使用常规的编辑器和编码工具,而不必添加自定义配置来忽略这些错误。
+ That when called, return instances of classes of the same name.
+
+ So, you import `Query`, which is a function. And when you call it, it returns an instance of a class also named `Query`.
+
+ These functions are there (instead of just using the classes directly) so that your editor doesn't mark errors about their types.
+
+ That way you can use your normal editor and coding tools without having to add custom configurations to disregard those errors.
From 43e63593c8d93f00472e498671a59b10251891f5 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:46 +0800
Subject: [PATCH 087/163] New translations path-params.md (Chinese Simplified)
---
docs/zh/docs/tutorial/path-params.md | 190 +++++++++++++++------------
1 file changed, 104 insertions(+), 86 deletions(-)
diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md
index 1b428d6627112..6b14a69a6f553 100644
--- a/docs/zh/docs/tutorial/path-params.md
+++ b/docs/zh/docs/tutorial/path-params.md
@@ -1,48 +1,48 @@
-# 路径参数
+# Path Parameters
-你可以使用与 Python 格式化字符串相同的语法来声明路径"参数"或"变量":
+You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
```Python hl_lines="6-7"
{!../../../docs_src/path_params/tutorial001.py!}
```
-路径参数 `item_id` 的值将作为参数 `item_id` 传递给你的函数。
+The value of the path parameter `item_id` will be passed to your function as the argument `item_id`.
-所以,如果你运行示例并访问 http://127.0.0.1:8000/items/foo,将会看到如下响应:
+So, if you run this example and go to http://127.0.0.1:8000/items/foo, you will see a response of:
```JSON
{"item_id":"foo"}
```
-## 有类型的路径参数
+## Path parameters with types
-你可以使用标准的 Python 类型标注为函数中的路径参数声明类型。
+You can declare the type of a path parameter in the function, using standard Python type annotations:
```Python hl_lines="7"
{!../../../docs_src/path_params/tutorial002.py!}
```
-在这个例子中,`item_id` 被声明为 `int` 类型。
+In this case, `item_id` is declared to be an `int`.
!!! check
- 这将为你的函数提供编辑器支持,包括错误检查、代码补全等等。
+ This will give you editor support inside of your function, with error checks, completion, etc.
-## 数据转换
+## Data conversion
-如果你运行示例并打开浏览器访问 http://127.0.0.1:8000/items/3,将得到如下响应:
+If you run this example and open your browser at http://127.0.0.1:8000/items/3, you will see a response of:
```JSON
{"item_id":3}
```
!!! check
- 注意函数接收(并返回)的值为 3,是一个 Python `int` 值,而不是字符串 `"3"`。
+ Notice that the value your function received (and returned) is `3`, as a Python `int`, not a string `"3"`.
- 所以,**FastAPI** 通过上面的类型声明提供了对请求的自动"解析"。
+ So, with that type declaration, **FastAPI** gives you automatic request "parsing".
-## 数据校验
+## Data validation
-但如果你通过浏览器访问 http://127.0.0.1:8000/items/foo,你会看到一个清晰可读的 HTTP 错误:
+But if you go to the browser at http://127.0.0.1:8000/items/foo, you will see a nice HTTP error of:
```JSON
{
@@ -59,176 +59,194 @@
}
```
-因为路径参数 `item_id` 传入的值为 `"foo"`,它不是一个 `int`。
+because the path parameter `item_id` had a value of `"foo"`, which is not an `int`.
-如果你提供的是 `float` 而非整数也会出现同样的错误,比如: http://127.0.0.1:8000/items/4.2
+The same error would appear if you provided a `float` instead of an `int`, as in: http://127.0.0.1:8000/items/4.2
!!! check
- 所以,通过同样的 Python 类型声明,**FastAPI** 提供了数据校验功能。
+ So, with the same Python type declaration, **FastAPI** gives you data validation.
- 注意上面的错误同样清楚地指出了校验未通过的具体原因。
+ Notice that the error also clearly states exactly the point where the validation didn't pass.
+
+ This is incredibly helpful while developing and debugging code that interacts with your API.
- 在开发和调试与你的 API 进行交互的代码时,这非常有用。
+## Documentation
-## 文档
+And when you open your browser at http://127.0.0.1:8000/docs, you will see an automatic, interactive, API documentation like:
-当你打开浏览器访问 http://127.0.0.1:8000/docs,你将看到自动生成的交互式 API 文档:
-
-
+
!!! check
- 再一次,还是通过相同的 Python 类型声明,**FastAPI** 为你提供了自动生成的交互式文档(集成 Swagger UI)。
+ Again, just with that same Python type declaration, **FastAPI** gives you automatic, interactive documentation (integrating Swagger UI).
- 注意这里的路径参数被声明为一个整数。
+ Notice that the path parameter is declared to be an integer.
-## 基于标准的好处:可选文档
+## Standards-based benefits, alternative documentation
-由于生成的 API 模式来自于 OpenAPI 标准,所以有很多工具与其兼容。
+And because the generated schema is from the OpenAPI standard, there are many compatible tools.
-正因如此,**FastAPI** 内置了一个可选的 API 文档(使用 Redoc):
+Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc), which you can access at http://127.0.0.1:8000/redoc:
-
+
-同样的,还有很多其他兼容的工具,包括适用于多种语言的代码生成工具。
+The same way, there are many compatible tools. Including code generation tools for many languages.
## Pydantic
-所有的数据校验都由 Pydantic 在幕后完成,所以你可以从它所有的优点中受益。并且你知道它在这方面非常胜任。
+All the data validation is performed under the hood by Pydantic, so you get all the benefits from it. And you know you are in good hands.
+
+You can use the same type declarations with `str`, `float`, `bool` and many other complex data types.
-你可以使用同样的类型声明来声明 `str`、`float`、`bool` 以及许多其他的复合数据类型。
+Several of these are explored in the next chapters of the tutorial.
-本教程的下一章节将探讨其中的一些内容。
+## Order matters
-## 顺序很重要
+When creating *path operations*, you can find situations where you have a fixed path.
-在创建*路径操作*时,你会发现有些情况下路径是固定的。
+Like `/users/me`, let's say that it's to get data about the current user.
-比如 `/users/me`,我们假设它用来获取关于当前用户的数据.
+And then you can also have a path `/users/{user_id}` to get data about a specific user by some user ID.
-然后,你还可以使用路径 `/users/{user_id}` 来通过用户 ID 获取关于特定用户的数据。
+Because *path operations* are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
-由于*路径操作*是按顺序依次运行的,你需要确保路径 `/users/me` 声明在路径 `/users/{user_id}`之前:
```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
-否则,`/users/{user_id}` 的路径还将与 `/users/me` 相匹配,"认为"自己正在接收一个值为 `"me"` 的 `user_id` 参数。
+Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`.
+
+Similarly, you cannot redefine a path operation:
+
+```Python hl_lines="6 11"
+{!../../../docs_src/path_params/tutorial003b.py!}
+```
+
+The first one will always be used since the path matches first.
-## 预设值
+## Predefined values
-如果你有一个接收路径参数的路径操作,但你希望预先设定可能的有效参数值,则可以使用标准的 Python `Enum` 类型。
+If you have a *path operation* that receives a *path parameter*, but you want the possible valid *path parameter* values to be predefined, you can use a standard Python `Enum`.
-### 创建一个 `Enum` 类
+### Create an `Enum` class
-导入 `Enum` 并创建一个继承自 `str` 和 `Enum` 的子类。
+Import `Enum` and create a sub-class that inherits from `str` and from `Enum`.
-通过从 `str` 继承,API 文档将能够知道这些值必须为 `string` 类型并且能够正确地展示出来。
+By inheriting from `str` the API docs will be able to know that the values must be of type `string` and will be able to render correctly.
-然后创建具有固定值的类属性,这些固定值将是可用的有效值:
+Then create class attributes with fixed values, which will be the available valid values:
```Python hl_lines="1 6-9"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! info
- 枚举(或 enums)从 3.4 版本起在 Python 中可用。
+ Enumerations (or enums) are available in Python since version 3.4.
!!! tip
- 如果你想知道,"AlexNet"、"ResNet" 和 "LeNet" 只是机器学习中的模型名称。
+ If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning models.
-### 声明*路径参数*
+### Declare a *path parameter*
-然后使用你定义的枚举类(`ModelName`)创建一个带有类型标注的*路径参数*:
+Then create a *path parameter* with a type annotation using the enum class you created (`ModelName`):
```Python hl_lines="16"
{!../../../docs_src/path_params/tutorial005.py!}
```
-### 查看文档
+### Check the docs
-因为已经指定了*路径参数*的可用值,所以交互式文档可以恰当地展示它们:
+Because the available values for the *path parameter* are predefined, the interactive docs can show them nicely:
-
+
-### 使用 Python *枚举类型*
+### Working with Python *enumerations*
-*路径参数*的值将是一个*枚举成员*。
+The value of the *path parameter* will be an *enumeration member*.
-#### 比较*枚举成员*
+#### Compare *enumeration members*
-你可以将它与你创建的枚举类 `ModelName` 中的*枚举成员*进行比较:
+You can compare it with the *enumeration member* in your created enum `ModelName`:
```Python hl_lines="17"
{!../../../docs_src/path_params/tutorial005.py!}
```
-#### 获取*枚举值*
+#### Get the *enumeration value*
-你可以使用 `model_name.value` 或通常来说 `your_enum_member.value` 来获取实际的值(在这个例子中为 `str`):
+You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
-```Python hl_lines="19"
+```Python hl_lines="20"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! tip
- 你也可以通过 `ModelName.lenet.value` 来获取值 `"lenet"`。
+ You could also access the value `"lenet"` with `ModelName.lenet.value`.
-#### 返回*枚举成员*
+#### Return *enumeration members*
-你可以从*路径操作*中返回*枚举成员*,即使嵌套在 JSON 结构中(例如一个 `dict` 中)。
+You can return *enum members* from your *path operation*, even nested in a JSON body (e.g. a `dict`).
-在返回给客户端之前,它们将被转换为对应的值:
+They will be converted to their corresponding values (strings in this case) before returning them to the client:
-```Python hl_lines="18-21"
+```Python hl_lines="18 21 23"
{!../../../docs_src/path_params/tutorial005.py!}
```
-## 包含路径的路径参数
+In your client you will get a JSON response like:
+
+```JSON
+{
+ "model_name": "alexnet",
+ "message": "Deep Learning FTW!"
+}
+```
+
+## Path parameters containing paths
-假设你有一个*路径操作*,它的路径为 `/files/{file_path}`。
+Let's say you have a *path operation* with a path `/files/{file_path}`.
-但是你需要 `file_path` 自身也包含*路径*,比如 `home/johndoe/myfile.txt`。
+But you need `file_path` itself to contain a *path*, like `home/johndoe/myfile.txt`.
-因此,该文件的URL将类似于这样:`/files/home/johndoe/myfile.txt`。
+So, the URL for that file would be something like: `/files/home/johndoe/myfile.txt`.
-### OpenAPI 支持
+### OpenAPI support
-OpenAPI 不支持任何方式去声明*路径参数*以在其内部包含*路径*,因为这可能会导致难以测试和定义的情况出现。
+OpenAPI doesn't support a way to declare a *path parameter* to contain a *path* inside, as that could lead to scenarios that are difficult to test and define.
-不过,你仍然可以通过 Starlette 的一个内部工具在 **FastAPI** 中实现它。
+Nevertheless, you can still do it in **FastAPI**, using one of the internal tools from Starlette.
-而且文档依旧可以使用,但是不会添加任何该参数应包含路径的说明。
+And the docs would still work, although not adding any documentation telling that the parameter should contain a path.
-### 路径转换器
+### Path convertor
-你可以使用直接来自 Starlette 的选项来声明一个包含*路径*的*路径参数*:
+Using an option directly from Starlette you can declare a *path parameter* containing a *path* using a URL like:
```
/files/{file_path:path}
```
-在这种情况下,参数的名称为 `file_path`,结尾部分的 `:path` 说明该参数应匹配任意的*路径*。
+In this case, the name of the parameter is `file_path`, and the last part, `:path`, tells it that the parameter should match any *path*.
-因此,你可以这样使用它:
+So, you can use it with:
```Python hl_lines="6"
{!../../../docs_src/path_params/tutorial004.py!}
```
!!! tip
- 你可能会需要参数包含 `/home/johndoe/myfile.txt`,以斜杠(`/`)开头。
+ You could need the parameter to contain `/home/johndoe/myfile.txt`, with a leading slash (`/`).
- 在这种情况下,URL 将会是 `/files//home/johndoe/myfile.txt`,在`files` 和 `home` 之间有一个双斜杠(`//`)。
+ In that case, the URL would be: `/files//home/johndoe/myfile.txt`, with a double slash (`//`) between `files` and `home`.
-## 总结
+## Recap
-使用 **FastAPI**,通过简短、直观和标准的 Python 类型声明,你将获得:
+With **FastAPI**, by using short, intuitive and standard Python type declarations, you get:
-* 编辑器支持:错误检查,代码补全等
-* 数据 "解析"
-* 数据校验
-* API 标注和自动生成的文档
+* Editor support: error checks, autocompletion, etc.
+* Data "parsing"
+* Data validation
+* API annotation and automatic documentation
-而且你只需要声明一次即可。
+And you only have to declare them once.
-这可能是 **FastAPI** 与其他框架相比主要的明显优势(除了原始性能以外)。
+That's probably the main visible advantage of **FastAPI** compared to alternative frameworks (apart from the raw performance).
From af859b4fb4ed14ba5ef55fd631a7b31b22bbda5b Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:47 +0800
Subject: [PATCH 088/163] New translations query-params-str-validations.md
(Chinese Simplified)
---
.../tutorial/query-params-str-validations.md | 913 +++++++++++++++---
1 file changed, 770 insertions(+), 143 deletions(-)
diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md
index 070074839f634..6905626cc983f 100644
--- a/docs/zh/docs/tutorial/query-params-str-validations.md
+++ b/docs/zh/docs/tutorial/query-params-str-validations.md
@@ -1,182 +1,598 @@
-# 查询参数和字符串校验
+# Query Parameters and String Validations
-**FastAPI** 允许你为参数声明额外的信息和校验。
+**FastAPI** allows you to declare additional information and validation for your parameters.
-让我们以下面的应用程序为例:
+Let's take this application as example:
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial001.py!}
-```
+=== "Python 3.10+"
-查询参数 `q` 的类型为 `str`,默认值为 `None`,因此它是可选的。
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
+ ```
-## 额外的校验
+=== "Python 3.6+"
-我们打算添加约束条件:即使 `q` 是可选的,但只要提供了该参数,则该参数值**不能超过50个字符的长度**。
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
+ ```
-### 导入 `Query`
+The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
-为此,首先从 `fastapi` 导入 `Query`:
+!!! note
+ FastAPI will know that the value of `q` is not required because of the default value `= None`.
-```Python hl_lines="1"
-{!../../../docs_src/query_params_str_validations/tutorial002.py!}
-```
+ The `Union` in `Union[str, None]` will allow your editor to give you better support and detect errors.
-## 使用 `Query` 作为默认值
+## Additional validation
-现在,将 `Query` 用作查询参数的默认值,并将它的 `max_length` 参数设置为 50:
+We are going to enforce that even though `q` is optional, whenever it is provided, **its length doesn't exceed 50 characters**.
-```Python hl_lines="9"
-{!../../../docs_src/query_params_str_validations/tutorial002.py!}
-```
+### Import `Query` and `Annotated`
+
+To achieve that, first import:
+
+* `Query` from `fastapi`
+* `Annotated` from `typing` (or from `typing_extensions` in Python below 3.9)
+
+=== "Python 3.10+"
+
+ In Python 3.9 or above, `Annotated` is part of the standard library, so you can import it from `typing`.
+
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ In versions of Python below Python 3.9 you import `Annotated` from `typing_extensions`.
+
+ It will already be installed with FastAPI.
+
+ ```Python hl_lines="3-4"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
+ ```
+
+!!! info
+ FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0.
+
+ If you have an older version, you would get errors when trying to use `Annotated`.
+
+ Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
+
+## Use `Annotated` in the type for the `q` parameter
+
+Remember I told you before that `Annotated` can be used to add metadata to your parameters in the [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
+
+Now it's the time to use it with FastAPI. 🚀
+
+We had this type annotation:
+
+=== "Python 3.10+"
+
+ ```Python
+ q: str | None = None
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ q: Union[str, None] = None
+ ```
+
+What we will do is wrap that with `Annotated`, so it becomes:
+
+=== "Python 3.10+"
+
+ ```Python
+ q: Annotated[str | None] = None
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ q: Annotated[Union[str, None]] = None
+ ```
+
+Both of those versions mean the same thing, `q` is a parameter that can be a `str` or `None`, and by default, it is `None`.
+
+Now let's jump to the fun stuff. 🎉
+
+## Add `Query` to `Annotated` in the `q` parameter
+
+Now that we have this `Annotated` where we can put more metadata, add `Query` to it, and set the parameter `max_length` to 50:
-由于我们必须用 `Query(default=None)` 替换默认值 `None`,`Query` 的第一个参数同样也是用于定义默认值。
+=== "Python 3.10+"
-所以:
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
+ ```
+
+Notice that the default value is still `None`, so the parameter is still optional.
+
+But now, having `Query(max_length=50)` inside of `Annotated`, we are telling FastAPI that we want it to extract this value from the query parameters (this would have been the default anyway 🤷) and that we want to have **additional validation** for this value (that's why we do this, to get the additional validation). 😎
+
+FastAPI will now:
+
+* **Validate** the data making sure that the max length is 50 characters
+* Show a **clear error** for the client when the data is not valid
+* **Document** the parameter in the OpenAPI schema *path operation* (so it will show up in the **automatic docs UI**)
+
+## Alternative (old) `Query` as the default value
+
+Previous versions of FastAPI (before 0.95.0) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you.
+
+!!! tip
+ For new code and whenever possible, use `Annotated` as explained above. There are multiple advantages (explained below) and no disadvantages. 🍰
+
+This is how you would use `Query()` as the default value of your function parameter, setting the parameter `max_length` to 50:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+ ```
+
+As in this case (without using `Annotated`) we have to replace the default value `None` in the function with `Query()`, we now need to set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value (at least for FastAPI).
+
+So:
```Python
q: Union[str, None] = Query(default=None)
```
-...使得参数可选,等同于:
+...makes the parameter optional, with a default value of `None`, the same as:
+
+```Python
+q: Union[str, None] = None
+```
+
+And in Python 3.10 and above:
+
+```Python
+q: str | None = Query(default=None)
+```
+
+...makes the parameter optional, with a default value of `None`, the same as:
```Python
-q: str = None
+q: str | None = None
```
-但是 `Query` 显式地将其声明为查询参数。
+But it declares it explicitly as being a query parameter.
+
+!!! info
+ Have in mind that the most important part to make a parameter optional is the part:
+
+ ```Python
+ = None
+ ```
+
+
+ or the:
+
+ ```Python
+ = Query(default=None)
+ ```
-然后,我们可以将更多的参数传递给 `Query`。在本例中,适用于字符串的 `max_length` 参数:
+
+ as it will use that `None` as the default value, and that way make the parameter **not required**.
+
+ The `Union[str, None]` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
+
+Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
```Python
q: Union[str, None] = Query(default=None, max_length=50)
```
-将会校验数据,在数据无效时展示清晰的错误信息,并在 OpenAPI 模式的*路径操作*中记录该参数。
+This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
+
+### `Query` as the default value or in `Annotated`
+
+Have in mind that when using `Query` inside of `Annotated` you cannot use the `default` parameter for `Query`.
-## 添加更多校验
+Instead use the actual default value of the function parameter. Otherwise, it would be inconsistent.
-你还可以添加 `min_length` 参数:
+For example, this is not allowed:
-```Python hl_lines="10"
-{!../../../docs_src/query_params_str_validations/tutorial003.py!}
+```Python
+q: Annotated[str, Query(default="rick")] = "morty"
```
-## 添加正则表达式
+...because it's not clear if the default value should be `"rick"` or `"morty"`.
+
+So, you would use (preferably):
+
+```Python
+q: Annotated[str, Query()] = "rick"
+```
-你可以定义一个参数值必须匹配的正则表达式:
+...or in older code bases you will find:
-```Python hl_lines="11"
-{!../../../docs_src/query_params_str_validations/tutorial004.py!}
+```Python
+q: str = Query(default="rick")
```
-这个指定的正则表达式通过以下规则检查接收到的参数值:
+### Advantages of `Annotated`
-* `^`:以该符号之后的字符开头,符号之前没有字符。
-* `fixedquery`: 值精确地等于 `fixedquery`。
-* `$`: 到此结束,在 `fixedquery` 之后没有更多字符。
+**Using `Annotated` is recommended** instead of the default value in function parameters, it is **better** for multiple reasons. 🤓
-如果你对所有的这些**「正则表达式」**概念感到迷茫,请不要担心。对于许多人来说这都是一个困难的主题。你仍然可以在无需正则表达式的情况下做很多事情。
+The **default** value of the **function parameter** is the **actual default** value, that's more intuitive with Python in general. 😌
-但是,一旦你需要用到并去学习它们时,请了解你已经可以在 **FastAPI** 中直接使用它们。
+You could **call** that same function in **other places** without FastAPI, and it would **work as expected**. If there's a **required** parameter (without a default value), your **editor** will let you know with an error, **Python** will also complain if you run it without passing the required parameter.
-## 默认值
+When you don't use `Annotated` and instead use the **(old) default value style**, if you call that function without FastAPI in **other place**, you have to **remember** to pass the arguments to the function for it to work correctly, otherwise the values will be different from what you expect (e.g. `QueryInfo` or something similar instead of `str`). And your editor won't complain, and Python won't complain running that function, only when the operations inside error out.
-你可以向 `Query` 的第一个参数传入 `None` 用作查询参数的默认值,以同样的方式你也可以传递其他默认值。
+Because `Annotated` can have more than one metadata annotation, you could now even use the same function with other tools, like Typer. 🚀
-假设你想要声明查询参数 `q`,使其 `min_length` 为 `3`,并且默认值为 `fixedquery`:
+## Add more validations
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial005.py!}
-```
+You can also add a parameter `min_length`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
+ ```
+
+## Add regular expressions
+
+You can define a regular expression `pattern` that the parameter should match:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
+ ```
+
+This specific regular expression pattern checks that the received parameter value:
+
+* `^`: starts with the following characters, doesn't have characters before.
+* `fixedquery`: has the exact value `fixedquery`.
+* `$`: ends there, doesn't have any more characters after `fixedquery`.
+
+If you feel lost with all these **"regular expression"** ideas, don't worry. They are a hard topic for many people. You can still do a lot of stuff without needing regular expressions yet.
+
+But whenever you need them and go and learn them, know that you can already use them directly in **FastAPI**.
+
+### Pydantic v1 `regex` instead of `pattern`
+
+Before Pydantic version 2 and before FastAPI 0.100.0, the parameter was called `regex` instead of `pattern`, but it's now deprecated.
+
+You could still see some code using it:
+
+=== "Python 3.10+ Pydantic v1"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial004_an_py310_regex.py!}
+ ```
+
+But know that this is deprecated and it should be updated to use the new parameter `pattern`. 🤓
+
+## Default values
+
+You can, of course, use default values other than `None`.
+
+Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial005.py!}
+ ```
!!! note
- 具有默认值还会使该参数成为可选参数。
+ Having a default value of any type, including `None`, makes the parameter optional (not required).
-## 声明为必需参数
+## Make it required
-当我们不需要声明额外的校验或元数据时,只需不声明默认值就可以使 `q` 参数成为必需参数,例如:
+When we don't need to declare more validations or metadata, we can make the `q` query parameter required just by not declaring a default value, like:
```Python
q: str
```
-代替:
+instead of:
```Python
q: Union[str, None] = None
```
-但是现在我们正在用 `Query` 声明它,例如:
+But we are now declaring it with `Query`, for example like:
-```Python
-q: Union[str, None] = Query(default=None, min_length=3)
-```
+=== "Annotated"
-因此,当你在使用 `Query` 且需要声明一个值是必需的时,只需不声明默认参数:
+ ```Python
+ q: Annotated[Union[str, None], Query(min_length=3)] = None
+ ```
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial006.py!}
-```
+=== "non-Annotated"
-### 使用省略号(`...`)声明必需参数
+ ```Python
+ q: Union[str, None] = Query(default=None, min_length=3)
+ ```
-有另一种方法可以显式的声明一个值是必需的,即将默认参数的默认值设为 `...` :
+So, when you need to declare a value as required while using `Query`, you can simply not declare a default value:
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial006b.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006.py!}
+ ```
+
+
+ !!! tip
+ Notice that, even though in this case the `Query()` is used as the function parameter default value, we don't pass the `default=None` to `Query()`.
+
+ Still, probably better to use the `Annotated` version. 😉
+
+### Required with Ellipsis (`...`)
+
+There's an alternative way to explicitly declare that a value is required. You can set the default to the literal value `...`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006b.py!}
+ ```
!!! info
- 如果你之前没见过 `...` 这种用法:它是一个特殊的单独值,它是 Python 的一部分并且被称为「省略号」。
- Pydantic 和 FastAPI 使用它来显式的声明需要一个值。
+ If you hadn't seen that `...` before: it is a special single value, it is part of Python and is called "Ellipsis".
-这将使 **FastAPI** 知道此查询参数是必需的。
+ It is used by Pydantic and FastAPI to explicitly declare that a value is required.
-### 使用`None`声明必需参数
+This will let **FastAPI** know that this parameter is required.
-你可以声明一个参数可以接收`None`值,但它仍然是必需的。这将强制客户端发送一个值,即使该值是`None`。
+### Required with `None`
-为此,你可以声明`None`是一个有效的类型,并仍然使用`default=...`:
+You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`.
-```Python hl_lines="9"
-{!../../../docs_src/query_params_str_validations/tutorial006c.py!}
-```
+To do that, you can declare that `None` is a valid type but still use `...` as the default:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
+ ```
!!! tip
- Pydantic 是 FastAPI 中所有数据验证和序列化的核心,当你在没有设默认值的情况下使用 `Optional` 或 `Union[Something, None]` 时,它具有特殊行为,你可以在 Pydantic 文档中阅读有关必需可选字段的更多信息。
+ Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about Required Optional fields.
-### 使用Pydantic中的`Required`代替省略号(`...`)
+### Use Pydantic's `Required` instead of Ellipsis (`...`)
-如果你觉得使用 `...` 不舒服,你也可以从 Pydantic 导入并使用 `Required`:
+If you feel uncomfortable using `...`, you can also import and use `Required` from Pydantic:
-```Python hl_lines="2 8"
-{!../../../docs_src/query_params_str_validations/tutorial006d.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="2 9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="2 8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial006d.py!}
+ ```
!!! tip
- 请记住,在大多数情况下,当你需要某些东西时,可以简单地省略 `default` 参数,因此你通常不必使用 `...` 或 `Required`
+ Remember that in most of the cases, when something is required, you can simply omit the default, so you normally don't have to use `...` nor `Required`.
+## Query parameter list / multiple values
-## 查询参数列表 / 多个值
+When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values.
-当你使用 `Query` 显式地定义查询参数时,你还可以声明它去接收一组值,或换句话来说,接收多个值。
+For example, to declare a query parameter `q` that can appear multiple times in the URL, you can write:
-例如,要声明一个可在 URL 中出现多次的查询参数 `q`,你可以这样写:
+=== "Python 3.10+"
-```Python hl_lines="9"
-{!../../../docs_src/query_params_str_validations/tutorial011.py!}
-```
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
+ ```
-然后,输入如下网址:
+Then, with a URL like:
```
http://localhost:8000/items/?q=foo&q=bar
```
-你会在*路径操作函数*的*函数参数* `q` 中以一个 Python `list` 的形式接收到*查询参数* `q` 的多个值(`foo` 和 `bar`)。
+you would receive the multiple `q` *query parameters'* values (`foo` and `bar`) in a Python `list` inside your *path operation function*, in the *function parameter* `q`.
-因此,该 URL 的响应将会是:
+So, the response to that URL would be:
```JSON
{
@@ -188,27 +604,53 @@ http://localhost:8000/items/?q=foo&q=bar
```
!!! tip
- 要声明类型为 `list` 的查询参数,如上例所示,你需要显式地使用 `Query`,否则该参数将被解释为请求体。
+ To declare a query parameter with a type of `list`, like in the example above, you need to explicitly use `Query`, otherwise it would be interpreted as a request body.
-交互式 API 文档将会相应地进行更新,以允许使用多个值:
+The interactive API docs will update accordingly, to allow multiple values:
-
+
-### 具有默认值的查询参数列表 / 多个值
+### Query parameter list / multiple values with defaults
-你还可以定义在没有任何给定值时的默认 `list` 值:
+And you can also define a default `list` of values if none are provided:
-```Python hl_lines="9"
-{!../../../docs_src/query_params_str_validations/tutorial012.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_an.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
-如果你访问:
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
+ ```
+
+If you go to:
```
http://localhost:8000/items/
```
-`q` 的默认值将为:`["foo", "bar"]`,你的响应会是:
+the default of `q` will be: `["foo", "bar"]` and your response will be:
```JSON
{
@@ -219,97 +661,282 @@ http://localhost:8000/items/
}
```
-#### 使用 `list`
+#### Using `list`
-你也可以直接使用 `list` 代替 `List [str]`:
+You can also use `list` directly instead of `List[str]` (or `list[str]` in Python 3.9+):
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial013.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial013.py!}
+ ```
!!! note
- 请记住,在这种情况下 FastAPI 将不会检查列表的内容。
+ Have in mind that in this case, FastAPI won't check the contents of the list.
- 例如,`List[int]` 将检查(并记录到文档)列表的内容必须是整数。但是单独的 `list` 不会。
+ For example, `List[int]` would check (and document) that the contents of the list are integers. But `list` alone wouldn't.
-## 声明更多元数据
+## Declare more metadata
-你可以添加更多有关该参数的信息。
+You can add more information about the parameter.
-这些信息将包含在生成的 OpenAPI 模式中,并由文档用户界面和外部工具所使用。
+That information will be included in the generated OpenAPI and used by the documentation user interfaces and external tools.
!!! note
- 请记住,不同的工具对 OpenAPI 的支持程度可能不同。
+ Have in mind that different tools might have different levels of OpenAPI support.
- 其中一些可能不会展示所有已声明的额外信息,尽管在大多数情况下,缺少的这部分功能已经计划进行开发。
+ Some of them might not show all the extra information declared yet, although in most of the cases, the missing feature is already planned for development.
-你可以添加 `title`:
+You can add a `title`:
-```Python hl_lines="10"
-{!../../../docs_src/query_params_str_validations/tutorial007.py!}
-```
+=== "Python 3.10+"
-以及 `description`:
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an_py310.py!}
+ ```
-```Python hl_lines="13"
-{!../../../docs_src/query_params_str_validations/tutorial008.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
+ ```
+
+And a `description`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
-## 别名参数
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an_py39.py!}
+ ```
-假设你想要查询参数为 `item-query`。
+=== "Python 3.6+"
-像下面这样:
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
+ ```
+
+## Alias parameters
+
+Imagine that you want the parameter to be `item-query`.
+
+Like in:
```
http://127.0.0.1:8000/items/?item-query=foobaritems
```
-但是 `item-query` 不是一个有效的 Python 变量名称。
+But `item-query` is not a valid Python variable name.
-最接近的有效名称是 `item_query`。
+The closest would be `item_query`.
-但是你仍然要求它在 URL 中必须是 `item-query`...
+But you still need it to be exactly `item-query`...
-这时你可以用 `alias` 参数声明一个别名,该别名将用于在 URL 中查找查询参数值:
+Then you can declare an `alias`, and that alias is what will be used to find the parameter value:
-```Python hl_lines="9"
-{!../../../docs_src/query_params_str_validations/tutorial009.py!}
-```
+=== "Python 3.10+"
-## 弃用参数
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an_py310.py!}
+ ```
-现在假设你不再喜欢此参数。
+=== "Python 3.9+"
-你不得不将其保留一段时间,因为有些客户端正在使用它,但你希望文档清楚地将其展示为已弃用。
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an_py39.py!}
+ ```
-那么将参数 `deprecated=True` 传入 `Query`:
+=== "Python 3.6+"
-```Python hl_lines="18"
-{!../../../docs_src/query_params_str_validations/tutorial010.py!}
-```
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
+ ```
+
+## Deprecating parameters
+
+Now let's say you don't like this parameter anymore.
+
+You have to leave it there a while because there are clients using it, but you want the docs to clearly show it as deprecated.
+
+Then pass the parameter `deprecated=True` to `Query`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
+ ```
+
+The docs will show it like this:
+
+
+
+## Exclude from OpenAPI
+
+To exclude a query parameter from the generated OpenAPI schema (and thus, from the automatic documentation systems), set the parameter `include_in_schema` of `Query` to `False`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
-文档将会像下面这样展示它:
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
+ ```
-## 总结
+## Recap
-你可以为查询参数声明额外的校验和元数据。
+You can declare additional validations and metadata for your parameters.
-通用的校验和元数据:
+Generic validations and metadata:
* `alias`
* `title`
* `description`
* `deprecated`
-特定于字符串的校验:
+Validations specific for strings:
* `min_length`
* `max_length`
* `regex`
-在这些示例中,你了解了如何声明对 `str` 值的校验。
+In these examples you saw how to declare validations for `str` values.
-请参阅下一章节,以了解如何声明对其他类型例如数值的校验。
+See the next chapters to see how to declare validations for other types, like numbers.
From c5a54911773277b6e5bbf1b214abf0b182f882b9 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:48 +0800
Subject: [PATCH 089/163] New translations query-params.md (Chinese Simplified)
---
docs/zh/docs/tutorial/query-params.md | 164 +++++++++++++++-----------
1 file changed, 98 insertions(+), 66 deletions(-)
diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md
index b1668a2d2523f..0b74b10f81c8c 100644
--- a/docs/zh/docs/tutorial/query-params.md
+++ b/docs/zh/docs/tutorial/query-params.md
@@ -1,151 +1,175 @@
-# 查询参数
+# Query Parameters
-声明不属于路径参数的其他函数参数时,它们将被自动解释为"查询字符串"参数
+When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
-查询字符串是键值对的集合,这些键值对位于 URL 的 `?` 之后,并以 `&` 符号分隔。
+The query is the set of key-value pairs that go after the `?` in a URL, separated by `&` characters.
-例如,在以下 url 中:
+For example, in the URL:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
-...查询参数为:
+...the query parameters are:
-* `skip`:对应的值为 `0`
-* `limit`:对应的值为 `10`
+* `skip`: with a value of `0`
+* `limit`: with a value of `10`
-由于它们是 URL 的一部分,因此它们的"原始值"是字符串。
+As they are part of the URL, they are "naturally" strings.
-但是,当你为它们声明了 Python 类型(在上面的示例中为 `int`)时,它们将转换为该类型并针对该类型进行校验。
+But when you declare them with Python types (in the example above, as `int`), they are converted to that type and validated against it.
-应用于路径参数的所有相同过程也适用于查询参数:
+All the same process that applied for path parameters also applies for query parameters:
-* (很明显的)编辑器支持
-* 数据"解析"
-* 数据校验
-* 自动生成文档
+* Editor support (obviously)
+* Data "parsing"
+* Data validation
+* Automatic documentation
-## 默认值
+## Defaults
-由于查询参数不是路径的固定部分,因此它们可以是可选的,并且可以有默认值。
+As query parameters are not a fixed part of a path, they can be optional and can have default values.
-在上面的示例中,它们具有 `skip=0` 和 `limit=10` 的默认值。
+In the example above they have default values of `skip=0` and `limit=10`.
-因此,访问 URL:
+So, going to the URL:
```
http://127.0.0.1:8000/items/
```
-将与访问以下地址相同:
+would be the same as going to:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
-但是,如果你访问的是:
+But if you go to, for example:
```
http://127.0.0.1:8000/items/?skip=20
```
-函数中的参数值将会是:
+The parameter values in your function will be:
-* `skip=20`:在 URL 中设定的值
-* `limit=10`:使用默认值
+* `skip=20`: because you set it in the URL
+* `limit=10`: because that was the default value
-## 可选参数
+## Optional parameters
-通过同样的方式,你可以将它们的默认值设置为 `None` 来声明可选查询参数:
+The same way, you can declare optional query parameters, by setting their default to `None`:
-```Python hl_lines="7"
-{!../../../docs_src/query_params/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial002.py!}
+ ```
-在这个例子中,函数参数 `q` 将是可选的,并且默认值为 `None`。
+In this case, the function parameter `q` will be optional, and will be `None` by default.
!!! check
- 还要注意的是,**FastAPI** 足够聪明,能够分辨出参数 `item_id` 是路径参数而 `q` 不是,因此 `q` 是一个查询参数。
+ Also notice that **FastAPI** is smart enough to notice that the path parameter `item_id` is a path parameter and `q` is not, so, it's a query parameter.
-## 查询参数类型转换
+## Query parameter type conversion
-你还可以声明 `bool` 类型,它们将被自动转换:
+You can also declare `bool` types, and they will be converted:
-```Python hl_lines="7"
-{!../../../docs_src/query_params/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params/tutorial003.py!}
+ ```
-这个例子中,如果你访问:
+In this case, if you go to:
```
http://127.0.0.1:8000/items/foo?short=1
```
-或
+or
```
http://127.0.0.1:8000/items/foo?short=True
```
-或
+or
```
http://127.0.0.1:8000/items/foo?short=true
```
-或
+or
```
http://127.0.0.1:8000/items/foo?short=on
```
-或
+or
```
http://127.0.0.1:8000/items/foo?short=yes
```
-或任何其他的变体形式(大写,首字母大写等等),你的函数接收的 `short` 参数都会是布尔值 `True`。对于值为 `False` 的情况也是一样的。
+or any other case variation (uppercase, first letter in uppercase, etc), your function will see the parameter `short` with a `bool` value of `True`. Otherwise as `False`.
-## 多个路径和查询参数
+## Multiple path and query parameters
-你可以同时声明多个路径参数和查询参数,**FastAPI** 能够识别它们。
+You can declare multiple path parameters and query parameters at the same time, **FastAPI** knows which is which.
-而且你不需要以任何特定的顺序来声明。
+And you don't have to declare them in any specific order.
-它们将通过名称被检测到:
+They will be detected by name:
-```Python hl_lines="6 8"
-{!../../../docs_src/query_params/tutorial004.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="6 8"
+ {!> ../../../docs_src/query_params/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="8 10"
+ {!> ../../../docs_src/query_params/tutorial004.py!}
+ ```
-## 必需查询参数
+## Required query parameters
-当你为非路径参数声明了默认值时(目前而言,我们所知道的仅有查询参数),则该参数不是必需的。
+When you declare a default value for non-path parameters (for now, we have only seen query parameters), then it is not required.
-如果你不想添加一个特定的值,而只是想使该参数成为可选的,则将默认值设置为 `None`。
+If you don't want to add a specific value but just make it optional, set the default as `None`.
-但当你想让一个查询参数成为必需的,不声明任何默认值就可以:
+But when you want to make a query parameter required, you can just not declare any default value:
```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
-这里的查询参数 `needy` 是类型为 `str` 的必需查询参数。
+Here the query parameter `needy` is a required query parameter of type `str`.
-如果你在浏览器中打开一个像下面的 URL:
+If you open in your browser a URL like:
```
http://127.0.0.1:8000/items/foo-item
```
-...因为没有添加必需的参数 `needy`,你将看到类似以下的错误:
+...without adding the required parameter `needy`, you will see an error like:
```JSON
{
@@ -162,13 +186,13 @@ http://127.0.0.1:8000/items/foo-item
}
```
-由于 `needy` 是必需参数,因此你需要在 URL 中设置它的值:
+As `needy` is a required parameter, you would need to set it in the URL:
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
-...这样就正常了:
+...this would work:
```JSON
{
@@ -177,17 +201,25 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
}
```
-当然,你也可以定义一些参数为必需的,一些具有默认值,而某些则完全是可选的:
+And of course, you can define some parameters as required, some as having a default value, and some entirely optional:
-```Python hl_lines="7"
-{!../../../docs_src/query_params/tutorial006.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/query_params/tutorial006_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/query_params/tutorial006.py!}
+ ```
-在这个例子中,有3个查询参数:
+In this case, there are 3 query parameters:
-* `needy`,一个必需的 `str` 类型参数。
-* `skip`,一个默认值为 `0` 的 `int` 类型参数。
-* `limit`,一个可选的 `int` 类型参数。
+* `needy`, a required `str`.
+* `skip`, an `int` with a default value of `0`.
+* `limit`, an optional `int`.
!!! tip
- 你还可以像在 [路径参数](path-params.md#predefined-values){.internal-link target=_blank} 中那样使用 `Enum`。
+ You could also use `Enum`s the same way as with [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
From fc9dcfe6991d421f8415db9a3d85228d97dd644f Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:49 +0800
Subject: [PATCH 090/163] New translations request-files.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/request-files.md | 303 +++++++++++++++++--------
1 file changed, 211 insertions(+), 92 deletions(-)
diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md
index 03474907ee94b..d2d649924f859 100644
--- a/docs/zh/docs/tutorial/request-files.md
+++ b/docs/zh/docs/tutorial/request-files.md
@@ -1,194 +1,313 @@
-# 请求文件
+# Request Files
-`File` 用于定义客户端的上传文件。
+You can define files to be uploaded by the client using `File`.
-!!! info "说明"
+!!! info
+ To receive uploaded files, first install `python-multipart`.
- 因为上传文件以「表单数据」形式发送。
+ E.g. `pip install python-multipart`.
+
+ This is because uploaded files are sent as "form data".
- 所以接收上传文件,要预先安装 `python-multipart`。
+## Import `File`
- 例如: `pip install python-multipart`。
+Import `File` and `UploadFile` from `fastapi`:
-## 导入 `File`
+=== "Python 3.9+"
-从 `fastapi` 导入 `File` 和 `UploadFile`:
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ ```
-```Python hl_lines="1"
-{!../../../docs_src/request_files/tutorial001.py!}
-```
+=== "Python 3.6+"
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ ```
-## 定义 `File` 参数
+=== "Python 3.6+ non-Annotated"
-创建文件(`File`)参数的方式与 `Body` 和 `Form` 一样:
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-```Python hl_lines="7"
-{!../../../docs_src/request_files/tutorial001.py!}
-```
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_files/tutorial001.py!}
+ ```
+
+## Define `File` Parameters
+
+Create file parameters the same way you would for `Body` or `Form`:
-!!! info "说明"
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
- `File` 是直接继承自 `Form` 的类。
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ ```
- 注意,从 `fastapi` 导入的 `Query`、`Path`、`File` 等项,实际上是返回特定类的函数。
+=== "Python 3.6+ non-Annotated"
-!!! tip "提示"
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- 声明文件体必须使用 `File`,否则,FastAPI 会把该参数当作查询参数或请求体(JSON)参数。
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/request_files/tutorial001.py!}
+ ```
-文件作为「表单数据」上传。
+!!! info
+ `File` is a class that inherits directly from `Form`.
-如果把*路径操作函数*参数的类型声明为 `bytes`,**FastAPI** 将以 `bytes` 形式读取和接收文件内容。
+ But remember that when you import `Query`, `Path`, `File` and others from `fastapi`, those are actually functions that return special classes.
-这种方式把文件的所有内容都存储在内存里,适用于小型文件。
+!!! tip
+ To declare File bodies, you need to use `File`, because otherwise the parameters would be interpreted as query parameters or body (JSON) parameters.
-不过,很多情况下,`UploadFile` 更好用。
+The files will be uploaded as "form data".
-## 含 `UploadFile` 的文件参数
+If you declare the type of your *path operation function* parameter as `bytes`, **FastAPI** will read the file for you and you will receive the contents as `bytes`.
-定义文件参数时使用 `UploadFile`:
+Have in mind that this means that the whole contents will be stored in memory. This will work well for small files.
-```Python hl_lines="12"
-{!../../../docs_src/request_files/tutorial001.py!}
-```
+But there are several cases in which you might benefit from using `UploadFile`.
-`UploadFile` 与 `bytes` 相比有更多优势:
+## File Parameters with `UploadFile`
-* 使用 `spooled` 文件:
- * 存储在内存的文件超出最大上限时,FastAPI 会把文件存入磁盘;
-* 这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;
-* 可获取上传文件的元数据;
-* 自带 file-like `async` 接口;
-* 暴露的 Python `SpooledTemporaryFile` 对象,可直接传递给其他预期「file-like」对象的库。
+Define a file parameter with a type of `UploadFile`:
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/request_files/tutorial001.py!}
+ ```
+
+Using `UploadFile` has several advantages over `bytes`:
+
+* You don't have to use `File()` in the default value of the parameter.
+* It uses a "spooled" file:
+ * A file stored in memory up to a maximum size limit, and after passing this limit it will be stored in disk.
+* This means that it will work well for large files like images, videos, large binaries, etc. without consuming all the memory.
+* You can get metadata from the uploaded file.
+* It has a file-like `async` interface.
+* It exposes an actual Python `SpooledTemporaryFile` object that you can pass directly to other libraries that expect a file-like object.
### `UploadFile`
-`UploadFile` 的属性如下:
+`UploadFile` has the following attributes:
-* `filename`:上传文件名字符串(`str`),例如, `myimage.jpg`;
-* `content_type`:内容类型(MIME 类型 / 媒体类型)字符串(`str`),例如,`image/jpeg`;
-* `file`: `SpooledTemporaryFile`( file-like 对象)。其实就是 Python文件,可直接传递给其他预期 `file-like` 对象的函数或支持库。
+* `filename`: A `str` with the original file name that was uploaded (e.g. `myimage.jpg`).
+* `content_type`: A `str` with the content type (MIME type / media type) (e.g. `image/jpeg`).
+* `file`: A `SpooledTemporaryFile` (a file-like object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
-`UploadFile` 支持以下 `async` 方法,(使用内部 `SpooledTemporaryFile`)可调用相应的文件方法。
+`UploadFile` has the following `async` methods. They all call the corresponding file methods underneath (using the internal `SpooledTemporaryFile`).
-* `write(data)`:把 `data` (`str` 或 `bytes`)写入文件;
-* `read(size)`:按指定数量的字节或字符(`size` (`int`))读取文件内容;
-* `seek(offset)`:移动至文件 `offset` (`int`)字节处的位置;
- * 例如,`await myfile.seek(0) ` 移动到文件开头;
- * 执行 `await myfile.read()` 后,需再次读取已读取内容时,这种方法特别好用;
-* `close()`:关闭文件。
+* `write(data)`: Writes `data` (`str` or `bytes`) to the file.
+* `read(size)`: Reads `size` (`int`) bytes/characters of the file.
+* `seek(offset)`: Goes to the byte position `offset` (`int`) in the file.
+ * E.g., `await myfile.seek(0)` would go to the start of the file.
+ * This is especially useful if you run `await myfile.read()` once and then need to read the contents again.
+* `close()`: Closes the file.
-因为上述方法都是 `async` 方法,要搭配「await」使用。
+As all these methods are `async` methods, you need to "await" them.
-例如,在 `async` *路径操作函数* 内,要用以下方式读取文件内容:
+For example, inside of an `async` *path operation function* you can get the contents with:
```Python
contents = await myfile.read()
```
-在普通 `def` *路径操作函数* 内,则可以直接访问 `UploadFile.file`,例如:
+If you are inside of a normal `def` *path operation function*, you can access the `UploadFile.file` directly, for example:
```Python
contents = myfile.file.read()
```
-!!! note "`async` 技术细节"
+!!! note "`async` Technical Details" When you use the `async` methods, **FastAPI** runs the file methods in a threadpool and awaits for them.
- 使用 `async` 方法时,**FastAPI** 在线程池中执行文件方法,并 `await` 操作完成。
+!!! note "Starlette Technical Details"
+ **FastAPI**'s `UploadFile` inherits directly from **Starlette**'s `UploadFile`, but adds some necessary parts to make it compatible with **Pydantic** and the other parts of FastAPI.
-!!! note "Starlette 技术细节"
+## What is "Form Data"
- **FastAPI** 的 `UploadFile` 直接继承自 **Starlette** 的 `UploadFile`,但添加了一些必要功能,使之与 **Pydantic** 及 FastAPI 的其它部件兼容。
+The way HTML forms (``) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON.
-## 什么是 「表单数据」
+**FastAPI** will make sure to read that data from the right place instead of JSON.
-与 JSON 不同,HTML 表单(``)向服务器发送数据通常使用「特殊」的编码。
+!!! note "Technical Details"
+ Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded` when it doesn't include files.
-**FastAPI** 要确保从正确的位置读取数据,而不是读取 JSON。
+ But when the form includes files, it is encoded as `multipart/form-data`. If you use `File`, **FastAPI** will know it has to get the files from the correct part of the body.
+
+ If you want to read more about these encodings and form fields, head to the MDN web docs for POST.
-!!! note "技术细节"
+!!! warning
+ You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
- 不包含文件时,表单数据一般用 `application/x-www-form-urlencoded`「媒体类型」编码。
+ This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
- 但表单包含文件时,编码为 `multipart/form-data`。使用了 `File`,**FastAPI** 就知道要从请求体的正确位置获取文件。
+## Optional File Upload
- 编码和表单字段详见 MDN Web 文档的 POST 小节。
+You can make a file optional by using standard type annotations and setting a default value of `None`:
-!!! warning "警告"
+=== "Python 3.10+"
- 可在一个*路径操作*中声明多个 `File` 和 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。因为此时请求体的编码是 `multipart/form-data`,不是 `application/json`。
+ ```Python hl_lines="9 17"
+ {!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
+ ```
- 这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
+=== "Python 3.9+"
-## 可选文件上传
+ ```Python hl_lines="9 17"
+ {!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
+ ```
-您可以通过使用标准类型注解并将 None 作为默认值的方式将一个文件参数设为可选:
+=== "Python 3.6+"
-=== "Python 3.9+"
+ ```Python hl_lines="10 18"
+ {!> ../../../docs_src/request_files/tutorial001_02_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="7 14"
+ ```Python hl_lines="7 15"
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02.py!}
```
-## 带有额外元数据的 `UploadFile`
+## `UploadFile` with Additional Metadata
-您也可以将 `File()` 与 `UploadFile` 一起使用,例如,设置额外的元数据:
+You can also use `File()` with `UploadFile`, for example, to set additional metadata:
-```Python hl_lines="13"
-{!../../../docs_src/request_files/tutorial001_03.py!}
-```
+=== "Python 3.9+"
-## 多文件上传
+ ```Python hl_lines="9 15"
+ {!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
+ ```
-FastAPI 支持同时上传多个文件。
+=== "Python 3.6+"
-可用同一个「表单字段」发送含多个文件的「表单数据」。
+ ```Python hl_lines="8 14"
+ {!> ../../../docs_src/request_files/tutorial001_03_an.py!}
+ ```
-上传多个文件时,要声明含 `bytes` 或 `UploadFile` 的列表(`List`):
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7 13"
+ {!> ../../../docs_src/request_files/tutorial001_03.py!}
+ ```
+
+## Multiple File Uploads
+
+It's possible to upload several files at the same time.
+
+They would be associated to the same "form field" sent using "form data".
+
+To use that, declare a list of `bytes` or `UploadFile`:
=== "Python 3.9+"
+ ```Python hl_lines="10 15"
+ {!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11 16"
+ {!> ../../../docs_src/request_files/tutorial002_an.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002.py!}
```
-接收的也是含 `bytes` 或 `UploadFile` 的列表(`list`)。
+You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
+!!! note "Technical Details"
+ You could also use `from starlette.responses import HTMLResponse`.
-!!! note "技术细节"
+ **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
- 也可以使用 `from starlette.responses import HTMLResponse`。
+### Multiple File Uploads with Additional Metadata
- `fastapi.responses` 其实与 `starlette.responses` 相同,只是为了方便开发者调用。实际上,大多数 **FastAPI** 的响应都直接从 Starlette 调用。
+And the same way as before, you can use `File()` to set additional parameters, even for `UploadFile`:
-### 带有额外元数据的多文件上传
+=== "Python 3.9+"
-和之前的方式一样, 您可以为 `File()` 设置额外参数, 即使是 `UploadFile`:
+ ```Python hl_lines="11 18-20"
+ {!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
+ ```
-=== "Python 3.9+"
+=== "Python 3.6+"
+
+ ```Python hl_lines="12 19-21"
+ {!> ../../../docs_src/request_files/tutorial003_an.py!}
+ ```
- ```Python hl_lines="16"
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9 16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
-=== "Python 3.6+"
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- ```Python hl_lines="18"
+ ```Python hl_lines="11 18"
{!> ../../../docs_src/request_files/tutorial003.py!}
```
-## 小结
+## Recap
-本节介绍了如何用 `File` 把上传文件声明为(表单数据的)输入参数。
+Use `File`, `bytes`, and `UploadFile` to declare files to be uploaded in the request, sent as form data.
From 9d1b1a384995963e63b4b4eb1a593c8bc004386c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:50 +0800
Subject: [PATCH 091/163] New translations request-forms-and-files.md (Chinese
Simplified)
---
.../docs/tutorial/request-forms-and-files.md | 74 +++++++++++++------
1 file changed, 53 insertions(+), 21 deletions(-)
diff --git a/docs/zh/docs/tutorial/request-forms-and-files.md b/docs/zh/docs/tutorial/request-forms-and-files.md
index 70cd70f98650c..1818946c4e087 100644
--- a/docs/zh/docs/tutorial/request-forms-and-files.md
+++ b/docs/zh/docs/tutorial/request-forms-and-files.md
@@ -1,37 +1,69 @@
-# 请求表单与文件
+# Request Forms and Files
-FastAPI 支持同时使用 `File` 和 `Form` 定义文件和表单字段。
+You can define files and form fields at the same time using `File` and `Form`.
-!!! info "说明"
+!!! info
+ To receive uploaded files and/or form data, first install `python-multipart`.
- 接收上传文件或表单数据,要预先安装 `python-multipart`。
+ E.g. `pip install python-multipart`.
- 例如,`pip install python-multipart`。
+## Import `File` and `Form`
-## 导入 `File` 与 `Form`
+=== "Python 3.9+"
-```Python hl_lines="1"
-{!../../../docs_src/request_forms_and_files/tutorial001.py!}
-```
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
+ ```
-## 定义 `File` 与 `Form` 参数
+=== "Python 3.6+"
-创建文件和表单参数的方式与 `Body` 和 `Query` 一样:
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
+ ```
-```Python hl_lines="8"
-{!../../../docs_src/request_forms_and_files/tutorial001.py!}
-```
+=== "Python 3.6+ non-Annotated"
-文件和表单字段作为表单数据上传与接收。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-声明文件可以使用 `bytes` 或 `UploadFile` 。
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
+ ```
-!!! warning "警告"
+## Define `File` and `Form` parameters
- 可在一个*路径操作*中声明多个 `File` 与 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。因为此时请求体的编码为 `multipart/form-data`,不是 `application/json`。
+Create file and form parameters the same way you would for `Body` or `Query`:
- 这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
+=== "Python 3.9+"
-## 小结
+ ```Python hl_lines="10-12"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
+ ```
-在同一个请求中接收数据和文件时,应同时使用 `File` 和 `Form`。
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
+ ```
+
+The files and form fields will be uploaded as form data and you will receive the files and form fields.
+
+And you can declare some of the files as `bytes` and some as `UploadFile`.
+
+!!! warning
+ You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
+
+ This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
+
+## Recap
+
+Use `File` and `Form` together when you need to receive data and files in the same request.
From 8f7116d3f9905d0c5e308fabbcc4d8b02b97eecf Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:51 +0800
Subject: [PATCH 092/163] New translations request-forms.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/request-forms.md | 97 +++++++++++++++++---------
1 file changed, 63 insertions(+), 34 deletions(-)
diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md
index 6436ffbcdc26e..1a608f33f5a3b 100644
--- a/docs/zh/docs/tutorial/request-forms.md
+++ b/docs/zh/docs/tutorial/request-forms.md
@@ -1,63 +1,92 @@
-# 表单数据
+# Form Data
-接收的不是 JSON,而是表单字段时,要使用 `Form`。
+When you need to receive form fields instead of JSON, you can use `Form`.
-!!! info "说明"
+!!! info
+ To use forms, first install `python-multipart`.
- 要使用表单,需预先安装 `python-multipart`。
+ E.g. `pip install python-multipart`.
- 例如,`pip install python-multipart`。
+## Import `Form`
-## 导入 `Form`
+Import `Form` from `fastapi`:
-从 `fastapi` 导入 `Form`:
+=== "Python 3.9+"
-```Python hl_lines="1"
-{!../../../docs_src/request_forms/tutorial001.py!}
-```
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
+ ```
-## 定义 `Form` 参数
+=== "Python 3.6+"
-创建表单(`Form`)参数的方式与 `Body` 和 `Query` 一样:
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms/tutorial001_an.py!}
+ ```
-```Python hl_lines="7"
-{!../../../docs_src/request_forms/tutorial001.py!}
-```
+=== "Python 3.6+ non-Annotated"
-例如,OAuth2 规范的 "密码流" 模式规定要通过表单字段发送 `username` 和 `password`。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-该规范要求字段必须命名为 `username` 和 `password`,并通过表单字段发送,不能用 JSON。
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/request_forms/tutorial001.py!}
+ ```
-使用 `Form` 可以声明与 `Body` (及 `Query`、`Path`、`Cookie`)相同的元数据和验证。
+## Define `Form` parameters
-!!! info "说明"
+Create form parameters the same way you would for `Body` or `Query`:
- `Form` 是直接继承自 `Body` 的类。
+=== "Python 3.9+"
-!!! tip "提示"
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
+ ```
- 声明表单体要显式使用 `Form` ,否则,FastAPI 会把该参数当作查询参数或请求体(JSON)参数。
+=== "Python 3.6+"
-## 关于 "表单字段"
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/request_forms/tutorial001_an.py!}
+ ```
-与 JSON 不同,HTML 表单(``)向服务器发送数据通常使用「特殊」的编码。
+=== "Python 3.6+ non-Annotated"
-**FastAPI** 要确保从正确的位置读取数据,而不是读取 JSON。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-!!! note "技术细节"
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/request_forms/tutorial001.py!}
+ ```
- 表单数据的「媒体类型」编码一般为 `application/x-www-form-urlencoded`。
+For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields.
- 但包含文件的表单编码为 `multipart/form-data`。文件处理详见下节。
+The spec requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON.
- 编码和表单字段详见 MDN Web 文档的 POST小节。
+With `Form` you can declare the same configurations as with `Body` (and `Query`, `Path`, `Cookie`), including validation, examples, an alias (e.g. `user-name` instead of `username`), etc.
-!!! warning "警告"
+!!! info
+ `Form` is a class that inherits directly from `Body`.
- 可在一个*路径操作*中声明多个 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。因为此时请求体的编码是 `application/x-www-form-urlencoded`,不是 `application/json`。
+!!! tip
+ To declare form bodies, you need to use `Form` explicitly, because without it the parameters would be interpreted as query parameters or body (JSON) parameters.
- 这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
+## About "Form Fields"
-## 小结
+The way HTML forms (``) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON.
-本节介绍了如何使用 `Form` 声明表单数据输入参数。
+**FastAPI** will make sure to read that data from the right place instead of JSON.
+
+!!! note "Technical Details"
+ Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded`.
+
+ But when the form includes files, it is encoded as `multipart/form-data`. You'll read about handling files in the next chapter.
+
+ If you want to read more about these encodings and form fields, head to the MDN web docs for POST.
+
+!!! warning
+ You can declare multiple `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `application/x-www-form-urlencoded` instead of `application/json`.
+
+ This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
+
+## Recap
+
+Use `Form` to declare form data input parameters.
From 80dfb4521dd71030390e194ab51c2021d50032c5 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:52 +0800
Subject: [PATCH 093/163] New translations response-model.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/response-model.md | 464 +++++++++++++++++++-----
1 file changed, 368 insertions(+), 96 deletions(-)
diff --git a/docs/zh/docs/tutorial/response-model.md b/docs/zh/docs/tutorial/response-model.md
index ea3d0666ded6e..9c849bf3a0453 100644
--- a/docs/zh/docs/tutorial/response-model.md
+++ b/docs/zh/docs/tutorial/response-model.md
@@ -1,118 +1,374 @@
-# 响应模型
+# Response Model - Return Type
-你可以在任意的*路径操作*中使用 `response_model` 参数来声明用于响应的模型:
+You can declare the type used for the response by annotating the *path operation function* **return type**.
+
+You can use **type annotations** the same way you would for input data in function **parameters**, you can use Pydantic models, lists, dictionaries, scalar values like integers, booleans, etc.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="16 21"
+ {!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18 23"
+ {!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18 23"
+ {!> ../../../docs_src/response_model/tutorial001_01.py!}
+ ```
+
+FastAPI will use this return type to:
+
+* **Validate** the returned data.
+ * If the data is invalid (e.g. you are missing a field), it means that *your* app code is broken, not returning what it should, and it will return a server error instead of returning incorrect data. This way you and your clients can be certain that they will receive the data and the data shape expected.
+* Add a **JSON Schema** for the response, in the OpenAPI *path operation*.
+ * This will be used by the **automatic docs**.
+ * It will also be used by automatic client code generation tools.
+
+But most importantly:
+
+* It will **limit and filter** the output data to what is defined in the return type.
+ * This is particularly important for **security**, we'll see more of that below.
+
+## `response_model` Parameter
+
+There are some cases where you need or want to return some data that is not exactly what the type declares.
+
+For example, you could want to **return a dictionary** or a database object, but **declare it as a Pydantic model**. This way the Pydantic model would do all the data documentation, validation, etc. for the object that you returned (e.g. a dictionary or database object).
+
+If you added the return type annotation, tools and editors would complain with a (correct) error telling you that your function is returning a type (e.g. a dict) that is different from what you declared (e.g. a Pydantic model).
+
+In those cases, you can use the *path operation decorator* parameter `response_model` instead of the return type.
+
+You can use the `response_model` parameter in any of the *path operations*:
* `@app.get()`
* `@app.post()`
* `@app.put()`
* `@app.delete()`
-* 等等。
+* etc.
-```Python hl_lines="17"
-{!../../../docs_src/response_model/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001.py!}
+ ```
!!! note
- 注意,`response_model`是「装饰器」方法(`get`,`post` 等)的一个参数。不像之前的所有参数和请求体,它不属于*路径操作函数*。
+ Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
-它接收的类型与你将为 Pydantic 模型属性所声明的类型相同,因此它可以是一个 Pydantic 模型,但也可以是一个由 Pydantic 模型组成的 `list`,例如 `List[Item]`。
+`response_model` receives the same type you would declare for a Pydantic model field, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`.
-FastAPI 将使用此 `response_model` 来:
+FastAPI will use this `response_model` to do all the data documentation, validation, etc. and also to **convert and filter the output data** to its type declaration.
-* 将输出数据转换为其声明的类型。
-* 校验数据。
-* 在 OpenAPI 的*路径操作*中为响应添加一个 JSON Schema。
-* 并在自动生成文档系统中使用。
+!!! tip
+ If you have strict type checks in your editor, mypy, etc, you can declare the function return type as `Any`.
-但最重要的是:
+ That way you tell the editor that you are intentionally returning anything. But FastAPI will still do the data documentation, validation, filtering, etc. with the `response_model`.
-* 会将输出数据限制在该模型定义内。下面我们会看到这一点有多重要。
+### `response_model` Priority
-!!! note "技术细节"
- 响应模型在参数中被声明,而不是作为函数返回类型的注解,这是因为路径函数可能不会真正返回该响应模型,而是返回一个 `dict`、数据库对象或其他模型,然后再使用 `response_model` 来执行字段约束和序列化。
+If you declare both a return type and a `response_model`, the `response_model` will take priority and be used by FastAPI.
-## 返回与输入相同的数据
+This way you can add correct type annotations to your functions even when you are returning a type different than the response model, to be used by the editor and tools like mypy. And still you can have FastAPI do the data validation, documentation, etc. using the `response_model`.
-现在我们声明一个 `UserIn` 模型,它将包含一个明文密码属性。
+You can also use `response_model=None` to disable creating a response model for that *path operation*, you might need to do it if you are adding type annotations for things that are not valid Pydantic fields, you will see an example of that in one of the sections below.
-```Python hl_lines="9 11"
-{!../../../docs_src/response_model/tutorial002.py!}
-```
+## Return the same input data
-我们正在使用此模型声明输入数据,并使用同一模型声明输出数据:
+Here we are declaring a `UserIn` model, it will contain a plaintext password:
-```Python hl_lines="17-18"
-{!../../../docs_src/response_model/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 9"
+ {!> ../../../docs_src/response_model/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11"
+ {!> ../../../docs_src/response_model/tutorial002.py!}
+ ```
+
+!!! info
+ To use `EmailStr`, first install `email_validator`.
+
+ E.g. `pip install email-validator`
+ or `pip install pydantic[email]`.
+
+And we are using this model to declare our input and the same model to declare our output:
+
+=== "Python 3.10+"
-现在,每当浏览器使用一个密码创建用户时,API 都会在响应中返回相同的密码。
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/response_model/tutorial002_py310.py!}
+ ```
-在这个案例中,这可能不算是问题,因为用户自己正在发送密码。
+=== "Python 3.6+"
-但是,如果我们在其他的*路径操作*中使用相同的模型,则可能会将用户的密码发送给每个客户端。
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/response_model/tutorial002.py!}
+ ```
+
+Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
+
+In this case, it might not be a problem, because it's the same user sending the password.
+
+But if we use the same model for another *path operation*, we could be sending our user's passwords to every client.
!!! danger
- 永远不要存储用户的明文密码,也不要在响应中发送密码。
+ Never store the plain password of a user or send it in a response like this, unless you know all the caveats and you know what you are doing.
-## 添加输出模型
+## Add an output model
-相反,我们可以创建一个有明文密码的输入模型和一个没有明文密码的输出模型:
+We can instead create an input model with the plaintext password and an output model without it:
-```Python hl_lines="9 11 16"
-{!../../../docs_src/response_model/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="9 11 16"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11 16"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
+Here, even though our *path operation function* is returning the same input user that contains the password:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
+...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
+
+So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
+
+### `response_model` or Return Type
+
+In this case, because the two models are different, if we annotated the function return type as `UserOut`, the editor and tools would complain that we are returning an invalid type, as those are different classes.
+
+That's why in this example we have to declare it in the `response_model` parameter.
+
+...but continue reading below to see how to overcome that.
+
+## Return Type and Data Filtering
+
+Let's continue from the previous example. We wanted to **annotate the function with one type** but return something that includes **more data**.
+
+We want FastAPI to keep **filtering** the data using the response model.
+
+In the previous example, because the classes were different, we had to use the `response_model` parameter. But that also means that we don't get the support from the editor and tools checking the function return type.
-这样,即便我们的*路径操作函数*将会返回包含密码的相同输入用户:
+But in most of the cases where we need to do something like this, we want the model just to **filter/remove** some of the data as in this example.
-```Python hl_lines="24"
-{!../../../docs_src/response_model/tutorial003.py!}
+And in those cases, we can use classes and inheritance to take advantage of function **type annotations** to get better support in the editor and tools, and still get the FastAPI **data filtering**.
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="7-10 13-14 18"
+ {!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-13 15-16 20"
+ {!> ../../../docs_src/response_model/tutorial003_01.py!}
+ ```
+
+With this, we get tooling support, from editors and mypy as this code is correct in terms of types, but we also get the data filtering from FastAPI.
+
+How does this work? Let's check that out. 🤓
+
+### Type Annotations and Tooling
+
+First let's see how editors, mypy and other tools would see this.
+
+`BaseUser` has the base fields. Then `UserIn` inherits from `BaseUser` and adds the `password` field, so, it will include all the fields from both models.
+
+We annotate the function return type as `BaseUser`, but we are actually returning a `UserIn` instance.
+
+The editor, mypy, and other tools won't complain about this because, in typing terms, `UserIn` is a subclass of `BaseUser`, which means it's a *valid* type when what is expected is anything that is a `BaseUser`.
+
+### FastAPI Data Filtering
+
+Now, for FastAPI, it will see the return type and make sure that what you return includes **only** the fields that are declared in the type.
+
+FastAPI does several things internally with Pydantic to make sure that those same rules of class inheritance are not used for the returned data filtering, otherwise you could end up returning much more data than what you expected.
+
+This way, you can get the best of both worlds: type annotations with **tooling support** and **data filtering**.
+
+## See it in the docs
+
+When you see the automatic docs, you can check that the input model and output model will both have their own JSON Schema:
+
+
+
+And both models will be used for the interactive API documentation:
+
+
+
+## Other Return Type Annotations
+
+There might be cases where you return something that is not a valid Pydantic field and you annotate it in the function, only to get the support provided by tooling (the editor, mypy, etc).
+
+### Return a Response Directly
+
+The most common case would be [returning a Response directly as explained later in the advanced docs](../advanced/response-directly.md){.internal-link target=_blank}.
+
+```Python hl_lines="8 10-11"
+{!> ../../../docs_src/response_model/tutorial003_02.py!}
```
-...我们已经将 `response_model` 声明为了不包含密码的 `UserOut` 模型:
+This simple case is handled automatically by FastAPI because the return type annotation is the class (or a subclass) of `Response`.
+
+And tools will also be happy because both `RedirectResponse` and `JSONResponse` are subclasses of `Response`, so the type annotation is correct.
+
+### Annotate a Response Subclass
-```Python hl_lines="22"
-{!../../../docs_src/response_model/tutorial003.py!}
+You can also use a subclass of `Response` in the type annotation:
+
+```Python hl_lines="8-9"
+{!> ../../../docs_src/response_model/tutorial003_03.py!}
```
-因此,**FastAPI** 将会负责过滤掉未在输出模型中声明的所有数据(使用 Pydantic)。
+This will also work because `RedirectResponse` is a subclass of `Response`, and FastAPI will automatically handle this simple case.
-## 在文档中查看
+### Invalid Return Type Annotations
-当你查看自动化文档时,你可以检查输入模型和输出模型是否都具有自己的 JSON Schema:
+But when you return some other arbitrary object that is not a valid Pydantic type (e.g. a database object) and you annotate it like that in the function, FastAPI will try to create a Pydantic response model from that type annotation, and will fail.
-
+The same would happen if you had something like a union between different types where one or more of them are not valid Pydantic types, for example this would fail 💥:
-并且两种模型都将在交互式 API 文档中使用:
+=== "Python 3.10+"
-
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
+ ```
-## 响应模型编码参数
+=== "Python 3.6+"
-你的响应模型可以具有默认值,例如:
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/response_model/tutorial003_04.py!}
+ ```
-```Python hl_lines="11 13-14"
-{!../../../docs_src/response_model/tutorial004.py!}
-```
+...this fails because the type annotation is not a Pydantic type and is not just a single `Response` class or subclass, it's a union (any of the two) between a `Response` and a `dict`.
-* `description: Union[str, None] = None` 具有默认值 `None`。
-* `tax: float = 10.5` 具有默认值 `10.5`.
-* `tags: List[str] = []` 具有一个空列表作为默认值: `[]`.
+### Disable Response Model
-但如果它们并没有存储实际的值,你可能想从结果中忽略它们的默认值。
+Continuing from the example above, you might not want to have the default data validation, documentation, filtering, etc. that is performed by FastAPI.
-举个例子,当你在 NoSQL 数据库中保存了具有许多可选属性的模型,但你又不想发送充满默认值的很长的 JSON 响应。
+But you might want to still keep the return type annotation in the function to get the support from tools like editors and type checkers (e.g. mypy).
-### 使用 `response_model_exclude_unset` 参数
+In this case, you can disable the response model generation by setting `response_model=None`:
-你可以设置*路径操作装饰器*的 `response_model_exclude_unset=True` 参数:
+=== "Python 3.10+"
-```Python hl_lines="24"
-{!../../../docs_src/response_model/tutorial004.py!}
-```
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
+ ```
-然后响应中将不会包含那些默认值,而是仅有实际设置的值。
+=== "Python 3.6+"
-因此,如果你向*路径操作*发送 ID 为 `foo` 的商品的请求,则响应(不包括默认值)将为:
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/response_model/tutorial003_05.py!}
+ ```
+
+This will make FastAPI skip the response model generation and that way you can have any return type annotations you need without it affecting your FastAPI application. 🤓
+
+## Response Model encoding parameters
+
+Your response model could have default values, like:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="9 11-12"
+ {!> ../../../docs_src/response_model/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11 13-14"
+ {!> ../../../docs_src/response_model/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11 13-14"
+ {!> ../../../docs_src/response_model/tutorial004.py!}
+ ```
+
+* `description: Union[str, None] = None` (or `str | None = None` in Python 3.10) has a default of `None`.
+* `tax: float = 10.5` has a default of `10.5`.
+* `tags: List[str] = []` as a default of an empty list: `[]`.
+
+but you might want to omit them from the result if they were not actually stored.
+
+For example, if you have models with many optional attributes in a NoSQL database, but you don't want to send very long JSON responses full of default values.
+
+### Use the `response_model_exclude_unset` parameter
+
+You can set the *path operation decorator* parameter `response_model_exclude_unset=True`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial004.py!}
+ ```
+
+and those default values won't be included in the response, only the values actually set.
+
+So, if you send a request to that *path operation* for the item with ID `foo`, the response (not including default values) will be:
```JSON
{
@@ -122,19 +378,19 @@ FastAPI 将使用此 `response_model` 来:
```
!!! info
- FastAPI 通过 Pydantic 模型的 `.dict()` 配合 该方法的 `exclude_unset` 参数 来实现此功能。
+ FastAPI uses Pydantic model's `.dict()` with its `exclude_unset` parameter to achieve this.
!!! info
- 你还可以使用:
+ You can also use:
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
- 参考 Pydantic 文档 中对 `exclude_defaults` 和 `exclude_none` 的描述。
+ as described in the Pydantic docs for `exclude_defaults` and `exclude_none`.
-#### 默认值字段有实际值的数据
+#### Data with values for fields with defaults
-但是,如果你的数据在具有默认值的模型字段中有实际的值,例如 ID 为 `bar` 的项:
+But if your data has values for the model's fields with default values, like the item with ID `bar`:
```Python hl_lines="3 5"
{
@@ -145,11 +401,11 @@ FastAPI 将使用此 `response_model` 来:
}
```
-这些值将包含在响应中。
+they will be included in the response.
-#### 具有与默认值相同值的数据
+#### Data with the same values as the defaults
-如果数据具有与默认值相同的值,例如 ID 为 `baz` 的项:
+If the data has the same values as the default ones, like the item with ID `baz`:
```Python hl_lines="3 5-6"
{
@@ -161,49 +417,65 @@ FastAPI 将使用此 `response_model` 来:
}
```
-即使 `description`、`tax` 和 `tags` 具有与默认值相同的值,FastAPI 足够聪明 (实际上是 Pydantic 足够聪明) 去认识到这一点,它们的值被显式地所设定(而不是取自默认值)。
+FastAPI is smart enough (actually, Pydantic is smart enough) to realize that, even though `description`, `tax`, and `tags` have the same values as the defaults, they were set explicitly (instead of taken from the defaults).
-因此,它们将包含在 JSON 响应中。
+So, they will be included in the JSON response.
!!! tip
- 请注意默认值可以是任何值,而不仅是`None`。
+ Notice that the default values can be anything, not only `None`.
- 它们可以是一个列表(`[]`),一个值为 `10.5`的 `float`,等等。
+ They can be a list (`[]`), a `float` of `10.5`, etc.
-### `response_model_include` 和 `response_model_exclude`
+### `response_model_include` and `response_model_exclude`
-你还可以使用*路径操作装饰器*的 `response_model_include` 和 `response_model_exclude` 参数。
+You can also use the *path operation decorator* parameters `response_model_include` and `response_model_exclude`.
-它们接收一个由属性名称 `str` 组成的 `set` 来包含(忽略其他的)或者排除(包含其他的)这些属性。
+They take a `set` of `str` with the name of the attributes to include (omitting the rest) or to exclude (including the rest).
-如果你只有一个 Pydantic 模型,并且想要从输出中移除一些数据,则可以使用这种快捷方法。
+This can be used as a quick shortcut if you have only one Pydantic model and want to remove some data from the output.
!!! tip
- 但是依然建议你使用上面提到的主意,使用多个类而不是这些参数。
+ But it is still recommended to use the ideas above, using multiple classes, instead of these parameters.
- 这是因为即使使用 `response_model_include` 或 `response_model_exclude` 来省略某些属性,在应用程序的 OpenAPI 定义(和文档)中生成的 JSON Schema 仍将是完整的模型。
+ This is because the JSON Schema generated in your app's OpenAPI (and the docs) will still be the one for the complete model, even if you use `response_model_include` or `response_model_exclude` to omit some attributes.
+
+ This also applies to `response_model_by_alias` that works similarly.
- 这也适用于作用类似的 `response_model_by_alias`。
+=== "Python 3.10+"
-```Python hl_lines="31 37"
-{!../../../docs_src/response_model/tutorial005.py!}
-```
+ ```Python hl_lines="29 35"
+ {!> ../../../docs_src/response_model/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="31 37"
+ {!> ../../../docs_src/response_model/tutorial005.py!}
+ ```
!!! tip
- `{"name", "description"}` 语法创建一个具有这两个值的 `set`。
+ The syntax `{"name", "description"}` creates a `set` with those two values.
- 等同于 `set(["name", "description"])`。
+ It is equivalent to `set(["name", "description"])`.
-#### 使用 `list` 而不是 `set`
+#### Using `list`s instead of `set`s
-如果你忘记使用 `set` 而是使用 `list` 或 `tuple`,FastAPI 仍会将其转换为 `set` 并且正常工作:
+If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will still convert it to a `set` and it will work correctly:
-```Python hl_lines="31 37"
-{!../../../docs_src/response_model/tutorial006.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="29 35"
+ {!> ../../../docs_src/response_model/tutorial006_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="31 37"
+ {!> ../../../docs_src/response_model/tutorial006.py!}
+ ```
-## 总结
+## Recap
-使用*路径操作装饰器*的 `response_model` 参数来定义响应模型,特别是确保私有数据被过滤掉。
+Use the *path operation decorator's* parameter `response_model` to define response models and especially to ensure private data is filtered out.
-使用 `response_model_exclude_unset` 来仅返回显式设定的值。
+Use `response_model_exclude_unset` to return only the values explicitly set.
From dade6ef2df8bacc5531d9c12ebd368c9fd16e49a Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:53 +0800
Subject: [PATCH 094/163] New translations response-status-code.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/response-status-code.md | 80 +++++++++----------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/docs/zh/docs/tutorial/response-status-code.md b/docs/zh/docs/tutorial/response-status-code.md
index 3578319423adc..8e26706e53d62 100644
--- a/docs/zh/docs/tutorial/response-status-code.md
+++ b/docs/zh/docs/tutorial/response-status-code.md
@@ -1,89 +1,89 @@
-# 响应状态码
+# Response Status Code
-与指定响应模型的方式相同,你也可以在以下任意的*路径操作*中使用 `status_code` 参数来声明用于响应的 HTTP 状态码:
+The same way you can specify a response model, you can also declare the HTTP status code used for the response with the parameter `status_code` in any of the *path operations*:
* `@app.get()`
* `@app.post()`
* `@app.put()`
* `@app.delete()`
-* 等等。
+* etc.
```Python hl_lines="6"
{!../../../docs_src/response_status_code/tutorial001.py!}
```
!!! note
- 注意,`status_code` 是「装饰器」方法(`get`,`post` 等)的一个参数。不像之前的所有参数和请求体,它不属于*路径操作函数*。
+ Notice that `status_code` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
-`status_code` 参数接收一个表示 HTTP 状态码的数字。
+The `status_code` parameter receives a number with the HTTP status code.
!!! info
- `status_code` 也能够接收一个 `IntEnum` 类型,比如 Python 的 `http.HTTPStatus`。
+ `status_code` can alternatively also receive an `IntEnum`, such as Python's `http.HTTPStatus`.
-它将会:
+It will:
-* 在响应中返回该状态码。
-* 在 OpenAPI 模式中(以及在用户界面中)将其记录为:
+* Return that status code in the response.
+* Document it as such in the OpenAPI schema (and so, in the user interfaces):
-
+
!!! note
- 一些响应状态码(请参阅下一部分)表示响应没有响应体。
+ Some response codes (see the next section) indicate that the response does not have a body.
- FastAPI 知道这一点,并将生成表明没有响应体的 OpenAPI 文档。
+ FastAPI knows this, and will produce OpenAPI docs that state there is no response body.
-## 关于 HTTP 状态码
+## About HTTP status codes
!!! note
- 如果你已经了解什么是 HTTP 状态码,请跳到下一部分。
+ If you already know what HTTP status codes are, skip to the next section.
-在 HTTP 协议中,你将发送 3 位数的数字状态码作为响应的一部分。
+In HTTP, you send a numeric status code of 3 digits as part of the response.
-这些状态码有一个识别它们的关联名称,但是重要的还是数字。
+These status codes have a name associated to recognize them, but the important part is the number.
-简而言之:
+In short:
-* `100` 及以上状态码用于「消息」响应。你很少直接使用它们。具有这些状态代码的响应不能带有响应体。
-* **`200`** 及以上状态码用于「成功」响应。这些是你最常使用的。
- * `200` 是默认状态代码,它表示一切「正常」。
- * 另一个例子会是 `201`,「已创建」。它通常在数据库中创建了一条新记录后使用。
- * 一个特殊的例子是 `204`,「无内容」。此响应在没有内容返回给客户端时使用,因此该响应不能包含响应体。
-* **`300`** 及以上状态码用于「重定向」。具有这些状态码的响应可能有或者可能没有响应体,但 `304`「未修改」是个例外,该响应不得含有响应体。
-* **`400`** 及以上状态码用于「客户端错误」响应。这些可能是你第二常使用的类型。
- * 一个例子是 `404`,用于「未找到」响应。
- * 对于来自客户端的一般错误,你可以只使用 `400`。
-* `500` 及以上状态码用于服务器端错误。你几乎永远不会直接使用它们。当你的应用程序代码或服务器中的某些部分出现问题时,它将自动返回这些状态代码之一。
+* `100` and above are for "Information". You rarely use them directly. Responses with these status codes cannot have a body.
+* **`200`** and above are for "Successful" responses. These are the ones you would use the most.
+ * `200` is the default status code, which means everything was "OK".
+ * Another example would be `201`, "Created". It is commonly used after creating a new record in the database.
+ * A special case is `204`, "No Content". This response is used when there is no content to return to the client, and so the response must not have a body.
+* **`300`** and above are for "Redirection". Responses with these status codes may or may not have a body, except for `304`, "Not Modified", which must not have one.
+* **`400`** and above are for "Client error" responses. These are the second type you would probably use the most.
+ * An example is `404`, for a "Not Found" response.
+ * For generic errors from the client, you can just use `400`.
+* `500` and above are for server errors. You almost never use them directly. When something goes wrong at some part in your application code, or server, it will automatically return one of these status codes.
!!! tip
- 要了解有关每个状态代码以及适用场景的更多信息,请查看 MDN 关于 HTTP 状态码的文档。
+ To know more about each status code and which code is for what, check the MDN documentation about HTTP status codes.
-## 记住名称的捷径
+## Shortcut to remember the names
-让我们再次看看之前的例子:
+Let's see the previous example again:
```Python hl_lines="6"
{!../../../docs_src/response_status_code/tutorial001.py!}
```
-`201` 是表示「已创建」的状态码。
+`201` is the status code for "Created".
-但是你不必去记住每个代码的含义。
+But you don't have to memorize what each of these codes mean.
-你可以使用来自 `fastapi.status` 的便捷变量。
+You can use the convenience variables from `fastapi.status`.
```Python hl_lines="1 6"
{!../../../docs_src/response_status_code/tutorial002.py!}
```
-它们只是一种便捷方式,它们具有同样的数字代码,但是这样使用你就可以使用编辑器的自动补全功能来查找它们:
+They are just a convenience, they hold the same number, but that way you can use the editor's autocomplete to find them:
-
+
-!!! note "技术细节"
- 你也可以使用 `from starlette import status`。
+!!! note "Technical Details"
+ You could also use `from starlette import status`.
- 为了给你(即开发者)提供方便,**FastAPI** 提供了与 `starlette.status` 完全相同的 `fastapi.status`。但它直接来自于 Starlette。
+ **FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
-## 更改默认状态码
+## Changing the default
-稍后,在[高级用户指南](../advanced/response-change-status-code.md){.internal-link target=_blank}中你将了解如何返回与在此声明的默认状态码不同的状态码。
+Later, in the [Advanced User Guide](../advanced/response-change-status-code.md){.internal-link target=_blank}, you will see how to return a different status code than the default you are declaring here.
From 7bcf2c38091ca8a6ce79318f74d37d1f2d9fc7c4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:54 +0800
Subject: [PATCH 095/163] New translations schema-extra-example.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/schema-extra-example.md | 263 +++++++++++++++---
1 file changed, 231 insertions(+), 32 deletions(-)
diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md
index 8f5fbfe70bbb5..9b24aa3702e80 100644
--- a/docs/zh/docs/tutorial/schema-extra-example.md
+++ b/docs/zh/docs/tutorial/schema-extra-example.md
@@ -1,58 +1,257 @@
-# 模式的额外信息 - 例子
+# Declare Request Example Data
-您可以在JSON模式中定义额外的信息。
+You can declare examples of the data your app can receive.
-一个常见的用例是添加一个将在文档中显示的`example`。
+Here are several ways to do it.
-有几种方法可以声明额外的 JSON 模式信息。
+## Extra JSON Schema data in Pydantic models
-## Pydantic `schema_extra`
+You can declare `examples` for a Pydantic model that will be added to the generated JSON Schema.
-您可以使用 `Config` 和 `schema_extra` 为Pydantic模型声明一个示例,如Pydantic 文档:定制 Schema 中所述:
+=== "Python 3.10+ Pydantic v2"
-```Python hl_lines="15-23"
-{!../../../docs_src/schema_extra_example/tutorial001.py!}
-```
+ ```Python hl_lines="13-24"
+ {!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
+ ```
-这些额外的信息将按原样添加到输出的JSON模式中。
+=== "Python 3.10+ Pydantic v1"
-## `Field` 的附加参数
+ ```Python hl_lines="13-23"
+ {!> ../../../docs_src/schema_extra_example/tutorial001_py310_pv1.py!}
+ ```
-在 `Field`, `Path`, `Query`, `Body` 和其他你之后将会看到的工厂函数,你可以为JSON 模式声明额外信息,你也可以通过给工厂函数传递其他的任意参数来给JSON 模式声明额外信息,比如增加 `example`:
+=== "Python 3.6+ Pydantic v2"
-```Python hl_lines="4 10-13"
-{!../../../docs_src/schema_extra_example/tutorial002.py!}
-```
+ ```Python hl_lines="15-26"
+ {!> ../../../docs_src/schema_extra_example/tutorial001.py!}
+ ```
+
+=== "Python 3.6+ Pydantic v1"
+
+ ```Python hl_lines="15-25"
+ {!> ../../../docs_src/schema_extra_example/tutorial001_pv1.py!}
+ ```
+
+That extra info will be added as-is to the output **JSON Schema** for that model, and it will be used in the API docs.
+
+=== "Pydantic v2"
+
+ In Pydantic version 2, you would use the attribute `model_config`, that takes a `dict` as described in Pydantic's docs: Model Config.
+
+ You can set `"json_schema_extra"` with a `dict` containing any additonal data you would like to show up in the generated JSON Schema, including `examples`.
+
+=== "Pydantic v1"
+
+ In Pydantic version 1, you would use an internal class `Config` and `schema_extra`, as described in Pydantic's docs: Schema customization.
+
+ You can set `schema_extra` with a `dict` containing any additonal data you would like to show up in the generated JSON Schema, including `examples`.
+
+!!! tip
+ You could use the same technique to extend the JSON Schema and add your own custom extra info.
+
+ For example you could use it to add metadata for a frontend user interface, etc.
+
+!!! info
+ OpenAPI 3.1.0 (used since FastAPI 0.99.0) added support for `examples`, which is part of the **JSON Schema** standard.
+
+ Before that, it only supported the keyword `example` with a single example. That is still supported by OpenAPI 3.1.0, but is deprecated and is not part of the JSON Schema standard. So you are encouraged to migrate `example` to `examples`. 🤓
+
+ You can read more at the end of this page.
+
+## `Field` additional arguments
+
+When using `Field()` with Pydantic models, you can also declare additional `examples`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="2 8-11"
+ {!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 10-13"
+ {!> ../../../docs_src/schema_extra_example/tutorial002.py!}
+ ```
+
+## `examples` in OpenAPI
+
+When using any of:
+
+* `Path()`
+* `Query()`
+* `Header()`
+* `Cookie()`
+* `Body()`
+* `Form()`
+* `File()`
+
+you can also declare a group of `examples` with additional information that will be added to **OpenAPI**.
+
+### `Body` with `examples`
+
+Here we pass `examples` containing one example of the data expected in `Body()`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="22-29"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="22-29"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="23-30"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="18-25"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="20-27"
+ {!> ../../../docs_src/schema_extra_example/tutorial003.py!}
+ ```
+
+### Example in the docs UI
+
+With any of the methods above it would look like this in the `/docs`:
+
+
+
+### `Body` with multiple `examples`
+
+You can of course also pass multiple `examples`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="23-38"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="23-38"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24-39"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19-34"
+ {!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="21-36"
+ {!> ../../../docs_src/schema_extra_example/tutorial004.py!}
+ ```
+
+### Examples in the docs UI
+
+With `examples` added to `Body()` the `/docs` would look like:
+
+
+
+## Technical Details
+
+!!! tip
+ If you are already using **FastAPI** version **0.99.0 or above**, you can probably **skip** these details.
+
+ They are more relevant for older versions, before OpenAPI 3.1.0 was available.
+
+ You can consider this a brief OpenAPI and JSON Schema **history lesson**. 🤓
!!! warning
- 请记住,传递的那些额外参数不会添加任何验证,只会添加注释,用于文档的目的。
+ These are very technical details about the standards **JSON Schema** and **OpenAPI**.
+
+ If the ideas above already work for you, that might be enough, and you probably don't need these details, feel free to skip them.
+
+Before OpenAPI 3.1.0, OpenAPI used an older and modified version of **JSON Schema**.
+
+JSON Schema didn't have `examples`, so OpenAPI added it's own `example` field to its own modified version.
+
+OpenAPI also added `example` and `examples` fields to other parts of the specification:
+
+* `Parameter Object` (in the specification) that was used by FastAPI's:
+ * `Path()`
+ * `Query()`
+ * `Header()`
+ * `Cookie()`
+* `Request Body Object`, in the field `content`, on the `Media Type Object` (in the specification) that was used by FastAPI's:
+ * `Body()`
+ * `File()`
+ * `Form()`
+
+### OpenAPI's `examples` field
+
+The shape of this field `examples` from OpenAPI is a `dict` with **multiple examples**, each with extra information that will be added to **OpenAPI** too.
+
+The keys of the `dict` identify each example, and each value is another `dict`.
+
+Each specific example `dict` in the `examples` can contain:
+
+* `summary`: Short description for the example.
+* `description`: A long description that can contain Markdown text.
+* `value`: This is the actual example shown, e.g. a `dict`.
+* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`.
+
+This applies to those other parts of the OpenAPI specification apart from JSON Schema.
+
+### JSON Schema's `examples` field
-## `Body` 额外参数
+But then JSON Schema added an `examples` field to a new version of the specification.
-你可以通过传递额外信息给 `Field` 同样的方式操作`Path`, `Query`, `Body`等。
+And then the new OpenAPI 3.1.0 was based on the latest version (JSON Schema 2020-12) that included this new field `examples`.
-比如,你可以将请求体的一个 `example` 传递给 `Body`:
+And now this new `examples` field takes precedence over the old single (and custom) `example` field, that is now deprecated.
-```Python hl_lines="20-25"
-{!../../../docs_src/schema_extra_example/tutorial003.py!}
-```
+This new `examples` field in JSON Schema is **just a `list`** of examples, not a dict with extra metadata as in the other places in OpenAPI (described above).
-## 文档 UI 中的例子
+!!! info
+ Even after OpenAPI 3.1.0 was released with this new simpler integration with JSON Schema, for a while, Swagger UI, the tool that provides the automatic docs, didn't support OpenAPI 3.1.0 (it does since version 5.0.0 🎉).
-使用上面的任何方法,它在 `/docs` 中看起来都是这样的:
+ Because of that, versions of FastAPI previous to 0.99.0 still used versions of OpenAPI lower than 3.1.0.
-
+### Pydantic and FastAPI `examples`
-## 技术细节
+When you add `examples` inside of a Pydantic model, using `schema_extra` or `Field(examples=["something"])` that example is added to the **JSON Schema** for that Pydantic model.
-关于 `example` 和 `examples`...
+And that **JSON Schema** of the Pydantic model is included in the **OpenAPI** of your API, and then it's used in the docs UI.
-JSON Schema在最新的一个版本中定义了一个字段 `examples` ,但是 OpenAPI 基于之前的一个旧版JSON Schema,并没有 `examples`.
+In versions of FastAPI before 0.99.0 (0.99.0 and above use the newer OpenAPI 3.1.0) when you used `example` or `examples` with any of the other utilities (`Query()`, `Body()`, etc.) those examples were not added to the JSON Schema that describes that data (not even to OpenAPI's own version of JSON Schema), they were added directly to the *path operation* declaration in OpenAPI (outside the parts of OpenAPI that use JSON Schema).
-所以 OpenAPI为了相似的目的定义了自己的 `example` (使用 `example`, 而不是 `examples`), 这也是文档 UI 所使用的 (使用 Swagger UI).
+But now that FastAPI 0.99.0 and above uses OpenAPI 3.1.0, that uses JSON Schema 2020-12, and Swagger UI 5.0.0 and above, everything is more consistent and the examples are included in JSON Schema.
-所以,虽然 `example` 不是JSON Schema的一部分,但它是OpenAPI的一部分,这将被文档UI使用。
+### Summary
-## 其他信息
+I used to say I didn't like history that much... and look at me now giving "tech history" lessons. 😅
-同样的方法,你可以添加你自己的额外信息,这些信息将被添加到每个模型的JSON模式中,例如定制前端用户界面,等等。
+In short, **upgrade to FastAPI 0.99.0 or above**, and things are much **simpler, consistent, and intuitive**, and you don't have to know all these historic details. 😎
From ff82fa21ba2d0180f748e851f6e361b459251b33 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:55 +0800
Subject: [PATCH 096/163] New translations first-steps.md (Chinese Simplified)
---
docs/zh/docs/tutorial/security/first-steps.md | 243 +++++++++++-------
1 file changed, 144 insertions(+), 99 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md
index 86c3320ce1e9e..25c20b8df21d6 100644
--- a/docs/zh/docs/tutorial/security/first-steps.md
+++ b/docs/zh/docs/tutorial/security/first-steps.md
@@ -1,40 +1,57 @@
-# 安全 - 第一步
+# Security - First Steps
-假设**后端** API 在某个域。
+Let's imagine that you have your **backend** API in some domain.
-**前端**在另一个域,或(移动应用中)在同一个域的不同路径下。
+And you have a **frontend** in another domain or in a different path of the same domain (or in a mobile application).
-并且,前端要使用后端的 **username** 与 **password** 验证用户身份。
+And you want to have a way for the frontend to authenticate with the backend, using a **username** and **password**.
-固然,**FastAPI** 支持 **OAuth2** 身份验证。
+We can use **OAuth2** to build that with **FastAPI**.
-但为了节省开发者的时间,不要只为了查找很少的内容,不得不阅读冗长的规范文档。
+But let's save you the time of reading the full long specification just to find those little pieces of information you need.
-我们建议使用 **FastAPI** 的安全工具。
+Let's use the tools provided by **FastAPI** to handle security.
-## 概览
+## How it looks
-首先,看看下面的代码是怎么运行的,然后再回过头来了解其背后的原理。
+Let's first just use the code and see how it works, and then we'll come back to understand what's happening.
-## 创建 `main.py`
+## Create `main.py`
-把下面的示例代码复制到 `main.py`:
+Copy the example in a file `main.py`:
-```Python
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
-## 运行
+ ```Python
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
-!!! info "说明"
+=== "Python 3.6+ non-Annotated"
- 先安装 `python-multipart`。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- 安装命令: `pip install python-multipart`。
+ ```Python
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
- 这是因为 **OAuth2** 使用**表单数据**发送 `username` 与 `password`。
-用下面的命令运行该示例:
+## Run it
+
+!!! info
+ First install `python-multipart`.
+
+ E.g. `pip install python-multipart`.
+
+ This is because **OAuth2** uses "form data" for sending the `username` and `password`.
+
+Run the example with:
+You will see something like this:
-!!! check "Authorize 按钮!"
+
- 页面右上角出现了一个「**Authorize**」按钮。
+!!! check "Authorize button!"
+ You already have a shiny new "Authorize" button.
- *路径操作*的右上角也出现了一个可以点击的小锁图标。
+ And your *path operation* has a little lock in the top-right corner that you can click.
-点击 **Authorize** 按钮,弹出授权表单,输入 `username` 与 `password` 及其它可选字段:
+And if you click it, you have a little authorization form to type a `username` and `password` (and other optional fields):
-
+
-!!! note "笔记"
+!!! note
+ It doesn't matter what you type in the form, it won't work yet. But we'll get there.
- 目前,在表单中输入内容不会有任何反应,后文会介绍相关内容。
+This is of course not the frontend for the final users, but it's a great automatic tool to document interactively all your API.
-虽然此文档不是给前端最终用户使用的,但这个自动工具非常实用,可在文档中与所有 API 交互。
+It can be used by the frontend team (that can also be yourself).
-前端团队(可能就是开发者本人)可以使用本工具。
+It can be used by third party applications and systems.
-第三方应用与系统也可以调用本工具。
+And it can also be used by yourself, to debug, check and test the same application.
-开发者也可以用它来调试、检查、测试应用。
+## The `password` flow
-## 密码流
+Now let's go back a bit and understand what is all that.
-现在,我们回过头来介绍这段代码的原理。
+The `password` "flow" is one of the ways ("flows") defined in OAuth2, to handle security and authentication.
-`Password` **流**是 OAuth2 定义的,用于处理安全与身份验证的方式(**流**)。
+OAuth2 was designed so that the backend or API could be independent of the server that authenticates the user.
-OAuth2 的设计目标是为了让后端或 API 独立于服务器验证用户身份。
+But in this case, the same **FastAPI** application will handle the API and the authentication.
-但在本例中,**FastAPI** 应用会处理 API 与身份验证。
+So, let's review it from that simplified point of view:
-下面,我们来看一下简化的运行流程:
+* The user types the `username` and `password` in the frontend, and hits `Enter`.
+* The frontend (running in the user's browser) sends that `username` and `password` to a specific URL in our API (declared with `tokenUrl="token"`).
+* The API checks that `username` and `password`, and responds with a "token" (we haven't implemented any of this yet).
+ * A "token" is just a string with some content that we can use later to verify this user.
+ * Normally, a token is set to expire after some time.
+ * So, the user will have to log in again at some point later.
+ * And if the token is stolen, the risk is less. It is not like a permanent key that will work forever (in most of the cases).
+* The frontend stores that token temporarily somewhere.
+* The user clicks in the frontend to go to another section of the frontend web app.
+* The frontend needs to fetch some more data from the API.
+ * But it needs authentication for that specific endpoint.
+ * So, to authenticate with our API, it sends a header `Authorization` with a value of `Bearer` plus the token.
+ * If the token contains `foobar`, the content of the `Authorization` header would be: `Bearer foobar`.
-- 用户在前端输入 `username` 与`password`,并点击**回车**
-- (用户浏览器中运行的)前端把 `username` 与`password` 发送至 API 中指定的 URL(使用 `tokenUrl="token"` 声明)
-- API 检查 `username` 与`password`,并用令牌(`Token`) 响应(暂未实现此功能):
- - 令牌只是用于验证用户的字符串
- - 一般来说,令牌会在一段时间后过期
- - 过时后,用户要再次登录
- - 这样一来,就算令牌被人窃取,风险也较低。因为它与永久密钥不同,**在绝大多数情况下**不会长期有效
-- 前端临时将令牌存储在某个位置
-- 用户点击前端,前往前端应用的其它部件
-- 前端需要从 API 中提取更多数据:
- - 为指定的端点(Endpoint)进行身份验证
- - 因此,用 API 验证身份时,要发送值为 `Bearer` + 令牌的请求头 `Authorization`
- - 假如令牌为 `foobar`,`Authorization` 请求头就是: `Bearer foobar`
+## **FastAPI**'s `OAuth2PasswordBearer`
-## **FastAPI** 的 `OAuth2PasswordBearer`
+**FastAPI** provides several tools, at different levels of abstraction, to implement these security features.
-**FastAPI** 提供了不同抽象级别的安全工具。
+In this example we are going to use **OAuth2**, with the **Password** flow, using a **Bearer** token. We do that using the `OAuth2PasswordBearer` class.
-本例使用 **OAuth2** 的 **Password** 流以及 **Bearer** 令牌(`Token`)。为此要使用 `OAuth2PasswordBearer` 类。
+!!! info
+ A "bearer" token is not the only option.
-!!! info "说明"
+ But it's the best one for our use case.
+
+ And it might be the best for most use cases, unless you are an OAuth2 expert and know exactly why there's another option that suits better your needs.
+
+ In that case, **FastAPI** also provides you with the tools to build it.
- `Bearer` 令牌不是唯一的选择。
+When we create an instance of the `OAuth2PasswordBearer` class we pass in the `tokenUrl` parameter. This parameter contains the URL that the client (the frontend running in the user's browser) will use to send the `username` and `password` in order to get a token.
- 但它是最适合这个用例的方案。
+=== "Python 3.9+"
- 甚至可以说,它是适用于绝大多数用例的最佳方案,除非您是 OAuth2 的专家,知道为什么其它方案更合适。
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
- 本例中,**FastAPI** 还提供了构建工具。
+=== "Python 3.6+"
-创建 `OAuth2PasswordBearer` 的类实例时,要传递 `tokenUrl` 参数。该参数包含客户端(用户浏览器中运行的前端) 的 URL,用于发送 `username` 与 `password`,并获取令牌。
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
-```Python hl_lines="6"
-{!../../../docs_src/security/tutorial001.py!}
-```
-
-!!! tip "提示"
+=== "Python 3.6+ non-Annotated"
- 在此,`tokenUrl="token"` 指向的是暂未创建的相对 URL `token`。这个相对 URL 相当于 `./token`。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- 因为使用的是相对 URL,如果 API 位于 `https://example.com/`,则指向 `https://example.com/token`。但如果 API 位于 `https://example.com/api/v1/`,它指向的就是`https://example.com/api/v1/token`。
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
- 使用相对 URL 非常重要,可以确保应用在遇到[使用代理](../../advanced/behind-a-proxy.md){.internal-link target=_blank}这样的高级用例时,也能正常运行。
+!!! tip
+ Here `tokenUrl="token"` refers to a relative URL `token` that we haven't created yet. As it's a relative URL, it's equivalent to `./token`.
-该参数不会创建端点或*路径操作*,但会声明客户端用来获取令牌的 URL `/token` 。此信息用于 OpenAPI 及 API 文档。
+ Because we are using a relative URL, if your API was located at `https://example.com/`, then it would refer to `https://example.com/token`. But if your API was located at `https://example.com/api/v1/`, then it would refer to `https://example.com/api/v1/token`.
+
+ Using a relative URL is important to make sure your application keeps working even in an advanced use case like [Behind a Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}.
-接下来,学习如何创建实际的路径操作。
+This parameter doesn't create that endpoint / *path operation*, but declares that the URL `/token` will be the one that the client should use to get the token. That information is used in OpenAPI, and then in the interactive API documentation systems.
-!!! info "说明"
+We will soon also create the actual path operation.
- 严苛的 **Pythonista** 可能不喜欢用 `tokenUrl` 这种命名风格代替 `token_url`。
+!!! info
+ If you are a very strict "Pythonista" you might dislike the style of the parameter name `tokenUrl` instead of `token_url`.
- 这种命名方式是因为要使用与 OpenAPI 规范中相同的名字。以便在深入校验安全方案时,能通过复制粘贴查找更多相关信息。
+ That's because it is using the same name as in the OpenAPI spec. So that if you need to investigate more about any of these security schemes you can just copy and paste it to find more information about it.
-`oauth2_scheme` 变量是 `OAuth2PasswordBearer` 的实例,也是**可调用项**。
+The `oauth2_scheme` variable is an instance of `OAuth2PasswordBearer`, but it is also a "callable".
-以如下方式调用:
+It could be called as:
```Python
oauth2_scheme(some, parameters)
```
-因此,`Depends` 可以调用 `oauth2_scheme` 变量。
+So, it can be used with `Depends`.
-### 使用
+### Use it
-接下来,使用 `Depends` 把 `oauth2_scheme` 传入依赖项。
+Now you can pass that `oauth2_scheme` in a dependency with `Depends`.
-```Python hl_lines="10"
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-该依赖项使用字符串(`str`)接收*路径操作函数*的参数 `token` 。
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
-**FastAPI** 使用依赖项在 OpenAPI 概图(及 API 文档)中定义**安全方案**。
+This dependency will provide a `str` that is assigned to the parameter `token` of the *path operation function*.
-!!! info "技术细节"
+**FastAPI** will know that it can use this dependency to define a "security scheme" in the OpenAPI schema (and the automatic API docs).
- **FastAPI** 使用(在依赖项中声明的)类 `OAuth2PasswordBearer` 在 OpenAPI 中定义安全方案,这是因为它继承自 `fastapi.security.oauth2.OAuth2`,而该类又是继承自`fastapi.security.base.SecurityBase`。
+!!! info "Technical Details"
+ **FastAPI** will know that it can use the class `OAuth2PasswordBearer` (declared in a dependency) to define the security scheme in OpenAPI because it inherits from `fastapi.security.oauth2.OAuth2`, which in turn inherits from `fastapi.security.base.SecurityBase`.
- 所有与 OpenAPI(及 API 文档)集成的安全工具都继承自 `SecurityBase`, 这就是为什么 **FastAPI** 能把它们集成至 OpenAPI 的原因。
+ All the security utilities that integrate with OpenAPI (and the automatic API docs) inherit from `SecurityBase`, that's how **FastAPI** can know how to integrate them in OpenAPI.
-## 实现的操作
+## What it does
-FastAPI 校验请求中的 `Authorization` 请求头,核对请求头的值是不是由 `Bearer ` + 令牌组成, 并返回令牌字符串(`str`)。
+It will go and look in the request for that `Authorization` header, check if the value is `Bearer` plus some token, and will return the token as a `str`.
-如果没有找到 `Authorization` 请求头,或请求头的值不是 `Bearer ` + 令牌。FastAPI 直接返回 401 错误状态码(`UNAUTHORIZED`)。
+If it doesn't see an `Authorization` header, or the value doesn't have a `Bearer` token, it will respond with a 401 status code error (`UNAUTHORIZED`) directly.
-开发者不需要检查错误信息,查看令牌是否存在,只要该函数能够执行,函数中就会包含令牌字符串。
+You don't even have to check if the token exists to return an error. You can be sure that if your function is executed, it will have a `str` in that token.
-正如下图所示,API 文档已经包含了这项功能:
+You can try it already in the interactive docs:
-
+
-目前,暂时还没有实现验证令牌是否有效的功能,不过后文很快就会介绍的。
+We are not verifying the validity of the token yet, but that's a start already.
-## 小结
+## Recap
-看到了吧,只要多写三四行代码,就可以添加基础的安全表单。
+So, in just 3 or 4 extra lines, you already have some primitive form of security.
From 713063ea0b1c7ddabf826e154af4afd2976e924f Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:56 +0800
Subject: [PATCH 097/163] New translations get-current-user.md (Chinese
Simplified)
---
.../tutorial/security/get-current-user.md | 296 ++++++++++++++----
1 file changed, 235 insertions(+), 61 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/get-current-user.md b/docs/zh/docs/tutorial/security/get-current-user.md
index 477baec3afbf4..1a8c5d9a8d8fd 100644
--- a/docs/zh/docs/tutorial/security/get-current-user.md
+++ b/docs/zh/docs/tutorial/security/get-current-user.md
@@ -1,114 +1,288 @@
-# 获取当前用户
+# Get Current User
-在上一章节中,(基于依赖项注入系统的)安全系统向*路径操作函数*提供了一个 `str` 类型的 `token`:
+In the previous chapter the security system (which is based on the dependency injection system) was giving the *path operation function* a `token` as a `str`:
-```Python hl_lines="10"
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
-但这还不是很实用。
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
-让我们来使它返回当前用户给我们。
+=== "Python 3.6+"
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
-## 创建一个用户模型
+=== "Python 3.6+ non-Annotated"
-首先,让我们来创建一个用户 Pydantic 模型。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-与使用 Pydantic 声明请求体的方式相同,我们可以在其他任何地方使用它:
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
-```Python hl_lines="5 12-16"
-{!../../../docs_src/security/tutorial002.py!}
-```
+But that is still not that useful.
-## 创建一个 `get_current_user` 依赖项
+Let's make it give us the current user.
-让我们来创建一个 `get_current_user` 依赖项。
+## Create a user model
-还记得依赖项可以有子依赖项吗?
+First, let's create a Pydantic user model.
-`get_current_user` 将具有一个我们之前所创建的同一个 `oauth2_scheme` 作为依赖项。
+The same way we use Pydantic to declare bodies, we can use it anywhere else:
-与我们之前直接在路径操作中所做的相同,我们新的依赖项 `get_current_user` 将从子依赖项 `oauth2_scheme` 中接收一个 `str` 类型的 `token`:
+=== "Python 3.10+"
-```Python hl_lines="25"
-{!../../../docs_src/security/tutorial002.py!}
-```
+ ```Python hl_lines="5 12-16"
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
+ ```
-## 获取用户
+=== "Python 3.9+"
-`get_current_user` 将使用我们创建的(伪)工具函数,该函数接收 `str` 类型的令牌并返回我们的 Pydantic `User` 模型:
+ ```Python hl_lines="5 12-16"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
-```Python hl_lines="19-22 26-27"
-{!../../../docs_src/security/tutorial002.py!}
-```
+=== "Python 3.6+"
-## 注入当前用户
+ ```Python hl_lines="5 13-17"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
-因此现在我们可以在*路径操作*中使用 `get_current_user` 作为 `Depends` 了:
+=== "Python 3.10+ non-Annotated"
-```Python hl_lines="31"
-{!../../../docs_src/security/tutorial002.py!}
-```
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-注意我们将 `current_user` 的类型声明为 Pydantic 模型 `User`。
+ ```Python hl_lines="3 10-14"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
-这将帮助我们在函数内部使用所有的代码补全和类型检查。
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="5 12-16"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+## Create a `get_current_user` dependency
+
+Let's create a dependency `get_current_user`.
+
+Remember that dependencies can have sub-dependencies?
+
+`get_current_user` will have a dependency with the same `oauth2_scheme` we created before.
+
+The same as we were doing before in the *path operation* directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="26"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+## Get the user
+
+`get_current_user` will use a (fake) utility function we created, that takes a token as a `str` and returns our Pydantic `User` model:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="19-22 26-27"
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="19-22 26-27"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20-23 27-28"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="17-20 24-25"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="19-22 26-27"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+## Inject the current user
+
+So now we can use the same `Depends` with our `get_current_user` in the *path operation*:
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="31"
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="31"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="32"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="29"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="31"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
+
+Notice that we declare the type of `current_user` as the Pydantic model `User`.
+
+This will help us inside of the function with all the completion and type checks.
!!! tip
- 你可能还记得请求体也是使用 Pydantic 模型来声明的。
+ You might remember that request bodies are also declared with Pydantic models.
- 在这里 **FastAPI** 不会搞混,因为你正在使用的是 `Depends`。
+ Here **FastAPI** won't get confused because you are using `Depends`.
!!! check
- 这种依赖系统的设计方式使我们可以拥有不同的依赖项(不同的「可依赖类型」),并且它们都返回一个 `User` 模型。
+ The way this dependency system is designed allows us to have different dependencies (different "dependables") that all return a `User` model.
+
+ We are not restricted to having only one dependency that can return that type of data.
+
+## Other models
+
+You can now get the current user directly in the *path operation functions* and deal with the security mechanisms at the **Dependency Injection** level, using `Depends`.
+
+And you can use any model or data for the security requirements (in this case, a Pydantic model `User`).
+
+But you are not restricted to using some specific data model, class or type.
+
+Do you want to have an `id` and `email` and not have any `username` in your model? Sure. You can use these same tools.
+
+Do you want to just have a `str`? Or just a `dict`? Or a database class model instance directly? It all works the same way.
+
+You actually don't have users that log in to your application but robots, bots, or other systems, that have just an access token? Again, it all works the same.
+
+Just use any kind of model, any kind of class, any kind of database that you need for your application. **FastAPI** has you covered with the dependency injection system.
- 我们并未被局限于只能有一个返回该类型数据的依赖项。
+## Code size
+This example might seem verbose. Have in mind that we are mixing security, data models, utility functions and *path operations* in the same file.
-## 其他模型
+But here's the key point.
-现在你可以直接在*路径操作函数*中获取当前用户,并使用 `Depends` 在**依赖注入**级别处理安全性机制。
+The security and dependency injection stuff is written once.
-你可以使用任何模型或数据来满足安全性要求(在这个示例中,使用的是 Pydantic 模型 `User`)。
+And you can make it as complex as you want. And still, have it written only once, in a single place. With all the flexibility.
-但是你并未被限制只能使用某些特定的数据模型,类或类型。
+But you can have thousands of endpoints (*path operations*) using the same security system.
-你想要在模型中使用 `id` 和 `email` 而不使用任何的 `username`?当然可以。你可以同样地使用这些工具。
+And all of them (or any portion of them that you want) can take the advantage of re-using these dependencies or any other dependencies you create.
-你只想要一个 `str`?或者仅仅一个 `dict`?还是直接一个数据库模型类的实例?它们的工作方式都是一样的。
+And all these thousands of *path operations* can be as small as 3 lines:
-实际上你没有用户登录到你的应用程序,而是只拥有访问令牌的机器人,程序或其他系统?再一次,它们的工作方式也是一样的。
+=== "Python 3.10+"
-尽管去使用你的应用程序所需要的任何模型,任何类,任何数据库。**FastAPI** 通过依赖项注入系统都帮你搞定。
+ ```Python hl_lines="30-32"
+ {!> ../../../docs_src/security/tutorial002_an_py310.py!}
+ ```
+=== "Python 3.9+"
-## 代码体积
+ ```Python hl_lines="30-32"
+ {!> ../../../docs_src/security/tutorial002_an_py39.py!}
+ ```
-这个示例似乎看起来很冗长。考虑到我们在同一文件中混合了安全性,数据模型工具函数和路径操作等代码。
+=== "Python 3.6+"
-但关键的是。
+ ```Python hl_lines="31-33"
+ {!> ../../../docs_src/security/tutorial002_an.py!}
+ ```
-安全性和依赖项注入内容只需要编写一次。
+=== "Python 3.10+ non-Annotated"
-你可以根据需要使其变得很复杂。而且只需要在一个地方写一次。但仍然具备所有的灵活性。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-但是,你可以有无数个使用同一安全系统的端点(*路径操作*)。
+ ```Python hl_lines="28-30"
+ {!> ../../../docs_src/security/tutorial002_py310.py!}
+ ```
-所有(或所需的任何部分)的端点,都可以利用对这些或你创建的其他依赖项进行复用所带来的优势。
+=== "Python 3.6+ non-Annotated"
-所有的这无数个*路径操作*甚至可以小到只需 3 行代码:
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-```Python hl_lines="30-32"
-{!../../../docs_src/security/tutorial002.py!}
-```
+ ```Python hl_lines="30-32"
+ {!> ../../../docs_src/security/tutorial002.py!}
+ ```
-## 总结
+## Recap
-现在你可以直接在*路径操作函数*中获取当前用户。
+You can now get the current user directly in your *path operation function*.
-我们已经进行到一半了。
+We are already halfway there.
-我们只需要再为用户/客户端添加一个真正发送 `username` 和 `password` 的*路径操作*。
+We just need to add a *path operation* for the user/client to actually send the `username` and `password`.
-这些内容在下一章节。
+That comes next.
From b2e7ad0f95d18d4a65d87d1bb743edb9033fe52b Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:57 +0800
Subject: [PATCH 098/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/tutorial/security/index.md | 100 ++++++++++++------------
1 file changed, 50 insertions(+), 50 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/index.md b/docs/zh/docs/tutorial/security/index.md
index 0595f5f636129..9679cda427d6a 100644
--- a/docs/zh/docs/tutorial/security/index.md
+++ b/docs/zh/docs/tutorial/security/index.md
@@ -1,101 +1,101 @@
-# 安全性
+# Security
-有许多方法可以处理安全性、身份认证和授权等问题。
+There are many ways to handle security, authentication and authorization.
-而且这通常是一个复杂而「困难」的话题。
+And it normally is a complex and "difficult" topic.
-在许多框架和系统中,仅处理安全性和身份认证就会花费大量的精力和代码(在许多情况下,可能占编写的所有代码的 50% 或更多)。
+In many frameworks and systems just handling security and authentication takes a big amount of effort and code (in many cases it can be 50% or more of all the code written).
-**FastAPI** 提供了多种工具,可帮助你以标准的方式轻松、快速地处理**安全性**,而无需研究和学习所有的安全规范。
+**FastAPI** provides several tools to help you deal with **Security** easily, rapidly, in a standard way, without having to study and learn all the security specifications.
-但首先,让我们来看一些小的概念。
+But first, let's check some small concepts.
-## 没有时间?
+## In a hurry?
-如果你不关心这些术语,而只需要*立即*通过基于用户名和密码的身份认证来增加安全性,请跳转到下一章。
+If you don't care about any of these terms and you just need to add security with authentication based on username and password *right now*, skip to the next chapters.
## OAuth2
-OAuth2是一个规范,它定义了几种处理身份认证和授权的方法。
+OAuth2 is a specification that defines several ways to handle authentication and authorization.
-它是一个相当广泛的规范,涵盖了一些复杂的使用场景。
+It is quite an extensive specification and covers several complex use cases.
-它包括了使用「第三方」进行身份认证的方法。
+It includes ways to authenticate using a "third party".
-这就是所有带有「使用 Facebook,Google,Twitter,GitHub 登录」的系统背后所使用的机制。
+That's what all the systems with "login with Facebook, Google, Twitter, GitHub" use underneath.
### OAuth 1
-有一个 OAuth 1,它与 OAuth2 完全不同,并且更为复杂,因为它直接包含了有关如何加密通信的规范。
+There was an OAuth 1, which is very different from OAuth2, and more complex, as it included direct specifications on how to encrypt the communication.
-如今它已经不是很流行,没有被广泛使用了。
+It is not very popular or used nowadays.
-OAuth2 没有指定如何加密通信,它期望你为应用程序使用 HTTPS 进行通信。
+OAuth2 doesn't specify how to encrypt the communication, it expects you to have your application served with HTTPS.
!!! tip
- 在有关**部署**的章节中,你将了解如何使用 Traefik 和 Let's Encrypt 免费设置 HTTPS。
+ In the section about **deployment** you will see how to set up HTTPS for free, using Traefik and Let's Encrypt.
## OpenID Connect
-OpenID Connect 是另一个基于 **OAuth2** 的规范。
+OpenID Connect is another specification, based on **OAuth2**.
-它只是扩展了 OAuth2,并明确了一些在 OAuth2 中相对模糊的内容,以尝试使其更具互操作性。
+It just extends OAuth2 specifying some things that are relatively ambiguous in OAuth2, to try to make it more interoperable.
-例如,Google 登录使用 OpenID Connect(底层使用OAuth2)。
+For example, Google login uses OpenID Connect (which underneath uses OAuth2).
-但是 Facebook 登录不支持 OpenID Connect。它具有自己的 OAuth2 风格。
+But Facebook login doesn't support OpenID Connect. It has its own flavor of OAuth2.
-### OpenID(非「OpenID Connect」)
+### OpenID (not "OpenID Connect")
-还有一个「OpenID」规范。它试图解决与 **OpenID Connect** 相同的问题,但它不是基于 OAuth2。
+There was also an "OpenID" specification. That tried to solve the same thing as **OpenID Connect**, but was not based on OAuth2.
-因此,它是一个完整的附加系统。
+So, it was a complete additional system.
-如今它已经不是很流行,没有被广泛使用了。
+It is not very popular or used nowadays.
## OpenAPI
-OpenAPI(以前称为 Swagger)是用于构建 API 的开放规范(现已成为 Linux Foundation 的一部分)。
+OpenAPI (previously known as Swagger) is the open specification for building APIs (now part of the Linux Foundation).
-**FastAPI** 基于 **OpenAPI**。
+**FastAPI** is based on **OpenAPI**.
-这就是使多个自动交互式文档界面,代码生成等成为可能的原因。
+That's what makes it possible to have multiple automatic interactive documentation interfaces, code generation, etc.
-OpenAPI 有一种定义多个安全「方案」的方法。
+OpenAPI has a way to define multiple security "schemes".
-通过使用它们,你可以利用所有这些基于标准的工具,包括这些交互式文档系统。
+By using them, you can take advantage of all these standard-based tools, including these interactive documentation systems.
-OpenAPI 定义了以下安全方案:
+OpenAPI defines the following security schemes:
-* `apiKey`:一个特定于应用程序的密钥,可以来自:
- * 查询参数。
- * 请求头。
- * cookie。
-* `http`:标准的 HTTP 身份认证系统,包括:
- * `bearer`: 一个值为 `Bearer` 加令牌字符串的 `Authorization` 请求头。这是从 OAuth2 继承的。
- * HTTP Basic 认证方式。
- * HTTP Digest,等等。
-* `oauth2`:所有的 OAuth2 处理安全性的方式(称为「流程」)。
- *以下几种流程适合构建 OAuth 2.0 身份认证的提供者(例如 Google,Facebook,Twitter,GitHub 等):
+* `apiKey`: an application specific key that can come from:
+ * A query parameter.
+ * A header.
+ * A cookie.
+* `http`: standard HTTP authentication systems, including:
+ * `bearer`: a header `Authorization` with a value of `Bearer` plus a token. This is inherited from OAuth2.
+ * HTTP Basic authentication.
+ * HTTP Digest, etc.
+* `oauth2`: all the OAuth2 ways to handle security (called "flows").
+ * Several of these flows are appropriate for building an OAuth 2.0 authentication provider (like Google, Facebook, Twitter, GitHub, etc):
* `implicit`
* `clientCredentials`
* `authorizationCode`
- * 但是有一个特定的「流程」可以完美地用于直接在同一应用程序中处理身份认证:
- * `password`:接下来的几章将介绍它的示例。
-* `openIdConnect`:提供了一种定义如何自动发现 OAuth2 身份认证数据的方法。
- * 此自动发现机制是 OpenID Connect 规范中定义的内容。
+ * But there is one specific "flow" that can be perfectly used for handling authentication in the same application directly:
+ * `password`: some next chapters will cover examples of this.
+* `openIdConnect`: has a way to define how to discover OAuth2 authentication data automatically.
+ * This automatic discovery is what is defined in the OpenID Connect specification.
!!! tip
- 集成其他身份认证/授权提供者(例如Google,Facebook,Twitter,GitHub等)也是可能的,而且较为容易。
+ Integrating other authentication/authorization providers like Google, Facebook, Twitter, GitHub, etc. is also possible and relatively easy.
- 最复杂的问题是创建一个像这样的身份认证/授权提供程序,但是 **FastAPI** 为你提供了轻松完成任务的工具,同时为你解决了重活。
+ The most complex problem is building an authentication/authorization provider like those, but **FastAPI** gives you the tools to do it easily, while doing the heavy lifting for you.
-## **FastAPI** 实用工具
+## **FastAPI** utilities
-FastAPI 在 `fastapi.security` 模块中为每个安全方案提供了几种工具,这些工具简化了这些安全机制的使用方法。
+FastAPI provides several tools for each of these security schemes in the `fastapi.security` module that simplify using these security mechanisms.
-在下一章中,你将看到如何使用 **FastAPI** 所提供的这些工具为你的 API 增加安全性。
+In the next chapters you will see how to add security to your API using those tools provided by **FastAPI**.
-而且你还将看到它如何自动地被集成到交互式文档系统中。
+And you will also see how it gets automatically integrated into the interactive documentation system.
From 41559535a402a2076e58803850450893f748e711 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:58 +0800
Subject: [PATCH 099/163] New translations oauth2-jwt.md (Chinese Simplified)
---
docs/zh/docs/tutorial/security/oauth2-jwt.md | 364 +++++++++++++------
1 file changed, 243 insertions(+), 121 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md
index 054198545ef8e..b663abcb7b696 100644
--- a/docs/zh/docs/tutorial/security/oauth2-jwt.md
+++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md
@@ -1,132 +1,160 @@
-# OAuth2 实现密码哈希与 Bearer JWT 令牌验证
+# OAuth2 with Password (and hashing), Bearer with JWT tokens
-至此,我们已经编写了所有安全流,本章学习如何使用 JWT 令牌(Token)和安全密码哈希(Hash)实现真正的安全机制。
+Now that we have all the security flow, let's make the application actually secure, using JWT tokens and secure password hashing.
-本章的示例代码真正实现了在应用的数据库中保存哈希密码等功能。
+This code is something you can actually use in your application, save the password hashes in your database, etc.
-接下来,我们紧接上一章,继续完善安全机制。
+We are going to start from where we left in the previous chapter and increment it.
-## JWT 简介
+## About JWT
-JWT 即**JSON 网络令牌**(JSON Web Tokens)。
+JWT means "JSON Web Tokens".
-JWT 是一种将 JSON 对象编码为没有空格,且难以理解的长字符串的标准。JWT 的内容如下所示:
+It's a standard to codify a JSON object in a long dense string without spaces. It looks like this:
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```
-JWT 字符串没有加密,任何人都能用它恢复原始信息。
+It is not encrypted, so, anyone could recover the information from the contents.
-但 JWT 使用了签名机制。接受令牌时,可以用签名校验令牌。
+But it's signed. So, when you receive a token that you emitted, you can verify that you actually emitted it.
-使用 JWT 创建有效期为一周的令牌。第二天,用户持令牌再次访问时,仍为登录状态。
+That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know that user is still logged in to your system.
-令牌于一周后过期,届时,用户身份验证就会失败。只有再次登录,才能获得新的令牌。如果用户(或第三方)篡改令牌的过期时间,因为签名不匹配会导致身份验证失败。
+After a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
-如需深入了解 JWT 令牌,了解它的工作方式,请参阅 https://jwt.io。
+If you want to play with JWT tokens and see how they work, check https://jwt.io.
-## 安装 `python-jose`
+## Install `python-jose`
-安装 `python-jose`,在 Python 中生成和校验 JWT 令牌:
+We need to install `python-jose` to generate and verify the JWT tokens in Python:
+=== "Python 3.6+"
-用与上一章同样的方式实现应用授权。
+ ```Python hl_lines="118-133"
+ {!> ../../../docs_src/security/tutorial004_an.py!}
+ ```
-使用如下凭证:
+=== "Python 3.10+ non-Annotated"
-用户名: `johndoe` 密码: `secret`
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-!!! check "检查"
+ ```Python hl_lines="114-127"
+ {!> ../../../docs_src/security/tutorial004_py310.py!}
+ ```
- 注意,代码中没有明文密码**`secret`**,只保存了它的哈希值。
+=== "Python 3.6+ non-Annotated"
-
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-调用 `/users/me/` 端点,收到下面的响应:
+ ```Python hl_lines="115-128"
+ {!> ../../../docs_src/security/tutorial004.py!}
+ ```
+
+### Technical details about the JWT "subject" `sub`
+
+The JWT specification says that there's a key `sub`, with the subject of the token.
+
+It's optional to use it, but that's where you would put the user's identification, so we are using it here.
+
+JWT might be used for other things apart from identifying a user and allowing them to perform operations directly on your API.
+
+For example, you could identify a "car" or a "blog post".
+
+Then you could add permissions about that entity, like "drive" (for the car) or "edit" (for the blog).
+
+And then, you could give that JWT token to a user (or bot), and they could use it to perform those actions (drive the car, or edit the blog post) without even needing to have an account, just with the JWT token your API generated for that.
+
+Using these ideas, JWT can be used for way more sophisticated scenarios.
+
+In those cases, several of those entities could have the same ID, let's say `foo` (a user `foo`, a car `foo`, and a blog post `foo`).
+
+So, to avoid ID collisions, when creating the JWT token for the user, you could prefix the value of the `sub` key, e.g. with `username:`. So, in this example, the value of `sub` could have been: `username:johndoe`.
+
+The important thing to have in mind is that the `sub` key should have a unique identifier across the entire application, and it should be a string.
+
+## Check it
+
+Run the server and go to the docs: http://127.0.0.1:8000/docs.
+
+You'll see the user interface like:
+
+
+
+Authorize the application the same way as before.
+
+Using the credentials:
+
+Username: `johndoe` Password: `secret`
+
+!!! check
+ Notice that nowhere in the code is the plaintext password "`secret`", we only have the hashed version.
+
+
+
+Call the endpoint `/users/me/`, you will get the response as:
```JSON
{
@@ -227,44 +350,43 @@ JWT 规范还包括 `sub` 键,值是令牌的主题。
}
```
-
-
-打开浏览器的开发者工具,查看数据是怎么发送的,而且数据里只包含了令牌,只有验证用户的第一个请求才发送密码,并获取访问令牌,但之后不会再发送密码:
+
-
+If you open the developer tools, you could see how the data sent only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
-!!! note "笔记"
+
- 注意,请求中 `Authorization` 响应头的值以 `Bearer` 开头。
+!!! note
+ Notice the header `Authorization`, with a value that starts with `Bearer`.
-## `scopes` 高级用法
+## Advanced usage with `scopes`
-OAuth2 支持**`scopes`**(作用域)。
+OAuth2 has the notion of "scopes".
-**`scopes`**为 JWT 令牌添加指定权限。
+You can use them to add a specific set of permissions to a JWT token.
-让持有令牌的用户或第三方在指定限制条件下与 API 交互。
+Then you can give this token to a user directly or a third party, to interact with your API with a set of restrictions.
-**高级用户指南**中将介绍如何使用 `scopes`,及如何把 `scopes` 集成至 **FastAPI**。
+You can learn how to use them and how they are integrated into **FastAPI** later in the **Advanced User Guide**.
-## 小结
+## Recap
-至此,您可以使用 OAuth2 和 JWT 等标准配置安全的 **FastAPI** 应用。
+With what you have seen up to now, you can set up a secure **FastAPI** application using standards like OAuth2 and JWT.
-几乎在所有框架中,处理安全问题很快都会变得非常复杂。
+In almost any framework handling the security becomes a rather complex subject quite quickly.
-有些包为了简化安全流,不得不在数据模型、数据库和功能上做出妥协。而有些过于简化的软件包其实存在了安全隐患。
+Many packages that simplify it a lot have to make many compromises with the data model, database, and available features. And some of these packages that simplify things too much actually have security flaws underneath.
---
-**FastAPI** 不向任何数据库、数据模型或工具做妥协。
+**FastAPI** doesn't make any compromise with any database, data model or tool.
-开发者可以灵活选择最适合项目的安全机制。
+It gives you all the flexibility to choose the ones that fit your project the best.
-还可以直接使用 `passlib` 和 `python-jose` 等维护良好、使用广泛的包,这是因为 **FastAPI** 不需要任何复杂机制,就能集成外部的包。
+And you can use directly many well maintained and widely used packages like `passlib` and `python-jose`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
-而且,**FastAPI** 还提供了一些工具,在不影响灵活、稳定和安全的前提下,尽可能地简化安全机制。
+But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security.
-**FastAPI** 还支持以相对简单的方式,使用 OAuth2 等安全、标准的协议。
+And you can use and implement secure, standard protocols, like OAuth2 in a relatively simple way.
-**高级用户指南**中详细介绍了 OAuth2**`scopes`**的内容,遵循同样的标准,实现更精密的权限系统。OAuth2 的作用域是脸书、谷歌、GitHub、微软、推特等第三方身份验证应用使用的机制,让用户授权第三方应用与 API 交互。
+You can learn more in the **Advanced User Guide** about how to use OAuth2 "scopes", for a more fine-grained permission system, following these same standards. OAuth2 with scopes is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, Twitter, etc. to authorize third party applications to interact with their APIs on behalf of their users.
From e628b0ae10c7da33831f7ac4dfb2feb67c322209 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:37:59 +0800
Subject: [PATCH 100/163] New translations simple-oauth2.md (Chinese
Simplified)
---
.../docs/tutorial/security/simple-oauth2.md | 414 ++++++++++++------
1 file changed, 287 insertions(+), 127 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/simple-oauth2.md b/docs/zh/docs/tutorial/security/simple-oauth2.md
index 276f3d63b69f9..f55ee6fb8f029 100644
--- a/docs/zh/docs/tutorial/security/simple-oauth2.md
+++ b/docs/zh/docs/tutorial/security/simple-oauth2.md
@@ -1,132 +1,228 @@
-# 使用密码和 Bearer 的简单 OAuth2
+# Simple OAuth2 with Password and Bearer
-现在让我们接着上一章继续开发,并添加缺少的部分以实现一个完整的安全性流程。
+Now let's build from the previous chapter and add the missing parts to have a complete security flow.
-## 获取 `username` 和 `password`
+## Get the `username` and `password`
-我们将使用 **FastAPI** 的安全性实用工具来获取 `username` 和 `password`。
+We are going to use **FastAPI** security utilities to get the `username` and `password`.
-OAuth2 规定在使用(我们打算用的)「password 流程」时,客户端/用户必须将 `username` 和 `password` 字段作为表单数据发送。
+OAuth2 specifies that when using the "password flow" (that we are using) the client/user must send a `username` and `password` fields as form data.
-而且规范明确了字段必须这样命名。因此 `user-name` 或 `email` 是行不通的。
+And the spec says that the fields have to be named like that. So `user-name` or `email` wouldn't work.
-不过不用担心,你可以在前端按照你的想法将它展示给最终用户。
+But don't worry, you can show it as you wish to your final users in the frontend.
-而且你的数据库模型也可以使用你想用的任何其他名称。
+And your database models can use any other names you want.
-但是对于登录*路径操作*,我们需要使用这些名称来与规范兼容(以具备例如使用集成的 API 文档系统的能力)。
+But for the login *path operation*, we need to use these names to be compatible with the spec (and be able to, for example, use the integrated API documentation system).
-规范还写明了 `username` 和 `password` 必须作为表单数据发送(因此,此处不能使用 JSON)。
+The spec also states that the `username` and `password` must be sent as form data (so, no JSON here).
### `scope`
-规范还提到客户端可以发送另一个表单字段「`scope`」。
+The spec also says that the client can send another form field "`scope`".
-这个表单字段的名称为 `scope`(单数形式),但实际上它是一个由空格分隔的「作用域」组成的长字符串。
+The form field name is `scope` (in singular), but it is actually a long string with "scopes" separated by spaces.
-每个「作用域」只是一个字符串(中间没有空格)。
+Each "scope" is just a string (without spaces).
-它们通常用于声明特定的安全权限,例如:
+They are normally used to declare specific security permissions, for example:
-* `users:read` 或者 `users:write` 是常见的例子。
-* Facebook / Instagram 使用 `instagram_basic`。
-* Google 使用了 `https://www.googleapis.com/auth/drive` 。
+* `users:read` or `users:write` are common examples.
+* `instagram_basic` is used by Facebook / Instagram.
+* `https://www.googleapis.com/auth/drive` is used by Google.
!!! info
- 在 OAuth2 中「作用域」只是一个声明所需特定权限的字符串。
+ In OAuth2 a "scope" is just a string that declares a specific permission required.
- 它有没有 `:` 这样的其他字符或者是不是 URL 都没有关系。
+ It doesn't matter if it has other characters like `:` or if it is a URL.
+
+ Those details are implementation specific.
+
+ For OAuth2 they are just strings.
- 这些细节是具体的实现。
+## Code to get the `username` and `password`
- 对 OAuth2 来说它们就只是字符串而已。
+Now let's use the utilities provided by **FastAPI** to handle this.
-## 获取 `username` 和 `password` 的代码
+### `OAuth2PasswordRequestForm`
-现在,让我们使用 **FastAPI** 提供的实用工具来处理此问题。
+First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` in the *path operation* for `/token`:
-### `OAuth2PasswordRequestForm`
+=== "Python 3.10+"
-首先,导入 `OAuth2PasswordRequestForm`,然后在 `token` 的*路径操作*中通过 `Depends` 将其作为依赖项使用。
+ ```Python hl_lines="4 78"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+ ```
-```Python hl_lines="4 76"
-{!../../../docs_src/security/tutorial003.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 78"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 79"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
-`OAuth2PasswordRequestForm` 是一个类依赖项,声明了如下的请求表单:
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-* `username`。
-* `password`。
-* 一个可选的 `scope` 字段,是一个由空格分隔的字符串组成的大字符串。
-* 一个可选的 `grant_type`.
+ ```Python hl_lines="2 74"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="4 76"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+`OAuth2PasswordRequestForm` is a class dependency that declares a form body with:
+
+* The `username`.
+* The `password`.
+* An optional `scope` field as a big string, composed of strings separated by spaces.
+* An optional `grant_type`.
!!! tip
- OAuth2 规范实际上*要求* `grant_type` 字段使用一个固定的值 `password`,但是 `OAuth2PasswordRequestForm` 没有作强制约束。
+ The OAuth2 spec actually *requires* a field `grant_type` with a fixed value of `password`, but `OAuth2PasswordRequestForm` doesn't enforce it.
- 如果你需要强制要求这一点,请使用 `OAuth2PasswordRequestFormStrict` 而不是 `OAuth2PasswordRequestForm`。
+ If you need to enforce it, use `OAuth2PasswordRequestFormStrict` instead of `OAuth2PasswordRequestForm`.
-* 一个可选的 `client_id`(我们的示例不需要它)。
-* 一个可选的 `client_secret`(我们的示例不需要它)。
+* An optional `client_id` (we don't need it for our example).
+* An optional `client_secret` (we don't need it for our example).
!!! info
- `OAuth2PasswordRequestForm` 并不像 `OAuth2PasswordBearer` 一样是 FastAPI 的一个特殊的类。
+ The `OAuth2PasswordRequestForm` is not a special class for **FastAPI** as is `OAuth2PasswordBearer`.
- `OAuth2PasswordBearer` 使得 **FastAPI** 明白它是一个安全方案。所以它得以通过这种方式添加到 OpenAPI 中。
+ `OAuth2PasswordBearer` makes **FastAPI** know that it is a security scheme. So it is added that way to OpenAPI.
+
+ But `OAuth2PasswordRequestForm` is just a class dependency that you could have written yourself, or you could have declared `Form` parameters directly.
+
+ But as it's a common use case, it is provided by **FastAPI** directly, just to make it easier.
- 但 `OAuth2PasswordRequestForm` 只是一个你可以自己编写的类依赖项,或者你也可以直接声明 `Form` 参数。
+### Use the form data
- 但是由于这是一种常见的使用场景,因此 FastAPI 出于简便直接提供了它。
+!!! tip
+ The instance of the dependency class `OAuth2PasswordRequestForm` won't have an attribute `scope` with the long string separated by spaces, instead, it will have a `scopes` attribute with the actual list of strings for each scope sent.
-### 使用表单数据
+ We are not using `scopes` in this example, but the functionality is there if you need it.
-!!! tip
- 类依赖项 `OAuth2PasswordRequestForm` 的实例不会有用空格分隔的长字符串属性 `scope`,而是具有一个 `scopes` 属性,该属性将包含实际被发送的每个作用域字符串组成的列表。
+Now, get the user data from the (fake) database, using the `username` from the form field.
- 在此示例中我们没有使用 `scopes`,但如果你需要的话可以使用该功能。
+If there is no such user, we return an error saying "incorrect username or password".
-现在,使用表单字段中的 `username` 从(伪)数据库中获取用户数据。
+For the error, we use the exception `HTTPException`:
-如果没有这个用户,我们将返回一个错误消息,提示「用户名或密码错误」。
+=== "Python 3.10+"
-对于这个错误,我们使用 `HTTPException` 异常:
+ ```Python hl_lines="3 79-81"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+ ```
-```Python hl_lines="3 77-79"
-{!../../../docs_src/security/tutorial003.py!}
-```
+=== "Python 3.9+"
-### 校验密码
+ ```Python hl_lines="3 79-81"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
-目前我们已经从数据库中获取了用户数据,但尚未校验密码。
+=== "Python 3.6+"
-让我们首先将这些数据放入 Pydantic `UserInDB` 模型中。
+ ```Python hl_lines="3 80-82"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
-永远不要保存明文密码,因此,我们将使用(伪)哈希密码系统。
+=== "Python 3.10+ non-Annotated"
-如果密码不匹配,我们将返回同一个错误。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-#### 哈希密码
+ ```Python hl_lines="1 75-77"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
-「哈希」的意思是:将某些内容(在本例中为密码)转换为看起来像乱码的字节序列(只是一个字符串)。
+=== "Python 3.6+ non-Annotated"
-每次你传入完全相同的内容(完全相同的密码)时,你都会得到完全相同的乱码。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
-但是你不能从乱码转换回密码。
+ ```Python hl_lines="3 77-79"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
-##### 为什么使用哈希密码
+### Check the password
-如果你的数据库被盗,小偷将无法获得用户的明文密码,只有哈希值。
+At this point we have the user data from our database, but we haven't checked the password.
-因此,小偷将无法尝试在另一个系统中使用这些相同的密码(由于许多用户在任何地方都使用相同的密码,因此这很危险)。
+Let's put that data in the Pydantic `UserInDB` model first.
-```Python hl_lines="80-83"
-{!../../../docs_src/security/tutorial003.py!}
-```
+You should never save plaintext passwords, so, we'll use the (fake) password hashing system.
+
+If the passwords don't match, we return the same error.
+
+#### Password hashing
+
+"Hashing" means: converting some content (a password in this case) into a sequence of bytes (just a string) that looks like gibberish.
+
+Whenever you pass exactly the same content (exactly the same password) you get exactly the same gibberish.
+
+But you cannot convert from the gibberish back to the password.
+
+##### Why use password hashing
+
+If your database is stolen, the thief won't have your users' plaintext passwords, only the hashes.
+
+So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
+
+=== "Python 3.10+"
+
+ ```Python hl_lines="82-85"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="82-85"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
-#### 关于 `**user_dict`
+=== "Python 3.6+"
-`UserInDB(**user_dict)` 表示:
+ ```Python hl_lines="83-86"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
-*直接将 `user_dict` 的键和值作为关键字参数传递,等同于:*
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="78-81"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="80-83"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+#### About `**user_dict`
+
+`UserInDB(**user_dict)` means:
+
+*Pass the keys and values of the `user_dict` directly as key-value arguments, equivalent to:*
```Python
UserInDB(
@@ -139,92 +235,156 @@ UserInDB(
```
!!! info
- 有关 `user_dict` 的更完整说明,请参阅[**额外的模型**文档](../extra-models.md#about-user_indict){.internal-link target=_blank}。
+ For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user_indict){.internal-link target=_blank}.
-## 返回令牌
+## Return the token
-`token` 端点的响应必须是一个 JSON 对象。
+The response of the `token` endpoint must be a JSON object.
-它应该有一个 `token_type`。在我们的例子中,由于我们使用的是「Bearer」令牌,因此令牌类型应为「`bearer`」。
+It should have a `token_type`. In our case, as we are using "Bearer" tokens, the token type should be "`bearer`".
-并且还应该有一个 `access_token` 字段,它是一个包含我们的访问令牌的字符串。
+And it should have an `access_token`, with a string containing our access token.
-对于这个简单的示例,我们将极其不安全地返回相同的 `username` 作为令牌。
+For this simple example, we are going to just be completely insecure and return the same `username` as the token.
!!! tip
- 在下一章中,你将看到一个真实的安全实现,使用了哈希密码和 JWT 令牌。
+ In the next chapter, you will see a real secure implementation, with password hashing and JWT tokens.
- 但现在,让我们仅关注我们需要的特定细节。
+ But for now, let's focus on the specific details we need.
-```Python hl_lines="85"
-{!../../../docs_src/security/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="87"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="87"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="88"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="83"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="85"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
!!! tip
- 根据规范,你应该像本示例一样,返回一个带有 `access_token` 和 `token_type` 的 JSON。
+ By the spec, you should return a JSON with an `access_token` and a `token_type`, the same as in this example.
- 这是你必须在代码中自行完成的工作,并且要确保使用了这些 JSON 字段。
+ This is something that you have to do yourself in your code, and make sure you use those JSON keys.
+
+ It's almost the only thing that you have to remember to do correctly yourself, to be compliant with the specifications.
+
+ For the rest, **FastAPI** handles it for you.
- 这几乎是唯一的你需要自己记住并正确地执行以符合规范的事情。
+## Update the dependencies
- 其余的,**FastAPI** 都会为你处理。
+Now we are going to update our dependencies.
-## 更新依赖项
+We want to get the `current_user` *only* if this user is active.
-现在我们将更新我们的依赖项。
+So, we create an additional dependency `get_current_active_user` that in turn uses `get_current_user` as a dependency.
-我们想要仅当此用户处于启用状态时才能获取 `current_user`。
+Both of these dependencies will just return an HTTP error if the user doesn't exist, or if is inactive.
-因此,我们创建了一个额外的依赖项 `get_current_active_user`,而该依赖项又以 `get_current_user` 作为依赖项。
+So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
-如果用户不存在或处于未启用状态,则这两个依赖项都将仅返回 HTTP 错误。
+=== "Python 3.10+"
-因此,在我们的端点中,只有当用户存在,身份认证通过且处于启用状态时,我们才能获得该用户:
+ ```Python hl_lines="58-66 69-74 94"
+ {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+ ```
-```Python hl_lines="58-67 69-72 90"
-{!../../../docs_src/security/tutorial003.py!}
-```
+=== "Python 3.9+"
-!!! info
- 我们在此处返回的值为 `Bearer` 的额外响应头 `WWW-Authenticate` 也是规范的一部分。
+ ```Python hl_lines="58-66 69-74 94"
+ {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="59-67 70-75 95"
+ {!> ../../../docs_src/security/tutorial003_an.py!}
+ ```
- 任何的 401「未认证」HTTP(错误)状态码都应该返回 `WWW-Authenticate` 响应头。
+=== "Python 3.10+ non-Annotated"
- 对于 bearer 令牌(我们的例子),该响应头的值应为 `Bearer`。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
- 实际上你可以忽略这个额外的响应头,不会有什么问题。
+ ```Python hl_lines="56-64 67-70 88"
+ {!> ../../../docs_src/security/tutorial003_py310.py!}
+ ```
- 但此处提供了它以符合规范。
+=== "Python 3.6+ non-Annotated"
- 而且,(现在或将来)可能会有工具期望得到并使用它,然后对你或你的用户有用处。
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="58-66 69-72 90"
+ {!> ../../../docs_src/security/tutorial003.py!}
+ ```
+
+!!! info
+ The additional header `WWW-Authenticate` with value `Bearer` we are returning here is also part of the spec.
- 这就是遵循标准的好处...
+ Any HTTP (error) status code 401 "UNAUTHORIZED" is supposed to also return a `WWW-Authenticate` header.
+
+ In the case of bearer tokens (our case), the value of that header should be `Bearer`.
+
+ You can actually skip that extra header and it would still work.
+
+ But it's provided here to be compliant with the specifications.
+
+ Also, there might be tools that expect and use it (now or in the future) and that might be useful for you or your users, now or in the future.
+
+ That's the benefit of standards...
-## 实际效果
+## See it in action
-打开交互式文档:http://127.0.0.1:8000/docs。
+Open the interactive docs: http://127.0.0.1:8000/docs.
-### 身份认证
+### Authenticate
-点击「Authorize」按钮。
+Click the "Authorize" button.
-使用以下凭证:
+Use the credentials:
-用户名:`johndoe`
+User: `johndoe`
-密码:`secret`
+Password: `secret`
-
+
-在系统中进行身份认证后,你将看到:
+After authenticating in the system, you will see it like:
-
+
-### 获取本人的用户数据
+### Get your own user data
-现在执行 `/users/me` 路径的 `GET` 操作。
+Now use the operation `GET` with the path `/users/me`.
-你将获得你的用户数据,如:
+You will get your user's data, like:
```JSON
{
@@ -236,9 +396,9 @@ UserInDB(
}
```
-
+
-如果你点击锁定图标并注销,然后再次尝试同一操作,则会得到 HTTP 401 错误:
+If you click the lock icon and logout, and then try the same operation again, you will get an HTTP 401 error of:
```JSON
{
@@ -246,17 +406,17 @@ UserInDB(
}
```
-### 未启用的用户
+### Inactive user
-现在尝试使用未启用的用户,并通过以下方式进行身份认证:
+Now try with an inactive user, authenticate with:
-用户名:`alice`
+User: `alice`
-密码:`secret2`
+Password: `secret2`
-然后尝试执行 `/users/me` 路径的 `GET` 操作。
+And try to use the operation `GET` with the path `/users/me`.
-你将得到一个「未启用的用户」错误,如:
+You will get an "inactive user" error, like:
```JSON
{
@@ -264,12 +424,12 @@ UserInDB(
}
```
-## 总结
+## Recap
-现在你掌握了为你的 API 实现一个基于 `username` 和 `password` 的完整安全系统的工具。
+You now have the tools to implement a complete security system based on `username` and `password` for your API.
-使用这些工具,你可以使安全系统与任何数据库以及任何用户或数据模型兼容。
+Using these tools, you can make the security system compatible with any database and with any user or data model.
-唯一缺少的细节是它实际上还并不「安全」。
+The only detail missing is that it is not actually "secure" yet.
-在下一章中,你将看到如何使用一个安全的哈希密码库和 JWT 令牌。
+In the next chapter you'll see how to use a secure password hashing library and JWT tokens.
From 02dd4b94da7baa201be9a39525e3462c4988cf7c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:38:00 +0800
Subject: [PATCH 101/163] New translations sql-databases.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/sql-databases.md | 535 +++++++++++++------------
1 file changed, 279 insertions(+), 256 deletions(-)
diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md
index 482588f94d7ec..136946bddddda 100644
--- a/docs/zh/docs/tutorial/sql-databases.md
+++ b/docs/zh/docs/tutorial/sql-databases.md
@@ -1,67 +1,76 @@
-# SQL (关系型) 数据库
+# SQL (Relational) Databases
-**FastAPI**不需要你使用SQL(关系型)数据库。
+!!! info
+ These docs are about to be updated. 🎉
+
+ The current version assumes Pydantic v1, and SQLAlchemy versions less than 2.0.
+
+ The new docs will include Pydantic v2 and will use SQLModel (which is also based on SQLAlchemy) once it is updated to use Pydantic v2 as well.
-但是您可以使用任何您想要的关系型数据库。
+**FastAPI** doesn't require you to use a SQL (relational) database.
-在这里,让我们看一个使用着[SQLAlchemy](https://www.sqlalchemy.org/)的示例。
+But you can use any relational database that you want.
-您可以很容易地将SQLAlchemy支持任何数据库,像:
+Here we'll see an example using SQLAlchemy.
+
+You can easily adapt it to any database supported by SQLAlchemy, like:
* PostgreSQL
* MySQL
* SQLite
* Oracle
-* Microsoft SQL Server,等等其它数据库
+* Microsoft SQL Server, etc.
-在此示例中,我们将使用**SQLite**,因为它使用单个文件并且 在Python中具有集成支持。因此,您可以复制此示例并按原样来运行它。
+In this example, we'll use **SQLite**, because it uses a single file and Python has integrated support. So, you can copy this example and run it as is.
-稍后,对于您的产品级别的应用程序,您可能会要使用像**PostgreSQL**这样的数据库服务器。
+Later, for your production application, you might want to use a database server like **PostgreSQL**.
!!! tip
- 这儿有一个**FastAPI**和**PostgreSQL**的官方项目生成器,全部基于**Docker**,包括前端和更多工具:https://github.com/tiangolo/full-stack-fastapi-postgresql
+ There is an official project generator with **FastAPI** and **PostgreSQL**, all based on **Docker**, including a frontend and more tools: https://github.com/tiangolo/full-stack-fastapi-postgresql
!!! note
- 请注意,大部分代码是`SQLAlchemy`的标准代码,您可以用于任何框架。FastAPI特定的代码和往常一样少。
+ Notice that most of the code is the standard `SQLAlchemy` code you would use with any framework.
+
+ The **FastAPI** specific code is as small as always.
-## ORMs(对象关系映射)
+## ORMs
-**FastAPI**可与任何数据库在任何样式的库中一起与 数据库进行通信。
+**FastAPI** works with any database and any style of library to talk to the database.
-一种常见的模式是使用“ORM”:对象关系映射。
+A common pattern is to use an "ORM": an "object-relational mapping" library.
-ORM 具有在代码和数据库表(“*关系型”)中的**对象**之间转换(“*映射*”)的工具。
+An ORM has tools to convert ("*map*") between *objects* in code and database tables ("*relations*").
-使用 ORM,您通常会在 SQL 数据库中创建一个代表映射的类,该类的每个属性代表一个列,具有名称和类型。
+With an ORM, you normally create a class that represents a table in a SQL database, each attribute of the class represents a column, with a name and a type.
-例如,一个类`Pet`可以表示一个 SQL 表`pets`。
+For example a class `Pet` could represent a SQL table `pets`.
-该类的每个*实例对象都代表数据库中的一行数据。*
+And each *instance* object of that class represents a row in the database.
-又例如,一个对象`orion_cat`(`Pet`的一个实例)可以有一个属性`orion_cat.type`, 对标数据库中的`type`列。并且该属性的值可以是其它,例如`"cat"`。
+For example an object `orion_cat` (an instance of `Pet`) could have an attribute `orion_cat.type`, for the column `type`. And the value of that attribute could be, e.g. `"cat"`.
-这些 ORM 还具有在表或实体之间建立关系的工具(比如创建多表关系)。
+These ORMs also have tools to make the connections or relations between tables or entities.
-这样,您还可以拥有一个属性`orion_cat.owner`,它包含该宠物所有者的数据,这些数据取自另外一个表。
+This way, you could also have an attribute `orion_cat.owner` and the owner would contain the data for this pet's owner, taken from the table *owners*.
-因此,`orion_cat.owner.name`可能是该宠物主人的姓名(来自表`owners`中的列`name`)。
+So, `orion_cat.owner.name` could be the name (from the `name` column in the `owners` table) of this pet's owner.
-它可能有一个像`"Arquilian"`(一种业务逻辑)。
+It could have a value like `"Arquilian"`.
-当您尝试从您的宠物对象访问它时,ORM 将完成所有工作以从相应的表*所有者那里再获取信息。*
+And the ORM will do all the work to get the information from the corresponding table *owners* when you try to access it from your pet object.
-常见的 ORM 例如:Django-ORM(Django 框架的一部分)、SQLAlchemy ORM(SQLAlchemy 的一部分,独立于框架)和 Peewee(独立于框架)等。
+Common ORMs are for example: Django-ORM (part of the Django framework), SQLAlchemy ORM (part of SQLAlchemy, independent of framework) and Peewee (independent of framework), among others.
-在这里,我们将看到如何使用**SQLAlchemy ORM**。
+Here we will see how to work with **SQLAlchemy ORM**.
-以类似的方式,您也可以使用任何其他 ORM。
+In a similar way you could use any other ORM.
!!! tip
- 在文档中也有一篇使用 Peewee 的等效的文章。
+ There's an equivalent article using Peewee here in the docs.
-## 文件结构
+## File structure
-对于这些示例,假设您有一个名为的目录`my_super_project`,其中包含一个名为的子目录`sql_app`,其结构如下:
+For these examples, let's say you have a directory named `my_super_project` that contains a sub-directory called `sql_app` with a structure like this:
```
.
@@ -74,177 +83,191 @@ ORM 具有在代码和数据库表(“*关系型”)中的**对象**之间
└── schemas.py
```
-该文件`__init__.py`只是一个空文件,但它告诉 Python 其中`sql_app`的所有模块(Python 文件)都是一个包。
+The file `__init__.py` is just an empty file, but it tells Python that `sql_app` with all its modules (Python files) is a package.
-现在让我们看看每个文件/模块的作用。
+Now let's see what each file/module does.
-## 创建 SQLAlchemy 部件
+## Install `SQLAlchemy`
-让我们涉及到文件`sql_app/database.py`。
+First you need to install `SQLAlchemy`:
-### 导入 SQLAlchemy 部件
+
+
-## 直接与数据库交互
+## Interact with the database directly
-如果您想独立于 FastAPI 直接浏览 SQLite 数据库(文件)以调试其内容、添加表、列、记录、修改数据等,您可以使用[SQLite 的 DB Browser](https://sqlitebrowser.org/)
+If you want to explore the SQLite database (file) directly, independently of FastAPI, to debug its contents, add tables, columns, records, modify data, etc. you can use DB Browser for SQLite.
-它看起来像这样:
+It will look like this:
-
+
-您还可以使用[SQLite Viewer](https://inloop.github.io/sqlite-viewer/)或[ExtendsClass](https://extendsclass.com/sqlite-browser.html)等在线 SQLite 浏览器。
+You can also use an online SQLite browser like SQLite Viewer or ExtendsClass.
-## 中间件替代数据库会话
+## Alternative DB session with middleware
-如果你不能使用依赖项`yield`——例如,如果你没有使用**Python 3.7**并且不能安装上面提到的**Python 3.6**的“backports” ——你可以在类似的“中间件”中设置会话方法。
+If you can't use dependencies with `yield` -- for example, if you are not using **Python 3.7** and can't install the "backports" mentioned above for **Python 3.6** -- you can set up the session in a "middleware" in a similar way.
-“中间件”基本功能是一个为每个请求执行的函数在请求之前进行执行相应的代码,以及在请求执行之后执行相应的代码。
+A "middleware" is basically a function that is always executed for each request, with some code executed before, and some code executed after the endpoint function.
-### 创建中间件
+### Create a middleware
-我们将添加中间件(只是一个函数)将为每个请求创建一个新的 SQLAlchemy`SessionLocal`,将其添加到请求中,然后在请求完成后关闭它。
+The middleware we'll add (just a function) will create a new SQLAlchemy `SessionLocal` for each request, add it to the request and then close it once the request is finished.
=== "Python 3.9+"
@@ -736,35 +759,35 @@ $ uvicorn sql_app.main:app --reload
```
!!! info
- 我们将`SessionLocal()`请求的创建和处理放在一个`try`块中。
-
- 然后我们在finally块中关闭它。
+ We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
- 通过这种方式,我们确保数据库会话在请求后始终关闭,即使在处理请求时出现异常也会关闭。
+ And then we close it in the `finally` block.
+
+ This way we make sure the database session is always closed after the request. Even if there was an exception while processing the request.
-### 关于`request.state`
+### About `request.state`
-`request.state`是每个`Request`对象的属性。它用于存储附加到请求本身的任意对象,例如本例中的数据库会话。您可以在[Starlette 的关于`Request`state](https://www.starlette.io/requests/#other-state)的文档中了解更多信息。
+`request.state` is a property of each `Request` object. It is there to store arbitrary objects attached to the request itself, like the database session in this case. You can read more about it in Starlette's docs about `Request` state.
-对于这种情况下,它帮助我们确保在所有请求中使用单个数据库会话,然后关闭(在中间件中)。
+For us in this case, it helps us ensure a single database session is used through all the request, and then closed afterwards (in the middleware).
-### 使用`yield`依赖项与使用中间件的区别
+### Dependencies with `yield` or middleware
-在此处添加**中间件**与`yield`的依赖项的作用效果类似,但也有一些区别:
+Adding a **middleware** here is similar to what a dependency with `yield` does, with some differences:
-* 中间件需要更多的代码并且更复杂一些。
-* 中间件必须是一个`async`函数。
- * 如果其中有代码必须“等待”网络,它可能会在那里“阻止”您的应用程序并稍微降低性能。
- * 尽管这里的`SQLAlchemy`工作方式可能不是很成问题。
- * 但是,如果您向等待大量I/O的中间件添加更多代码,则可能会出现问题。
-* *每个*请求都会运行一个中间件。
- * 将为每个请求创建一个连接。
- * 即使处理该请求的*路径操作*不需要数据库。
+* It requires more code and is a bit more complex.
+* The middleware has to be an `async` function.
+ * If there is code in it that has to "wait" for the network, it could "block" your application there and degrade performance a bit.
+ * Although it's probably not very problematic here with the way `SQLAlchemy` works.
+ * But if you added more code to the middleware that had a lot of I/O waiting, it could then be problematic.
+* A middleware is run for *every* request.
+ * So, a connection will be created for every request.
+ * Even when the *path operation* that handles that request didn't need the DB.
!!! tip
- `tyield`当依赖项 足以满足用例时,使用`tyield`依赖项方法会更好。
+ It's probably better to use dependencies with `yield` when they are enough for the use case.
!!! info
- `yield`的依赖项是最近刚加入**FastAPI**中的。
+ Dependencies with `yield` were added recently to **FastAPI**.
- 所以本教程的先前版本只有带有中间件的示例,并且可能有多个应用程序使用中间件进行数据库会话管理。
+ A previous version of this tutorial only had the examples with a middleware and there are probably several applications using the middleware for database session management.
From 2f64a0149e32e94ef84b74099548833dace4f72f Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:38:01 +0800
Subject: [PATCH 102/163] New translations static-files.md (Chinese Simplified)
---
docs/zh/docs/tutorial/static-files.md | 38 +++++++++++++--------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md
index e7c5c3f0a16b0..7a0c36af3f4c5 100644
--- a/docs/zh/docs/tutorial/static-files.md
+++ b/docs/zh/docs/tutorial/static-files.md
@@ -1,39 +1,39 @@
-# 静态文件
+# Static Files
-您可以使用 `StaticFiles`从目录中自动提供静态文件。
+You can serve static files automatically from a directory using `StaticFiles`.
-## 使用`StaticFiles`
+## Use `StaticFiles`
-* 导入`StaticFiles`。
-* "挂载"(Mount) 一个 `StaticFiles()` 实例到一个指定路径。
+* Import `StaticFiles`.
+* "Mount" a `StaticFiles()` instance in a specific path.
```Python hl_lines="2 6"
{!../../../docs_src/static_files/tutorial001.py!}
```
-!!! note "技术细节"
- 你也可以用 `from starlette.staticfiles import StaticFiles`。
+!!! note "Technical Details"
+ You could also use `from starlette.staticfiles import StaticFiles`.
- **FastAPI** 提供了和 `starlette.staticfiles` 相同的 `fastapi.staticfiles` ,只是为了方便你,开发者。但它确实来自Starlette。
+ **FastAPI** provides the same `starlette.staticfiles` as `fastapi.staticfiles` just as a convenience for you, the developer. But it actually comes directly from Starlette.
-### 什么是"挂载"(Mounting)
+### What is "Mounting"
-"挂载" 表示在特定路径添加一个完全"独立的"应用,然后负责处理所有子路径。
+"Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
-这与使用`APIRouter`不同,因为安装的应用程序是完全独立的。OpenAPI和来自你主应用的文档不会包含已挂载应用的任何东西等等。
+This is different from using an `APIRouter` as a mounted application is completely independent. The OpenAPI and docs from your main application won't include anything from the mounted application, etc.
-你可以在**高级用户指南**中了解更多。
+You can read more about this in the **Advanced User Guide**.
-## 细节
+## Details
-这个 "子应用" 会被 "挂载" 到第一个 `"/static"` 指向的子路径。因此,任何以`"/static"`开头的路径都会被它处理。
+The first `"/static"` refers to the sub-path this "sub-application" will be "mounted" on. So, any path that starts with `"/static"` will be handled by it.
- `directory="static"` 指向包含你的静态文件的目录名字。
+The `directory="static"` refers to the name of the directory that contains your static files.
-`name="static"` 提供了一个能被**FastAPI**内部使用的名字。
+The `name="static"` gives it a name that can be used internally by **FastAPI**.
-所有这些参数可以不同于"`static`",根据你应用的需要和具体细节调整它们。
+All these parameters can be different than "`static`", adjust them with the needs and specific details of your own application.
-## 更多信息
+## More info
-更多细节和选择查阅 Starlette's docs about Static Files.
+For more details and options check Starlette's docs about Static Files.
From 6ead130ec1fd5ba9cda5af424418531a434b7659 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:38:02 +0800
Subject: [PATCH 103/163] New translations testing.md (Chinese Simplified)
---
docs/zh/docs/tutorial/testing.md | 118 +++++++++++++++----------------
1 file changed, 59 insertions(+), 59 deletions(-)
diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md
index 41f01f8d84a41..3609d39d9f5b1 100644
--- a/docs/zh/docs/tutorial/testing.md
+++ b/docs/zh/docs/tutorial/testing.md
@@ -1,56 +1,56 @@
-# 测试
+# Testing
-感谢 Starlette,测试**FastAPI** 应用轻松又愉快。
+Thanks to Starlette, testing **FastAPI** applications is easy and enjoyable.
-它基于 HTTPX, 而HTTPX又是基于Requests设计的,所以很相似且易懂。
+It is based on HTTPX, which in turn is designed based on Requests, so it's very familiar and intuitive.
-有了它,你可以直接与**FastAPI**一起使用 pytest。
+With it, you can use pytest directly with **FastAPI**.
-## 使用 `TestClient`
+## Using `TestClient`
-!!! 信息
- 要使用 `TestClient`,先要安装 `httpx`.
+!!! info
+ To use `TestClient`, first install `httpx`.
- 例:`pip install httpx`.
+ E.g. `pip install httpx`.
-导入 `TestClient`.
+Import `TestClient`.
-通过传入你的**FastAPI**应用创建一个 `TestClient` 。
+Create a `TestClient` by passing your **FastAPI** application to it.
-创建名字以 `test_` 开头的函数(这是标准的 `pytest` 约定)。
+Create functions with a name that starts with `test_` (this is standard `pytest` conventions).
-像使用 `httpx` 那样使用 `TestClient` 对象。
+Use the `TestClient` object the same way as you do with `httpx`.
-为你需要检查的地方用标准的Python表达式写个简单的 `assert` 语句(重申,标准的`pytest`)。
+Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
```Python hl_lines="2 12 15-18"
{!../../../docs_src/app_testing/tutorial001.py!}
```
-!!! 提示
- 注意测试函数是普通的 `def`,不是 `async def`。
+!!! tip
+ Notice that the testing functions are normal `def`, not `async def`.
- 还有client的调用也是普通的调用,不是用 `await`。
+ And the calls to the client are also normal calls, not using `await`.
+
+ This allows you to use `pytest` directly without complications.
- 这让你可以直接使用 `pytest` 而不会遇到麻烦。
+!!! note "Technical Details"
+ You could also use `from starlette.testclient import TestClient`.
-!!! note "技术细节"
- 你也可以用 `from starlette.testclient import TestClient`。
+ **FastAPI** provides the same `starlette.testclient` as `fastapi.testclient` just as a convenience for you, the developer. But it comes directly from Starlette.
- **FastAPI** 提供了和 `starlette.testclient` 一样的 `fastapi.testclient`,只是为了方便开发者。但它直接来自Starlette。
+!!! tip
+ If you want to call `async` functions in your tests apart from sending requests to your FastAPI application (e.g. asynchronous database functions), have a look at the [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} in the advanced tutorial.
-!!! 提示
- 除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下 [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} 。
+## Separating tests
-## 分离测试
+In a real application, you probably would have your tests in a different file.
-在实际应用中,你可能会把你的测试放在另一个文件里。
+And your **FastAPI** application might also be composed of several files/modules, etc.
-您的**FastAPI**应用程序也可能由一些文件/模块组成等等。
+### **FastAPI** app file
-### **FastAPI** app 文件
-
-假设你有一个像 [更大的应用](./bigger-applications.md){.internal-link target=_blank} 中所描述的文件结构:
+Let's say you have a file structure as described in [Bigger Applications](./bigger-applications.md){.internal-link target=_blank}:
```
.
@@ -59,16 +59,16 @@
│ └── main.py
```
-在 `main.py` 文件中你有一个 **FastAPI** app:
+In the file `main.py` you have your **FastAPI** app:
```Python
{!../../../docs_src/app_testing/main.py!}
```
-### 测试文件
+### Testing file
-然后你会有一个包含测试的文件 `test_main.py` 。app可以像Python包那样存在(一样是目录,但有个 `__init__.py` 文件):
+Then you could have a file `test_main.py` with your tests. It could live on the same Python package (the same directory with a `__init__.py` file):
``` hl_lines="5"
.
@@ -78,21 +78,21 @@
│ └── test_main.py
```
-因为这文件在同一个包中,所以你可以通过相对导入从 `main` 模块(`main.py`)导入`app`对象:
+Because this file is in the same package, you can use relative imports to import the object `app` from the `main` module (`main.py`):
```Python hl_lines="3"
{!../../../docs_src/app_testing/test_main.py!}
```
-...然后测试代码和之前一样的。
+...and have the code for the tests just like before.
-## 测试:扩展示例
+## Testing: extended example
-现在让我们扩展这个例子,并添加更多细节,看下如何测试不同部分。
+Now let's extend this example and add more details to see how to test different parts.
-### 扩展后的 **FastAPI** app 文件
+### Extended **FastAPI** app file
-让我们继续之前的文件结构:
+Let's continue with the same file structure as before:
```
.
@@ -102,13 +102,13 @@
│ └── test_main.py
```
-假设现在包含**FastAPI** app的文件 `main.py` 有些其他**路径操作**。
+Let's say that now the file `main.py` with your **FastAPI** app has some other **path operations**.
-有个 `GET` 操作会返回错误。
+It has a `GET` operation that could return an error.
-有个 `POST` 操作会返回一些错误。
+It has a `POST` operation that could return several errors.
-所有*路径操作* 都需要一个`X-Token` 头。
+Both *path operations* require an `X-Token` header.
=== "Python 3.10+"
@@ -146,36 +146,36 @@
{!> ../../../docs_src/app_testing/app_b/main.py!}
```
-### 扩展后的测试文件
+### Extended testing file
-然后您可以使用扩展后的测试更新`test_main.py`:
+You could then update `test_main.py` with the extended tests:
```Python
{!> ../../../docs_src/app_testing/app_b/test_main.py!}
```
-每当你需要客户端在请求中传递信息,但你不知道如何传递时,你可以通过搜索(谷歌)如何用 `httpx`做,或者是用 `requests` 做,毕竟HTTPX的设计是基于Requests的设计的。
+Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `httpx`, or even how to do it with `requests`, as HTTPX's design is based on Requests' design.
-接着只需在测试中同样操作。
+Then you just do the same in your tests.
-示例:
+E.g.:
-* 传一个*路径* 或*查询* 参数,添加到URL上。
-* 传一个JSON体,传一个Python对象(例如一个`dict`)到参数 `json`。
-* 如果你需要发送 *Form Data* 而不是 JSON,使用 `data` 参数。
-* 要发送 *headers*,传 `dict` 给 `headers` 参数。
-* 对于 *cookies*,传 `dict` 给 `cookies` 参数。
+* To pass a *path* or *query* parameter, add it to the URL itself.
+* To pass a JSON body, pass a Python object (e.g. a `dict`) to the parameter `json`.
+* If you need to send *Form Data* instead of JSON, use the `data` parameter instead.
+* To pass *headers*, use a `dict` in the `headers` parameter.
+* For *cookies*, a `dict` in the `cookies` parameter.
-关于如何传数据给后端的更多信息 (使用`httpx` 或 `TestClient`),请查阅 HTTPX 文档.
+For more information about how to pass data to the backend (using `httpx` or the `TestClient`) check the HTTPX documentation.
-!!! 信息
- 注意 `TestClient` 接收可以被转化为JSON的数据,而不是Pydantic模型。
+!!! info
+ Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models.
- 如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON Compatible Encoder](encoder.md){.internal-link target=_blank}介绍的`jsonable_encoder` 。
+ If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the `jsonable_encoder` described in [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
-## 运行起来
+## Run it
-之后,你只需要安装 `pytest`:
+After that, you just need to install `pytest`:
from starlette.responses import JSONResponse。
```
+。
+
=== "Python 3.9+"
```Python hl_lines="4 25"
- {!> ../../../docs_src/additional_status_codes/tutorial001_an_py39.py!}
+ !!! warning "警告"
+ 当你直接返回一个像上面例子中的 Response 对象时,它会直接返回。
```
+ 对象时,它会直接返回。
+
=== "Python 3.6+"
@@ -47,23 +53,21 @@ To achieve that, import `JSONResponse`, and return your content there directly,
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4 25"
- {!> ../../../docs_src/additional_status_codes/tutorial001.py!}
+ {!../../../docs_src/additional_status_codes/tutorial001.py!}
```
!!! warning
When you return a `Response` directly, like in the example above, it will be returned directly.
- It won't be serialized with a model, etc.
-
- Make sure it has the data you want it to have, and that the values are valid JSON (if you are using `JSONResponse`).
+ FastAPI 不会用模型等对该响应进行序列化。 确保其中有你想要的数据,且返回的值为合法的 JSON(如果你使用 `JSONResponse` 的话)。
!!! note "Technical Details"
You could also use `from starlette.responses import JSONResponse`.
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `status`.
+ 出于方便,**FastAPI** 为开发者提供同 `starlette.responses` 一样的 `fastapi.responses`。 但是大多数可用的响应都是直接来自 Starlette。 `status` 也是一样。
-## OpenAPI and API docs
+## OpenAPI 和 API 文档
-If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know beforehand what you are going to return.
+如果你直接返回额外的状态码和响应,它们不会包含在 OpenAPI 方案(API 文档)中,因为 FastAPI 没办法预先知道你要返回什么。
-But you can document that in your code, using: [Additional Responses](additional-responses.md){.internal-link target=_blank}.
+但是你可以使用 [额外的响应](additional-responses.md){.internal-link target=_blank} 在代码中记录这些内容。
From f70e7ce53198dba258b2671f46c7bb03093dd42e Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:39 +0800
Subject: [PATCH 105/163] New translations custom-response.md (Chinese
Simplified)
---
docs/zh/docs/advanced/custom-response.md | 154 ++++++++++++-----------
1 file changed, 81 insertions(+), 73 deletions(-)
diff --git a/docs/zh/docs/advanced/custom-response.md b/docs/zh/docs/advanced/custom-response.md
index e3876f2928643..cc557dfde50ca 100644
--- a/docs/zh/docs/advanced/custom-response.md
+++ b/docs/zh/docs/advanced/custom-response.md
@@ -1,31 +1,31 @@
-# Custom Response - HTML, Stream, File, others
+# 自定义响应 - HTML,流,文件和其他
-By default, **FastAPI** will return the responses using `JSONResponse`.
+**FastAPI** 默认会使用 `JSONResponse` 返回响应。
-You can override it by returning a `Response` directly as seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}.
+你可以通过直接返回 `Response` 来重载它,参见 [直接返回响应](response-directly.md){.internal-link target=_blank}。
-But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type` as part of the generated OpenAPI).
+但如果你直接返回 `Response`,返回数据不会自动转换,也不会自动生成文档(例如,在 HTTP 头 `Content-Type` 中包含特定的「媒体类型」作为生成的 OpenAPI 的一部分)。
-But you can also declare the `Response` that you want to be used, in the *path operation decorator*.
+你还可以在 *路径操作装饰器* 中声明你想用的 `Response`。
-The contents that you return from your *path operation function* will be put inside of that `Response`.
+你从 *路径操作函数* 中返回的内容将被放在该 `Response` 中。
-And if that `Response` has a JSON media type (`application/json`), like is the case with the `JSONResponse` and `UJSONResponse`, the data you return will be automatically converted (and filtered) with any Pydantic `response_model` that you declared in the *path operation decorator*.
+并且如果该 `Response` 有一个 JSON 媒体类型(`application/json`),比如使用 `JSONResponse` 或者 `UJSONResponse` 的时候,返回的数据将使用你在路径操作装饰器中声明的任何 Pydantic 的 `response_model` 自动转换(和过滤)。
!!! note
If you use a response class with no media type, FastAPI will expect your response to have no content, so it will not document the response format in its generated OpenAPI docs.
-## Use `ORJSONResponse`
+## 使用 `ORJSONResponse`
-For example, if you are squeezing performance, you can install and use `orjson` and set the response to be `ORJSONResponse`.
+例如,如果你需要压榨性能,你可以安装并使用 `orjson` 并将响应设置为 `ORJSONResponse`。
-Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
+导入你想要使用的 `Response` 类(子类)然后在 *路径操作装饰器* 中声明它。
For large responses, returning a `Response` directly is much faster than returning a dictionary.
This is because by default, FastAPI will inspect every item inside and make sure it is serializable with JSON, using the same [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} explained in the tutorial. This is what allows you to return **arbitrary objects**, for example database models.
-But if you are certain that the content that you are returning is **serializable with JSON**, you can pass it directly to the response class and avoid the extra overhead that FastAPI would have by passing your return content through the `jsonable_encoder` before passing it to the response class.
+使用 `HTMLResponse` 来从 **FastAPI** 中直接返回一个 HTML 响应。
```Python hl_lines="2 7"
{!../../../docs_src/custom_response/tutorial001b.py!}
@@ -34,19 +34,20 @@ But if you are certain that the content that you are returning is **serializable
!!! info
The parameter `response_class` will also be used to define the "media type" of the response.
- In this case, the HTTP header `Content-Type` will be set to `application/json`.
+ 在这个例子中,HTTP 头的 `Content-Type` 会被设置成 `application/json`。
- And it will be documented as such in OpenAPI.
+ 并且在 OpenAPI 文档中也会这样记录。
!!! tip
The `ORJSONResponse` is currently only available in FastAPI, not in Starlette.
-## HTML Response
+## HTML 响应
-To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
+!!! warning "警告"
+ *路径操作函数* 直接返回的 `Response` 不会被 OpenAPI 的文档记录(比如,`Content-Type` 不会被文档记录),并且在自动化交互文档中也是不可见的。
-* Import `HTMLResponse`.
-* Pass `HTMLResponse` as the parameter `response_class` of your *path operation decorator*.
+* 导入 `HTMLResponse`。
+* 将 `HTMLResponse` 作为你的 *路径操作* 的 `response_class` 参数传入。
```Python hl_lines="2 7"
{!../../../docs_src/custom_response/tutorial002.py!}
@@ -55,15 +56,15 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
!!! info
The parameter `response_class` will also be used to define the "media type" of the response.
- In this case, the HTTP header `Content-Type` will be set to `text/html`.
+ 在这个例子中,HTTP 头的 `Content-Type` 会被设置成 `text/html`。
- And it will be documented as such in OpenAPI.
+ 并且在 OpenAPI 文档中也会这样记录。
-### Return a `Response`
+### 返回一个 `Response`
-As seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}, you can also override the response directly in your *path operation*, by returning it.
+正如你在 [直接返回响应](response-directly.md){.internal-link target=_blank} 中了解到的,你也可以通过直接返回响应在 *路径操作* 中直接重载响应。
-The same example from above, returning an `HTMLResponse`, could look like:
+和上面一样的例子,返回一个 `HTMLResponse` 看起来可能是这样:
```Python hl_lines="2 7 19"
{!../../../docs_src/custom_response/tutorial003.py!}
@@ -75,53 +76,53 @@ The same example from above, returning an `HTMLResponse`, could look like:
!!! info
Of course, the actual `Content-Type` header, status code, etc, will come from the `Response` object your returned.
-### Document in OpenAPI and override `Response`
+### OpenAPI 中的文档和重载 `Response`
-If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `response_class` parameter AND return a `Response` object.
+如果你想要在函数内重载响应,但是同时在 OpenAPI 中文档化「媒体类型」,你可以使用 `response_class` 参数并返回一个 `Response` 对象。
-The `response_class` will then be used only to document the OpenAPI *path operation*, but your `Response` will be used as is.
+接着 `response_class` 参数只会被用来文档化 OpenAPI 的 *路径操作*,你的 `Response` 用来返回响应。
-#### Return an `HTMLResponse` directly
+#### 直接返回 `HTMLResponse`
-For example, it could be something like:
+比如像这样:
```Python hl_lines="7 21 23"
{!../../../docs_src/custom_response/tutorial004.py!}
```
-In this example, the function `generate_html_response()` already generates and returns a `Response` instead of returning the HTML in a `str`.
+在这个例子中,函数 `generate_html_response()` 已经生成并返回 `Response` 对象而不是在 `str` 中返回 HTML。
-By returning the result of calling `generate_html_response()`, you are already returning a `Response` that will override the default **FastAPI** behavior.
+通过返回函数 `generate_html_response()` 的调用结果,你已经返回一个重载 **FastAPI** 默认行为的 `Response` 对象,
-But as you passed the `HTMLResponse` in the `response_class` too, **FastAPI** will know how to document it in OpenAPI and the interactive docs as HTML with `text/html`:
+但如果你在 `response_class` 中也传入了 `HTMLResponse`,**FastAPI** 会知道如何在 OpenAPI 和交互式文档中使用 `text/html` 将其文档化为 HTML。
-## Available responses
+## 可用响应
-Here are some of the available responses.
+这里有一些可用的响应。
-Have in mind that you can use `Response` to return anything else, or even create a custom sub-class.
+要记得你可以使用 `Response` 来返回任何其他东西,甚至创建一个自定义的子类。
!!! note "Technical Details"
You could also use `from starlette.responses import HTMLResponse`.
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+ **FastAPI** 提供了同 `fastapi.responses` 相同的 `starlette.responses` 只是为了方便开发者。 但大多数可用的响应都直接来自 Starlette。
### `Response`
-The main `Response` class, all the other responses inherit from it.
+其他全部的响应都继承自主类 `Response`。
-You can return it directly.
+你可以直接返回它。
It accepts the following parameters:
-* `content` - A `str` or `bytes`.
-* `status_code` - An `int` HTTP status code.
-* `headers` - A `dict` of strings.
+* `content` - 一个 `str` 或者 `bytes`。
+* `status_code` - 一个 `int` 类型的 HTTP 状态码。
+* `headers` - 一个由字符串组成的 `dict`。
* `media_type` - A `str` giving the media type. E.g. `"text/html"`.
-FastAPI (actually Starlette) will automatically include a Content-Length header. It will also include a Content-Type header, based on the media_type and appending a charset for text types.
+FastAPI(实际上是 Starlette)将自动包含 Content-Length 的头。 它还将包含一个基于 media_type 的 Content-Type 头,并为文本类型附加一个字符集。
```Python hl_lines="1 18"
{!../../../docs_src/response_directly/tutorial002.py!}
@@ -129,11 +130,11 @@ FastAPI (actually Starlette) will automatically include a Content-Length header.
### `HTMLResponse`
-Takes some text or bytes and returns an HTML response, as you read above.
+如上文所述,接受文本或字节并返回 HTML 响应。
### `PlainTextResponse`
-Takes some text or bytes and returns an plain text response.
+接受文本或字节并返回纯文本响应。
```Python hl_lines="2 7 9"
{!../../../docs_src/custom_response/tutorial005.py!}
@@ -141,20 +142,20 @@ Takes some text or bytes and returns an plain text response.
### `JSONResponse`
-Takes some data and returns an `application/json` encoded response.
+接受数据并返回一个 `application/json` 编码的响应。
-This is the default response used in **FastAPI**, as you read above.
+如上文所述,这是 **FastAPI** 中使用的默认响应。
### `ORJSONResponse`
-A fast alternative JSON response using `orjson`, as you read above.
+如上文所述,`ORJSONResponse` 是一个使用 `orjson` 的快速的可选 JSON 响应。
### `UJSONResponse`
-An alternative JSON response using `ujson`.
+`UJSONResponse` 是一个使用 `ujson` 的可选 JSON 响应。
-!!! warning
- `ujson` is less careful than Python's built-in implementation in how it handles some edge-cases.
+!!! !!! warning "警告"
+ 在处理某些边缘情况时,`ujson` 不如 Python 的内置实现那么谨慎。
```Python hl_lines="2 7"
{!../../../docs_src/custom_response/tutorial001.py!}
@@ -165,9 +166,10 @@ An alternative JSON response using `orjson`, but with some custom settings not used in the included `ORJSONResponse` class.
+!!! tip "小贴士"
+ `ORJSONResponse` 可能是一个更快的选择。
Let's say you want it to return indented and formatted JSON, so you want to use the orjson option `orjson.OPT_INDENT_2`.
@@ -282,11 +287,14 @@ Of course, you will probably find much better ways to take advantage of this tha
## Default response class
-When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
+!!! note "说明"
+ 如果你使用不带有任何媒体类型的响应类,FastAPI 认为你的响应没有任何内容,所以不会在生成的OpenAPI文档中记录响应格式。
-The parameter that defines this is `default_response_class`.
+!!! info "提示"
+ 参数 `response_class` 也会用来定义响应的「媒体类型」。
-In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
+!!! tip "小贴士"
+ `ORJSONResponse` 目前只在 FastAPI 中可用,而在 Starlette 中不可用。
```Python hl_lines="2 4"
{!../../../docs_src/custom_response/tutorial010.py!}
@@ -295,6 +303,6 @@ In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *
!!! tip
You can still override `response_class` in *path operations* as before.
-## Additional documentation
+## 额外文档
-You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
+您还可以使用 `response` 在 OpenAPI 中声明媒体类型和许多其他详细信息:[OpenAPI 中的额外文档](additional-responses.md){.internal-link target=_blank}。
From 2c1aaf3050b2f9a66c17ecabf2dafbaacf70b917 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:42 +0800
Subject: [PATCH 106/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/advanced/index.md | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/docs/zh/docs/advanced/index.md b/docs/zh/docs/advanced/index.md
index 467f0833e60a6..c042c1d32422c 100644
--- a/docs/zh/docs/advanced/index.md
+++ b/docs/zh/docs/advanced/index.md
@@ -1,21 +1,21 @@
-# Advanced User Guide
+# 高级用户指南
-## Additional Features
+## 额外特性
-The main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank} should be enough to give you a tour through all the main features of **FastAPI**.
+主要的教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 应该足以让你了解 **FastAPI** 的所有主要特性。
-In the next sections you will see other options, configurations, and additional features.
+你会在接下来的章节中了解到其他的选项、配置以及额外的特性。
-!!! tip
- The next sections are **not necessarily "advanced"**.
+!!! !!! tip
+ 接下来的章节**并不一定是**「高级的」。
- And it's possible that for your use case, the solution is in one of them.
+ 而且对于你的使用场景来说,解决方案很可能就在其中。
-## Read the Tutorial first
+## 先阅读教程
-You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank}.
+你可能仍会用到 **FastAPI** 主教程 [教程 - 用户指南](../tutorial/){.internal-link target=_blank} 中的大多数特性。
-And the next sections assume you already read it, and assume that you know those main ideas.
+接下来的章节我们认为你已经读过 [教程 - 用户指南](../tutorial/){.internal-link target=_blank},并且假设你已经知晓其中主要思想。
## TestDriven.io course
From c49afbafb69f21899452240094bbf9b20894e908 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:45 +0800
Subject: [PATCH 107/163] New translations
path-operation-advanced-configuration.md (Chinese Simplified)
---
.../path-operation-advanced-configuration.md | 38 +++++++++----------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/docs/zh/docs/advanced/path-operation-advanced-configuration.md b/docs/zh/docs/advanced/path-operation-advanced-configuration.md
index f8bffadf4ffcf..b9cbd79f35f9d 100644
--- a/docs/zh/docs/advanced/path-operation-advanced-configuration.md
+++ b/docs/zh/docs/advanced/path-operation-advanced-configuration.md
@@ -1,11 +1,11 @@
-# Path Operation Advanced Configuration
+# 路径操作的高级配置
-## OpenAPI operationId
+## OpenAPI 的 operationId
-!!! warning
- If you are not an "expert" in OpenAPI, you probably don't need this.
+!!! !!! warning
+ 如果你并非 OpenAPI 的「专家」,你可能不需要这部分内容。
-You can set the OpenAPI `operationId` to be used in your *path operation* with the parameter `operation_id`.
+你可以在路径操作中通过参数 `operation_id` 设置要使用的 OpenAPI `operationId`。
You would have to make sure that it is unique for each operation.
@@ -13,39 +13,39 @@ You would have to make sure that it is unique for each operation.
{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
```
-### Using the *path operation function* name as the operationId
+### 使用 *路径操作函数* 的函数名作为 operationId
-If you want to use your APIs' function names as `operationId`s, you can iterate over all of them and override each *path operation's* `operation_id` using their `APIRoute.name`.
+如果你想用你的 API 的函数名作为 `operationId` 的名字,你可以遍历一遍 API 的函数名,然后使用他们的 `APIRoute.name` 重写每个 *路径操作* 的 `operation_id`。
-You should do it after adding all your *path operations*.
+你应该在添加了所有 *路径操作* 之后执行此操作。
```Python hl_lines="2 12-21 24"
{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
```
-!!! tip
- If you manually call `app.openapi()`, you should update the `operationId`s before that.
+!!! !!! tip
+ 如果你手动调用 `app.openapi()`,你应该在此之前更新 `operationId`。
-!!! warning
- If you do this, you have to make sure each one of your *path operation functions* has a unique name.
+!!! !!! warning
+ 如果你这样做,务必确保你的每个 *路径操作函数* 的名字唯一。
- Even if they are in different modules (Python files).
+ 即使它们在不同的模块中(Python 文件)。
-## Exclude from OpenAPI
+## 从 OpenAPI 中排除
-To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`:
+使用参数 `include_in_schema` 并将其设置为 `False` ,来从生成的 OpenAPI 方案中排除一个 *路径操作*(这样一来,就从自动化文档系统中排除掉了)。
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
```
-## Advanced description from docstring
+## docstring 的高级描述
-You can limit the lines used from the docstring of a *path operation function* for OpenAPI.
+你可以限制 *路径操作函数* 的 `docstring` 中用于 OpenAPI 的行数。
-Adding an `\f` (an escaped "form feed" character) causes **FastAPI** to truncate the output used for OpenAPI at this point.
+添加一个 `\f` (一个「换页」的转义字符)可以使 **FastAPI** 在那一位置截断用于 OpenAPI 的输出。
-It won't show up in the documentation, but other tools (such as Sphinx) will be able to use the rest.
+剩余部分不会出现在文档中,但是其他工具(比如 Sphinx)可以使用剩余部分。
```Python hl_lines="19-29"
{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
From c4b9a67ac002e232216ff7ff9212c14b3ae7a707 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:46 +0800
Subject: [PATCH 108/163] New translations response-change-status-code.md
(Chinese Simplified)
---
.../advanced/response-change-status-code.md | 30 +++++++++----------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md
index 979cef3f05367..3bc41be37ad22 100644
--- a/docs/zh/docs/advanced/response-change-status-code.md
+++ b/docs/zh/docs/advanced/response-change-status-code.md
@@ -1,33 +1,33 @@
-# Response - Change Status Code
+# 响应 - 更改状态码
-You probably read before that you can set a default [Response Status Code](../tutorial/response-status-code.md){.internal-link target=_blank}.
+你可能之前已经了解到,你可以设置默认的[响应状态码](../tutorial/response-status-code.md){.internal-link target=_blank}。
-But in some cases you need to return a different status code than the default.
+但在某些情况下,你需要返回一个不同于默认值的状态码。
-## Use case
+## 使用场景
-For example, imagine that you want to return an HTTP status code of "OK" `200` by default.
+例如,假设你想默认返回一个HTTP状态码为“OK”`200`。
-But if the data didn't exist, you want to create it, and return an HTTP status code of "CREATED" `201`.
+但如果数据不存在,你想创建它,并返回一个HTTP状态码为“CREATED”`201`。
-But you still want to be able to filter and convert the data you return with a `response_model`.
+但你仍然希望能够使用`response_model`过滤和转换你返回的数据。
-For those cases, you can use a `Response` parameter.
+对于这些情况,你可以使用一个`Response`参数。
-## Use a `Response` parameter
+## 使用 `Response` 参数
-You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies and headers).
+你可以在你的*路径操作函数*中声明一个`Response`类型的参数(就像你可以为cookies和头部做的那样)。
-And then you can set the `status_code` in that *temporal* response object.
+然后你可以在这个*临时*响应对象中设置`status_code`。
```Python hl_lines="1 9 12"
{!../../../docs_src/response_change_status_code/tutorial001.py!}
```
-And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
+然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。
-And if you declared a `response_model`, it will still be used to filter and convert the object you returned.
+如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
-**FastAPI** will use that *temporal* response to extract the status code (also cookies and headers), and will put them in the final response that contains the value you returned, filtered by any `response_model`.
+**FastAPI**将使用这个临时响应来提取状态码(也包括cookies和头部),并将它们放入包含你返回的值的最终响应中,该响应由任何`response_model`过滤。
-You can also declare the `Response` parameter in dependencies, and set the status code in them. But have in mind that the last one to be set will win.
+你也可以在依赖项中声明`Response`参数,并在其中设置状态码。 但请注意,最后设置的状态码将会生效。
From c2adc5e25076dfa3b6e9178bdc89359d9b335e59 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:49 +0800
Subject: [PATCH 109/163] New translations response-cookies.md (Chinese
Simplified)
---
docs/zh/docs/advanced/response-cookies.md | 42 +++++++++++------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md
index 328094c9b5f7a..810119ea8a6eb 100644
--- a/docs/zh/docs/advanced/response-cookies.md
+++ b/docs/zh/docs/advanced/response-cookies.md
@@ -1,8 +1,8 @@
-# Response Cookies
+# 响应Cookies
-## Use a `Response` parameter
+## 使用 `Response` 参数
-You can declare a parameter of type `Response` in your *path operation function*.
+你可以在 *路径函数* 中定义一个类型为 `Response`的参数,这样你就可以在这个临时响应对象中设置cookie了。
And then you can set cookies in that *temporal* response object.
@@ -10,40 +10,40 @@ And then you can set cookies in that *temporal* response object.
{!../../../docs_src/response_cookies/tutorial002.py!}
```
-And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
+而且你还可以根据你的需要响应不同的对象,比如常用的 `dict`,数据库model等。
-And if you declared a `response_model`, it will still be used to filter and convert the object you returned.
+如果你定义了 `response_model`,程序会自动根据`response_model`来过滤和转换你响应的对象。
-**FastAPI** will use that *temporal* response to extract the cookies (also headers and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`.
+**FastAPI** 会使用这个 *临时* 响应对象去装在这些cookies信息 (同样还有headers和状态码等信息), 最终会将这些信息和通过`response_model`转化过的数据合并到最终的响应里。
-You can also declare the `Response` parameter in dependencies, and set cookies (and headers) in them.
+你还可以在直接响应`Response`时直接创建cookies。
-## Return a `Response` directly
+## 直接响应 `Response`
-You can also create cookies when returning a `Response` directly in your code.
+你也可以在depend中定义`Response`参数,并设置cookie和header。
-To do that, you can create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank}.
+你可以参考[Return a Response Directly](response-directly.md){.internal-link target=_blank}来创建response
-Then set Cookies in it, and then return it:
+然后设置Cookies,并返回:
```Python hl_lines="10-12"
{!../../../docs_src/response_cookies/tutorial001.py!}
```
-!!! tip
- Have in mind that if you return a response directly instead of using the `Response` parameter, FastAPI will return it directly.
+!!! !!! tip
+ 需要注意,如果你直接反馈一个response对象,而不是使用`Response`入参,FastAPI则会直接反馈你封装的response对象。
- So, you will have to make sure your data is of the correct type. E.g. it is compatible with JSON, if you are returning a `JSONResponse`.
+ So, you will have to make sure your data is of the correct type. E.g. 所以你需要确保你响应数据类型的正确性,如:你可以使用`JSONResponse`来兼容JSON的场景。
- And also that you are not sending any data that should have been filtered by a `response_model`.
+ 同时,你也应当仅反馈通过`response_model`过滤过的数据。
-### More info
+### 更多信息
-!!! note "Technical Details"
- You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
+!!! !!! note "技术细节"
+ 你也可以使用`from starlette.responses import Response` 或者 `from starlette.responses import JSONResponse`。
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+ 为了方便开发者,**FastAPI** 封装了相同数据类型,如`starlette.responses` 和 `fastapi.responses`。 不过大部分response对象都是直接引用自Starlette。
- And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
+ 因为`Response`对象可以非常便捷的设置headers和cookies,所以 **FastAPI** 同时也封装了`fastapi.Response`。
-To see all the available parameters and options, check the documentation in Starlette.
+如果你想查看所有可用的参数和选项,可以参考 Starlette帮助文档
From e1ce77d720f5ae10dcd7d40aca19c98b37696c40 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:50 +0800
Subject: [PATCH 110/163] New translations response-directly.md (Chinese
Simplified)
---
docs/zh/docs/advanced/response-directly.md | 56 +++++++++++-----------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md
index 8836140ecf7ee..bd26889d9f64d 100644
--- a/docs/zh/docs/advanced/response-directly.md
+++ b/docs/zh/docs/advanced/response-directly.md
@@ -1,63 +1,63 @@
-# Return a Response Directly
+# 直接返回响应
-When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc.
+当你创建一个 **FastAPI** *路径操作* 时,你可以正常返回以下任意一种数据:`dict`,`list`,Pydantic 模型,数据库模型等等。
-By default, **FastAPI** would automatically convert that return value to JSON using the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
+**FastAPI** 默认会使用 `jsonable_encoder` 将这些类型的返回值转换成 JSON 格式,`jsonable_encoder` 在 [JSON 兼容编码器](../tutorial/encoder.md){.internal-link target=_blank} 中有阐述。
-Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a `JSONResponse` that would be used to send the response to the client.
+然后,**FastAPI** 会在后台将这些兼容 JSON 的数据(比如字典)放到一个 `JSONResponse` 中,该 `JSONResponse` 会用来发送响应给客户端。
-But you can return a `JSONResponse` directly from your *path operations*.
+但是你可以在你的 *路径操作* 中直接返回一个 `JSONResponse`。
-It might be useful, for example, to return custom headers or cookies.
+直接返回响应可能会有用处,比如返回自定义的响应头和 cookies。
-## Return a `Response`
+## 返回 `Response`
-In fact, you can return any `Response` or any sub-class of it.
+事实上,你可以返回任意 `Response` 或者任意 `Response` 的子类。
-!!! tip
- `JSONResponse` itself is a sub-class of `Response`.
+!!! !!! tip "小贴士"
+ `JSONResponse` 本身是一个 `Response` 的子类。
-And when you return a `Response`, **FastAPI** will pass it directly.
+当你返回一个 `Response` 时,**FastAPI** 会直接传递它。
It won't do any data conversion with Pydantic models, it won't convert the contents to any type, etc.
-This gives you a lot of flexibility. You can return any data type, override any data declaration or validation, etc.
+这种特性给你极大的可扩展性。 你可以返回任何数据类型,重写任何数据声明或者校验,等等。
-## Using the `jsonable_encoder` in a `Response`
+## 在 `Response` 中使用 `jsonable_encoder`
-Because **FastAPI** doesn't do any change to a `Response` you return, you have to make sure it's contents are ready for it.
+由于 **FastAPI** 并未对你返回的 `Response` 做任何改变,你必须确保你已经准备好响应内容。
-For example, you cannot put a Pydantic model in a `JSONResponse` without first converting it to a `dict` with all the data types (like `datetime`, `UUID`, etc) converted to JSON-compatible types.
+例如,如果不首先将 Pydantic 模型转换为 `dict`,并将所有数据类型(如 `datetime`、`UUID` 等)转换为兼容 JSON 的类型,则不能将其放入JSONResponse中。
-For those cases, you can use the `jsonable_encoder` to convert your data before passing it to a response:
+对于这些情况,在将数据传递给响应之前,你可以使用 `jsonable_encoder` 来转换你的数据。
```Python hl_lines="6-7 21-22"
{!../../../docs_src/response_directly/tutorial001.py!}
```
-!!! note "Technical Details"
- You could also use `from starlette.responses import JSONResponse`.
+!!! !!! note "技术细节"
+ 你也可以使用 `from starlette.responses import JSONResponse`。
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+ 出于方便,**FastAPI** 会提供与 `starlette.responses` 相同的 `fastapi.responses` 给开发者。 但是大多数可用的响应都直接来自 Starlette。
-## Returning a custom `Response`
+## 返回自定义 `Response`
-The example above shows all the parts you need, but it's not very useful yet, as you could have just returned the `item` directly, and **FastAPI** would put it in a `JSONResponse` for you, converting it to a `dict`, etc. All that by default.
+上面的例子展示了需要的所有部分,但还不够实用,因为你本可以只是直接返回 `item`,而**FastAPI** 默认帮你把这个 `item` 放到 `JSONResponse` 中,又默认将其转换成了 `dict`等等。 All that by default.
-Now, let's see how you could use that to return a custom response.
+现在,让我们看看你如何才能返回一个自定义的响应。
-Let's say that you want to return an XML response.
+假设你想要返回一个 XML 响应。
-You could put your XML content in a string, put it in a `Response`, and return it:
+你可以把你的 XML 内容放到一个字符串中,放到一个 `Response` 中,然后返回。
```Python hl_lines="1 18"
{!../../../docs_src/response_directly/tutorial002.py!}
```
-## Notes
+## 说明
-When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically.
+当你直接返回 `Response` 时,它的数据既没有校验,又不会进行转换(序列化),也不会自动生成文档。
-But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
+但是你仍可以参考 [OpenApI 中的额外响应](additional-responses.md){.internal-link target=_blank} 给响应编写文档。
-You can see in later sections how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc.
+在后续的章节中你可以了解到如何使用/声明这些自定义的 `Response` 的同时还保留自动化的数据转换和文档等。
From 5575fd90f6d58c658092a0c72660904f053ba6bc Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:51 +0800
Subject: [PATCH 111/163] New translations response-headers.md (Chinese
Simplified)
---
docs/zh/docs/advanced/response-headers.md | 32 +++++++++++------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md
index 99c280024f59d..6ff939767b495 100644
--- a/docs/zh/docs/advanced/response-headers.md
+++ b/docs/zh/docs/advanced/response-headers.md
@@ -1,42 +1,42 @@
-# Response Headers
+# 响应头
-## Use a `Response` parameter
+## 使用 `Response` 参数
-You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies).
+你可以在你的*路径操作函数*中声明一个`Response`类型的参数(就像你可以为cookies做的那样)。
-And then you can set headers in that *temporal* response object.
+然后你可以在这个*临时*响应对象中设置头部。
```Python hl_lines="1 7-8"
{!../../../docs_src/response_headers/tutorial002.py!}
```
-And then you can return any object you need, as you normally would (a `dict`, a database model, etc).
+然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。
-And if you declared a `response_model`, it will still be used to filter and convert the object you returned.
+如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。
-**FastAPI** will use that *temporal* response to extract the headers (also cookies and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`.
+**FastAPI**将使用这个临时响应来提取头部(也包括cookies和状态码),并将它们放入包含你返回的值的最终响应中,该响应由任何`response_model`过滤。
-You can also declare the `Response` parameter in dependencies, and set headers (and cookies) in them.
+你也可以在直接返回`Response`时添加头部。
-## Return a `Response` directly
+## 直接返回 `Response`
You can also add headers when you return a `Response` directly.
-Create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank} and pass the headers as an additional parameter:
+按照[直接返回响应](response-directly.md){.internal-link target=_blank}中所述创建响应,并将头部作为附加参数传递:
```Python hl_lines="10-12"
{!../../../docs_src/response_headers/tutorial001.py!}
```
-!!! note "Technical Details"
- You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
+!!! !!! 注意 "技术细节"
+ 你也可以使用`from starlette.responses import Response`或`from starlette.responses import JSONResponse`。
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+ **FastAPI**提供了与`fastapi.responses`相同的`starlette.responses`,只是为了方便开发者。 但是,大多数可用的响应都直接来自Starlette。
- And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
+ 由于`Response`经常用于设置头部和cookies,因此**FastAPI**还在`fastapi.Response`中提供了它。
-## Custom Headers
+## 自定义头部
Have in mind that custom proprietary headers can be added using the 'X-' prefix.
-But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in Starlette's CORS docs.
+但是,如果你有自定义头部,你希望浏览器中的客户端能够看到它们,你需要将它们添加到你的CORS配置中(在[CORS(跨源资源共享)](../tutorial/cors.md){.internal-link target=_blank}中阅读更多),使用在Starlette的CORS文档中记录的`expose_headers`参数。
From 2aab3b1039ab31b67793bf6a94c17efded7f54a1 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:52 +0800
Subject: [PATCH 112/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/advanced/security/index.md | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/docs/zh/docs/advanced/security/index.md b/docs/zh/docs/advanced/security/index.md
index c18baf64b0d27..4cae9655474f7 100644
--- a/docs/zh/docs/advanced/security/index.md
+++ b/docs/zh/docs/advanced/security/index.md
@@ -1,16 +1,16 @@
-# Advanced Security
+# 高级安全
-## Additional Features
+## 附加特性
-There are some extra features to handle security apart from the ones covered in the [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
+除 [教程 - 用户指南: 安全性](../../tutorial/security/){.internal-link target=_blank} 中涵盖的功能之外,还有一些额外的功能来处理安全性.
-!!! tip
- The next sections are **not necessarily "advanced"**.
+!!! !!! tip "小贴士"
+ 接下来的章节 **并不一定是 "高级的"**.
- And it's possible that for your use case, the solution is in one of them.
+ 而且对于你的使用场景来说,解决方案很可能就在其中。
-## Read the Tutorial first
+## 先阅读教程
-The next sections assume you already read the main [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
+接下来的部分假设你已经阅读了主要的 [教程 - 用户指南: 安全性](../../tutorial/security/){.internal-link target=_blank}.
-They are all based on the same concepts, but allow some extra functionalities.
+它们都基于相同的概念,但支持一些额外的功能.
From 99f54ec9adb27fc25ace18780f97f5e9df7e5f88 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:54 +0800
Subject: [PATCH 113/163] New translations settings.md (Chinese Simplified)
---
docs/zh/docs/advanced/settings.md | 276 ++++++++++++++++--------------
1 file changed, 148 insertions(+), 128 deletions(-)
diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md
index a4a773b1fdeaf..d37bf11e79479 100644
--- a/docs/zh/docs/advanced/settings.md
+++ b/docs/zh/docs/advanced/settings.md
@@ -1,29 +1,29 @@
-# Settings and Environment Variables
+# 设置和环境变量
-In many cases your application could need some external settings or configurations, for example secret keys, database credentials, credentials for email services, etc.
+在许多情况下,您的应用程序可能需要一些外部设置或配置,例如密钥、数据库凭据、电子邮件服务的凭据等等。
-Most of these settings are variable (can change), like database URLs. And many could be sensitive, like secrets.
+这些设置中的大多数是可变的(可以更改的),比如数据库的 URL。 而且许多设置可能是敏感的,比如密钥。
-For this reason it's common to provide them in environment variables that are read by the application.
+因此,通常会将它们提供为由应用程序读取的环境变量。
-## Environment Variables
+## 环境变量
-!!! tip
- If you already know what "environment variables" are and how to use them, feel free to skip to the next section below.
+!!! !!! tip
+ 如果您已经知道什么是"环境变量"以及如何使用它们,请随意跳到下面的下一节。
-An environment variable (also known as "env var") is a variable that lives outside of the Python code, in the operating system, and could be read by your Python code (or by other programs as well).
+环境变量(也称为"env var")是一种存在于 Python 代码之外、存在于操作系统中的变量,可以被您的 Python 代码(或其他程序)读取。
-You can create and use environment variables in the shell, without needing Python:
+您可以在 shell 中创建和使用环境变量,而无需使用 Python:
-=== "Linux, macOS, Windows Bash"
+=== "Linux、macOS、Windows Bash"
@lru_cache()。
```
+。
+
-!!! tip
- If you want something quick to copy and paste, don't use this example, use the last one below.
+!!! !!! tip
+ 如果您需要一个快速的复制粘贴示例,请不要使用此示例,而应使用下面的最后一个示例。
-Then, when you create an instance of that `Settings` class (in this case, in the `settings` object), Pydantic will read the environment variables in a case-insensitive way, so, an upper-case variable `APP_NAME` will still be read for the attribute `app_name`.
+然后,当您创建该 `Settings` 类的实例(在此示例中是 `settings` 对象)时,Pydantic 将以不区分大小写的方式读取环境变量,因此,大写的变量 `APP_NAME` 仍将为属性 `app_name` 读取。
-Next it will convert and validate the data. So, when you use that `settings` object, you will have data of the types you declared (e.g. `items_per_user` will be an `int`).
+然后,它将转换和验证数据。 因此,当您使用该 `settings` 对象时,您将获得您声明的类型的数据(例如 `items_per_user` 将为 `int` 类型)。
-### Use the `settings`
+### 创建 `Settings` 对象
-Then you can use the new `settings` object in your application:
+然后,您可以在应用程序中使用新的 `settings` 对象:
```Python hl_lines="18-20"
{!../../../docs_src/settings/tutorial001.py!}
```
-### Run the server
+### 运行服务器
-Next, you would run the server passing the configurations as environment variables, for example you could set an `ADMIN_EMAIL` and `APP_NAME` with:
+接下来,您将运行服务器,并将配置作为环境变量传递。 例如,您可以设置一个 `ADMIN_EMAIL` 和 `APP_NAME`,如下所示:
__init__.py 的文件,就像您在Bigger Applications - Multiple Files{.internal-link target=_blank}中看到的那样。
```
+ 的文件,就像您在[Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}中看到的那样。
+
-
- !!! tip
- The `Config` class is used just for Pydantic configuration. You can read more at Pydantic Model Config.
+ !!! !!! tip
+ Config 类仅用于 Pydantic 配置。 您可以在Pydantic Model Config中阅读更多相关信息。
+
!!! info
In Pydantic version 1 the configuration was done in an internal class `Config`, in Pydantic version 2 it's done in an attribute `model_config`. This attribute takes a `dict`, and to get autocompletion and inline errors you can import and use `SettingsConfigDict` to define that `dict`.
-Here we define the config `env_file` inside of your Pydantic `Settings` class, and set the value to the filename with the dotenv file we want to use.
+在这里,我们在 Pydantic 的 `Settings` 类中创建了一个名为 `Config` 的类,并将 `env_file` 设置为我们想要使用的 dotenv 文件的文件名。
-### Creating the `Settings` only once with `lru_cache`
+### 使用 `lru_cache` 仅创建一次 `Settings`
-Reading a file from disk is normally a costly (slow) operation, so you probably want to do it only once and then re-use the same settings object, instead of reading it for each request.
+从磁盘中读取文件通常是一项耗时的(慢)操作,因此您可能希望仅在首次读取后并重复使用相同的设置对象,而不是为每个请求都读取它。
-But every time we do:
+但是,每次执行以下操作:
```Python
Settings()
```
-a new `Settings` object would be created, and at creation it would read the `.env` file again.
+都会创建一个新的 `Settings` 对象,并且在创建时会再次读取 `.env` 文件。
-If the dependency function was just like:
+如果依赖项函数只是这样的:
```Python
def get_settings():
return Settings()
```
-we would create that object for each request, and we would be reading the `.env` file for each request. ⚠️
+我们将为每个请求创建该对象,并且将在每个请求中读取 `.env` 文件。 ⚠️
But as we are using the `@lru_cache()` decorator on top, the `Settings` object will be created only once, the first time it's called. ✔️
@@ -406,24 +413,24 @@ But as we are using the `@lru_cache()` decorator on top, the `Settings` object w
{!> ../../../docs_src/settings/app03_an/main.py!}
```
-=== "Python 3.6+ non-Annotated"
+=== "Python 3.6+ 非注解版本"
- !!! tip
- Prefer to use the `Annotated` version if possible.
+ !!! !!! tip
+ 如果可能,请尽量使用 `Annotated` 版本。
```Python hl_lines="1 10"
{!> ../../../docs_src/settings/app03/main.py!}
```
-Then for any subsequent calls of `get_settings()` in the dependencies for the next requests, instead of executing the internal code of `get_settings()` and creating a new `Settings` object, it will return the same object that was returned on the first call, again and again.
+然后,在下一次请求的依赖项中对 `get_settings()` 进行任何后续调用时,它不会执行 `get_settings()` 的内部代码并创建新的 `Settings` 对象,而是返回在第一次调用时返回的相同对象,一次又一次。
-#### `lru_cache` Technical Details
+#### `lru_cache` 技术细节
-`@lru_cache()` modifies the function it decorates to return the same value that was returned the first time, instead of computing it again, executing the code of the function every time.
+`@lru_cache()` 修改了它所装饰的函数,以返回第一次返回的相同值,而不是再次计算它,每次都执行函数的代码。
-So, the function below it will be executed once for each combination of arguments. And then the values returned by each of those combinations of arguments will be used again and again whenever the function is called with exactly the same combination of arguments.
+因此,下面的函数将对每个参数组合执行一次。 然后,每个参数组合返回的值将在使用完全相同的参数组合调用函数时再次使用。
-For example, if you have a function:
+例如,如果您有一个函数:
```Python
@lru_cache()
@@ -431,7 +438,7 @@ def say_hi(name: str, salutation: str = "Ms."):
return f"Hello {salutation} {name}"
```
-your program could execute like this:
+您的程序可以像这样执行:
```mermaid
sequenceDiagram
@@ -442,23 +449,36 @@ participant execute as Execute function
rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Camila")
- function ->> execute: execute function code
- execute ->> code: return the result
+ function ->> execute: 执行函数代码
+ execute ->> code: 返回结果
end
rect rgba(0, 255, 255, .1)
code ->> function: say_hi(name="Camila")
- function ->> code: return stored result
+ function ->> code: 返回存储的结果
end
rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Rick")
- function ->> execute: execute function code
- execute ->> code: return the result
+ function ->> execute: 执行函数代码
+ execute ->> code: 返回结果
end
rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Rick", salutation="Mr.")
+ function ->> execute: 执行函数代码
+ execute ->> code: 返回结果
+ end
+
+ rect rgba(0, 255, 255, .1)
+ code ->> function: say_hi(name="Rick")
+ function ->> code: 返回存储的结果
+ end
+
+ rect rgba(0, 255, 255, .1)
+ code ->> function: say_hi(name="Camila")
+ function ->> code: 返回存储的结果
+ end
function ->> execute: execute function code
execute ->> code: return the result
end
@@ -474,16 +494,16 @@ participant execute as Execute function
end
```
-In the case of our dependency `get_settings()`, the function doesn't even take any arguments, so it always returns the same value.
+对于我们的依赖项 `get_settings()`,该函数甚至不接受任何参数,因此它始终返回相同的值。
-That way, it behaves almost as if it was just a global variable. But as it uses a dependency function, then we can override it easily for testing.
+这样,它的行为几乎就像是一个全局变量。 但是由于它使用了依赖项函数,因此我们可以轻松地进行测试时的覆盖。
-`@lru_cache()` is part of `functools` which is part of Python's standard library, you can read more about it in the Python docs for `@lru_cache()`.
+`@lru_cache()` 是 `functools` 的一部分,它是 Python 标准库的一部分,您可以在Python 文档中了解有关 `@lru_cache()` 的更多信息。
## Recap
-You can use Pydantic Settings to handle the settings or configurations for your application, with all the power of Pydantic models.
+您可以使用 Pydantic 设置处理应用程序的设置或配置,利用 Pydantic 模型的所有功能。
-* By using a dependency you can simplify testing.
-* You can use `.env` files with it.
-* Using `@lru_cache()` lets you avoid reading the dotenv file again and again for each request, while allowing you to override it during testing.
+* 通过使用依赖项,您可以简化测试。
+* 您可以使用 `.env` 文件。
+* 使用 `@lru_cache()` 可以避免为每个请求重复读取 dotenv 文件,同时允许您在测试时进行覆盖。
From bcfcd5aeab13cbad142658a1e4392dc9d5e35239 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:58 +0800
Subject: [PATCH 114/163] New translations websockets.md (Chinese Simplified)
---
docs/zh/docs/advanced/websockets.md | 140 +++++++++++++---------------
1 file changed, 67 insertions(+), 73 deletions(-)
diff --git a/docs/zh/docs/advanced/websockets.md b/docs/zh/docs/advanced/websockets.md
index e1ae3bf84d699..e9665e48659c6 100644
--- a/docs/zh/docs/advanced/websockets.md
+++ b/docs/zh/docs/advanced/websockets.md
@@ -1,107 +1,103 @@
# WebSockets
-You can use WebSockets with **FastAPI**.
+您可以在 **FastAPI** 中使用 [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)。
-## Install `WebSockets`
+## 安装 `WebSockets`
-First you need to install `WebSockets`:
+首先,您需要安装 `WebSockets`:
-You can type messages in the input box, and send them:
+您可以在输入框中输入消息并发送:
-And your **FastAPI** application with WebSockets will respond back:
+您的 **FastAPI** 应用程序将回复:
-You can send (and receive) many messages:
+您可以发送(和接收)多条消息:
-And all of them will use the same WebSocket connection.
+所有这些消息都将使用同一个 WebSocket 连
-## Using `Depends` and others
+## 使用 `Depends` 和其他依赖项
-In WebSocket endpoints you can import from `fastapi` and use:
+在 WebSocket 端点中,您可以从 `fastapi` 导入并使用以下内容:
* `Depends`
* `Security`
@@ -110,7 +106,7 @@ In WebSocket endpoints you can import from `fastapi` and use:
* `Path`
* `Query`
-They work the same way as for other FastAPI endpoints/*path operations*:
+它们的工作方式与其他 FastAPI 端点/ *路径操作* 相同:
=== "Python 3.10+"
@@ -130,60 +126,58 @@ They work the same way as for other FastAPI endpoints/*path operations*:
{!> ../../../docs_src/websockets/tutorial002_an.py!}
```
-=== "Python 3.10+ non-Annotated"
+=== "Python 3.6+ 非带注解版本"
- !!! tip
- Prefer to use the `Annotated` version if possible.
+ !!! !!! tip
+ 如果可能,请尽量使用 `Annotated` 版本。
```Python hl_lines="66-67 79"
{!> ../../../docs_src/websockets/tutorial002_py310.py!}
```
-=== "Python 3.6+ non-Annotated"
+=== "Python 3.10+ 非带注解版本"
- !!! tip
- Prefer to use the `Annotated` version if possible.
+ !!! !!! tip
+ 如果可能,请尽量使用 `Annotated` 版本。
```Python hl_lines="68-69 81"
{!> ../../../docs_src/websockets/tutorial002.py!}
```
-!!! info
- As this is a WebSocket it doesn't really make sense to raise an `HTTPException`, instead we raise a `WebSocketException`.
+!!! !!! info
+ 由于这是一个 WebSocket,抛出 `HTTPException` 并不是很合理,而是抛出 `WebSocketException`。
- You can use a closing code from the valid codes defined in the specification.
+ 您可以使用规范中定义的有效代码。
-### Try the WebSockets with dependencies
+### 尝试带有依赖项的 WebSockets
-If your file is named `main.py`, run your application with:
+如果您的文件名为 `main.py`,请使用以下命令运行应用程序:
-## Handling disconnections and multiple clients
+## 处理断开连接和多个客户端
-When a WebSocket connection is closed, the `await websocket.receive_text()` will raise a `WebSocketDisconnect` exception, which you can then catch and handle like in this example.
+当 WebSocket 连接关闭时,`await websocket.receive_text()` 将引发 `WebSocketDisconnect` 异常,您可以捕获并处理该异常,就像本示例中的示例一样。
=== "Python 3.9+"
@@ -197,28 +191,28 @@ When a WebSocket connection is closed, the `await websocket.receive_text()` will
{!> ../../../docs_src/websockets/tutorial003.py!}
```
-To try it out:
+尝试以下操作:
-* Open the app with several browser tabs.
+* 使用多个浏览器选项卡打开应用程序。
* Write messages from them.
-* Then close one of the tabs.
+* 然后关闭其中一个选项卡。
-That will raise the `WebSocketDisconnect` exception, and all the other clients will receive a message like:
+这将引发 `WebSocketDisconnect` 异常,并且所有其他客户端都会收到类似以下的消息:
```
Client #1596980209979 left the chat
```
-!!! tip
- The app above is a minimal and simple example to demonstrate how to handle and broadcast messages to several WebSocket connections.
+!!! !!! tip
+ 上面的应用程序是一个最小和简单的示例,用于演示如何处理和向多个 WebSocket 连接广播消息。
- But have in mind that, as everything is handled in memory, in a single list, it will only work while the process is running, and will only work with a single process.
+ 但请记住,由于所有内容都在内存中以单个列表的形式处理,因此它只能在进程运行时工作,并且只能使用单个进程。
- If you need something easy to integrate with FastAPI but that is more robust, supported by Redis, PostgreSQL or others, check encode/broadcaster.
+ 如果您需要与 FastAPI 集成更简单但更强大的功能,支持 Redis、PostgreSQL 或其他功能,请查看 [encode/broadcaster](https://github.com/encode/broadcaster)。
-## More info
+## 更多信息
-To learn more about the options, check Starlette's documentation for:
+要了解更多选项,请查看 Starlette 的文档:
-* The `WebSocket` class.
-* Class-based WebSocket handling.
+* WebSocket 类
+* [基于类的 WebSocket 处理](https://www.starlette.io/endpoints/#websocketendpoint)。
From 2ce642ec07c5d6e368f2c7423626464606598f9b Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:40:59 +0800
Subject: [PATCH 115/163] New translations wsgi.md (Chinese Simplified)
---
docs/zh/docs/advanced/wsgi.md | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md
index cfe3c78c11ca4..e39b8eb3d26c9 100644
--- a/docs/zh/docs/advanced/wsgi.md
+++ b/docs/zh/docs/advanced/wsgi.md
@@ -1,34 +1,34 @@
-# Including WSGI - Flask, Django, others
+# 包含 WSGI - Flask,Django,其它
-You can mount WSGI applications as you saw with [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank}.
+您可以挂载多个 WSGI 应用,正如您在 [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank} 中所看到的那样。
-For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc.
+为此, 您可以使用 `WSGIMiddleware` 来包装你的 WSGI 应用,如:Flask,Django,等等。
-## Using `WSGIMiddleware`
+## 使用 `WSGIMiddleware`
-You need to import `WSGIMiddleware`.
+您需要导入 `WSGIMiddleware`。
-Then wrap the WSGI (e.g. Flask) app with the middleware.
+然后使用该中间件包装 WSGI 应用(例如 Flask)。
-And then mount that under a path.
+之后将其挂载到某一个路径下。
```Python hl_lines="2-3 23"
{!../../../docs_src/wsgi/tutorial001.py!}
```
-## Check it
+## 检查
-Now, every request under the path `/v1/` will be handled by the Flask application.
+现在,所有定义在 `/v1/` 路径下的请求将会被 Flask 应用处理。
-And the rest will be handled by **FastAPI**.
+其余的请求则会被 **FastAPI** 处理。
-If you run it with Uvicorn and go to http://localhost:8000/v1/ you will see the response from Flask:
+如果您使用 Uvicorn 运行应用实例并且访问 http://localhost:8000/v1/,您将会看到由 Flask 返回的响应:
```txt
Hello, World from Flask!
```
-And if you go to http://localhost:8000/v2 you will see the response from FastAPI:
+并且如果您访问 http://localhost:8000/v2,您将会看到由 FastAPI 返回的响应:
```JSON
{
From 1e20d99e0eb9ec1a976af7a55b37d1062d08f9e5 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:41:01 +0800
Subject: [PATCH 116/163] New translations benchmarks.md (Chinese Simplified)
---
docs/zh/docs/benchmarks.md | 42 +++++++++++++++++++-------------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/docs/zh/docs/benchmarks.md b/docs/zh/docs/benchmarks.md
index e05fec8406621..44ff3a3870998 100644
--- a/docs/zh/docs/benchmarks.md
+++ b/docs/zh/docs/benchmarks.md
@@ -1,34 +1,34 @@
# Benchmarks
-Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
+第三方机构 TechEmpower 的基准测试表明在 Uvicorn 下运行的 **FastAPI** 应用程序是 可用的最快的 Python 框架之一,仅次于 Starlette 和 Uvicorn 本身 (由 FastAPI 内部使用)。 (*)
-But when checking benchmarks and comparisons you should have the following in mind.
+但是在查看基准得分和对比时,请注意以下几点。
-## Benchmarks and speed
+## 基准测试和速度
-When you check the benchmarks, it is common to see several tools of different types compared as equivalent.
+当你查看基准测试时,几个不同类型的工具被等效地做比较是很常见的情况。
-Specifically, to see Uvicorn, Starlette and FastAPI compared together (among many other tools).
+具体来说,是将 Uvicorn,Starlette 和 FastAPI 一起比较(在许多其它工具中)。
-The simpler the problem solved by the tool, the better performance it will get. And most of the benchmarks don't test the additional features provided by the tool.
+该工具解决的问题最简单,它将获得更好的性能。 而且大多数基准测试并未测试该工具提供的其他功能。
-The hierarchy is like:
+层次结构如下:
-* **Uvicorn**: an ASGI server
- * **Starlette**: (uses Uvicorn) a web microframework
- * **FastAPI**: (uses Starlette) an API microframework with several additional features for building APIs, with data validation, etc.
+* **Uvicorn**:ASGI服务器
+ * **Starlette**:(使用 Uvicorn)网络微框架
+ * **FastAPI**:(使用 Starlette) 具有多个附加功能的API微框架,用于构建API,进行数据验证等。
* **Uvicorn**:
- * Will have the best performance, as it doesn't have much extra code apart from the server itself.
- * You wouldn't write an application in Uvicorn directly. That would mean that your code would have to include more or less, at least, all the code provided by Starlette (or **FastAPI**). And if you did that, your final application would have the same overhead as having used a framework and minimizing your app code and bugs.
- * If you are comparing Uvicorn, compare it against Daphne, Hypercorn, uWSGI, etc. Application servers.
+ * 具有最佳性能,因为除了服务器本身外,它没有太多额外的代码。
+ * 您不会直接在 Uvicorn 中编写应用程序。 这意味着您的代码至少必须包含 Starlette(或 **FastAPI**)提供的代码。 如果您这样做了(即直接在 Uvicorn 中编写应用程序),最终的应用程序会和使用了框架并且最小化了应用代码和 bug 的情况具有相同的性能损耗。
+ * 如果要对比与 Uvicorn 对标的服务器,请将其与 Daphne,Hypercorn,uWSGI等应用服务器进行比较。 Application servers.
* **Starlette**:
- * Will have the next best performance, after Uvicorn. In fact, Starlette uses Uvicorn to run. So, it probably can only get "slower" than Uvicorn by having to execute more code.
- * But it provides you the tools to build simple web applications, with routing based on paths, etc.
- * If you are comparing Starlette, compare it against Sanic, Flask, Django, etc. Web frameworks (or microframeworks).
+ * 在 Uvicorn 后使用 Starlette,性能会略有下降。 实际上,Starlette 使用 Uvicorn运行。 因此,由于必须执行更多的代码,它只会比 Uvicorn 更慢。
+ * 但它为您提供了构建简单的网络程序的工具,并具有基于路径的路由等功能。
+ * 如果想对比与 Starlette 对标的开发框架,请将其与 Sanic,Flask,Django 等网络框架(或微框架)进行比较。 Web frameworks (or microframeworks).
* **FastAPI**:
- * The same way that Starlette uses Uvicorn and cannot be faster than it, **FastAPI** uses Starlette, so it cannot be faster than it.
- * FastAPI provides more features on top of Starlette. Features that you almost always need when building APIs, like data validation and serialization. And by using it, you get automatic documentation for free (the automatic documentation doesn't even add overhead to running applications, it is generated on startup).
- * If you didn't use FastAPI and used Starlette directly (or another tool, like Sanic, Flask, Responder, etc) you would have to implement all the data validation and serialization yourself. So, your final application would still have the same overhead as if it was built using FastAPI. And in many cases, this data validation and serialization is the biggest amount of code written in applications.
- * So, by using FastAPI you are saving development time, bugs, lines of code, and you would probably get the same performance (or better) you would if you didn't use it (as you would have to implement it all in your code).
- * If you are comparing FastAPI, compare it against a web application framework (or set of tools) that provides data validation, serialization and documentation, like Flask-apispec, NestJS, Molten, etc. Frameworks with integrated automatic data validation, serialization and documentation.
+ * 与 Starlette 使用 Uvicorn 一样,由于 **FastAPI** 使用 Starlette,因此 FastAPI 不能比 Starlette 更快。
+ * FastAPI 在 Starlette 基础上提供了更多功能。 例如在开发 API 时,所需的数据验证和序列化功能。 FastAPI 可以帮助您自动生成 API文档,(文档在应用程序启动时自动生成,所以不会增加应用程序运行时的开销)。
+ * 如果您不使用 FastAPI 而直接使用 Starlette(或诸如 Sanic,Flask,Responder 等其它工具),您则要自己实现所有的数据验证和序列化。 那么最终您的应用程序会和使用 FastAPI 构建的程序有相同的开销。 一般这种数据验证和序列化的操作在您应用程序的代码中会占很大比重。
+ * 因此,通过使用 FastAPI 意味着您可以节省开发时间,减少编码错误,用更少的编码实现其功能,并且相比不使用 FastAPI 您很大可能会获得相同或更好的性能(因为那样您必须在代码中实现所有相同的功能)。
+ * 如果您想对比与 FastAPI 对标的开发框架,请与能够提供数据验证,序列化和带有自动文档生成的网络应用程序框架(或工具集)进行对比,例如具有集成自动数据验证,序列化和自动化文档的 Flask-apispec,NestJS,Molten 等。 Frameworks with integrated automatic data validation, serialization and documentation.
From 15cd6db371666de6b33ec19d3dc8327f5f2eacb0 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:41:03 +0800
Subject: [PATCH 117/163] New translations contributing.md (Chinese Simplified)
---
docs/zh/docs/contributing.md | 215 +++++++++++++++++++----------------
1 file changed, 114 insertions(+), 101 deletions(-)
diff --git a/docs/zh/docs/contributing.md b/docs/zh/docs/contributing.md
index f9276b28e9e49..46f349f032fab 100644
--- a/docs/zh/docs/contributing.md
+++ b/docs/zh/docs/contributing.md
@@ -1,14 +1,14 @@
-# Development - Contributing
+# 开发 - 贡献
-First, you might want to see the basic ways to [help FastAPI and get help](help-fastapi.md){.internal-link target=_blank}.
+首先,你最好先了解 [帮助 FastAPI 及获取帮助](help-fastapi.md){.internal-link target=_blank}的基本方式。
-## Developing
+## 开发
-If you already cloned the repository and you know that you need to deep dive in the code, here are some guidelines to set up your environment.
+如果你已经克隆了源码仓库,并且需要深入研究代码,下面是设置开发环境的指南。
-### Virtual environment with `venv`
+### 通过 `venv` 管理虚拟环境
-You can create a virtual environment in a directory using Python's `venv` module:
+你可以使用 Python 的 `venv` 模块在一个目录中创建虚拟环境:
-## Include the same router multiple times with different `prefix`
+## 多次使用不同的 `prefix` 包含同一个路由器
-You can also use `.include_router()` multiple times with the *same* router using different prefixes.
+你也可以在*同一*路由器上使用不同的前缀来多次使用 `.include_router()`。
-This could be useful, for example, to expose the same API under different prefixes, e.g. `/api/v1` and `/api/latest`.
+在有些场景这可能有用,例如以不同的前缀公开同一个的 API,比方说 `/api/v1` 和 `/api/latest`。
-This is an advanced usage that you might not really need, but it's there in case you do.
+这是一个你可能并不真正需要的高级用法,但万一你有需要了就能够用上。
-## Include an `APIRouter` in another
+## 在另一个 `APIRouter` 中包含一个 `APIRouter`
-The same way you can include an `APIRouter` in a `FastAPI` application, you can include an `APIRouter` in another `APIRouter` using:
+与在 `FastAPI` 应用程序中包含 `APIRouter` 的方式相同,你也可以在另一个 `APIRouter` 中包含 `APIRouter`,通过:
```Python
router.include_router(other_router)
```
-Make sure you do it before including `router` in the `FastAPI` app, so that the *path operations* from `other_router` are also included.
+请确保在你将 `router` 包含到 `FastAPI` 应用程序之前进行此操作,以便 `other_router` 中的`路径操作`也能被包含进来。
From e796961df1bc14695efb5974ac0154808ad365a0 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:26 +0800
Subject: [PATCH 122/163] New translations body-fields.md (Chinese Simplified)
---
docs/zh/docs/tutorial/body-fields.md | 51 ++++++++++++++++------------
1 file changed, 30 insertions(+), 21 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-fields.md b/docs/zh/docs/tutorial/body-fields.md
index 36039020923ba..da96baaecfbc0 100644
--- a/docs/zh/docs/tutorial/body-fields.md
+++ b/docs/zh/docs/tutorial/body-fields.md
@@ -1,10 +1,10 @@
# Body - Fields
-The same way you can declare additional validation and metadata in *path operation function* parameters with `Query`, `Path` and `Body`, you can declare validation and metadata inside of Pydantic models using Pydantic's `Field`.
+与使用 `Query`、`Path` 和 `Body` 在*路径操作函数*中声明额外的校验和元数据的方式相同,你可以使用 Pydantic 的 `Field` 在 Pydantic 模型内部声明校验和元数据。
-## Import `Field`
+## 导入 `Field`
-First, you have to import it:
+首先,你必须导入它:
=== "Python 3.10+"
@@ -21,8 +21,11 @@ First, you have to import it:
=== "Python 3.6+"
```Python hl_lines="4"
- {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ !!! note "技术细节"
+ 实际上,Query、Path 和其他你将在之后看到的类,创建的是由一个共同的 Params 类派生的子类的对象,该共同类本身又是 Pydantic 的 FieldInfo 类的子类。
```
+、Path 和其他你将在之后看到的类,创建的是由一个共同的 Params 类派生的子类的对象,该共同类本身又是 Pydantic 的 FieldInfo 类的子类。
+
=== "Python 3.10+ non-Annotated"
@@ -30,7 +33,7 @@ First, you have to import it:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2"
- {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ {!../../../docs_src/body_fields/tutorial001.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -39,20 +42,23 @@ First, you have to import it:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4"
- {!> ../../../docs_src/body_fields/tutorial001.py!}
+ !!! tip
+ 注意每个模型属性如何使用类型、默认值和 Field 在代码结构上和路径操作函数的参数是相同的,区别是用 Field 替换Path、Query 和 Body。
```
+ 在代码结构上和*路径操作函数*的参数是相同的,区别是用 Field 替换Path、Query 和 Body。
+
!!! warning
Notice that `Field` is imported directly from `pydantic`, not from `fastapi` as are all the rest (`Query`, `Path`, `Body`, etc).
-## Declare model attributes
+## 声明模型属性
-You can then use `Field` with model attributes:
+然后,你可以对模型属性使用 `Field`:
=== "Python 3.10+"
```Python hl_lines="11-14"
- {!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
+ 总结
```
=== "Python 3.9+"
@@ -64,7 +70,7 @@ You can then use `Field` with model attributes:
=== "Python 3.6+"
```Python hl_lines="12-15"
- {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ 请求体 - 字段
```
=== "Python 3.10+ non-Annotated"
@@ -73,7 +79,7 @@ You can then use `Field` with model attributes:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9-12"
- {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ {!../../../docs_src/body_fields/tutorial001.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -82,34 +88,37 @@ You can then use `Field` with model attributes:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11-14"
- {!> ../../../docs_src/body_fields/tutorial001.py!}
+ !!! warning
+ 注意,Field 是直接从 pydantic 导入的,而不是像其他的(Query,Path,Body 等)都从 fastapi 导入。
```
+ 是直接从 pydantic 导入的,而不是像其他的(Query,Path,Body 等)都从 fastapi 导入。
+
-`Field` works the same way as `Query`, `Path` and `Body`, it has all the same parameters, etc.
+`Field` 的工作方式和 `Query`、`Path` 和 `Body` 相同,包括它们的参数等等也完全相同。
!!! note "Technical Details"
Actually, `Query`, `Path` and others you'll see next create objects of subclasses of a common `Param` class, which is itself a subclass of Pydantic's `FieldInfo` class.
- And Pydantic's `Field` returns an instance of `FieldInfo` as well.
+ Pydantic 的 `Field` 也会返回一个 `FieldInfo` 的实例。
- `Body` also returns objects of a subclass of `FieldInfo` directly. And there are others you will see later that are subclasses of the `Body` class.
+ `Body` 也直接返回 `FieldInfo` 的一个子类的对象。 还有其他一些你之后会看到的类是 `Body` 类的子类。
- Remember that when you import `Query`, `Path`, and others from `fastapi`, those are actually functions that return special classes.
+ 请记住当你从 `fastapi` 导入 `Query`、`Path` 等对象时,他们实际上是返回特殊类的函数。
!!! tip
Notice how each model's attribute with a type, default value and `Field` has the same structure as a *path operation function's* parameter, with `Field` instead of `Path`, `Query` and `Body`.
-## Add extra information
+## 添加额外信息
-You can declare extra information in `Field`, `Query`, `Body`, etc. And it will be included in the generated JSON Schema.
+你可以在 `Field`、`Query`、`Body` 中声明额外的信息。 这些信息将包含在生成的 JSON Schema 中。
-You will learn more about adding extra information later in the docs, when learning to declare examples.
+你将在文档的后面部分学习声明示例时,了解到更多有关添加额外信息的知识。
!!! warning
Extra keys passed to `Field` will also be present in the resulting OpenAPI schema for your application. As these keys may not necessarily be part of the OpenAPI specification, some OpenAPI tools, for example [the OpenAPI validator](https://validator.swagger.io/), may not work with your generated schema.
## Recap
-You can use Pydantic's `Field` to declare extra validations and metadata for model attributes.
+你可以使用 Pydantic 的 `Field` 为模型属性声明额外的校验和元数据。
-You can also use the extra keyword arguments to pass additional JSON Schema metadata.
+你还可以使用额外的关键字参数来传递额外的 JSON Schema 元数据。
From d33e24d93298b45f5c656644f69afb0576ff6b2c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:27 +0800
Subject: [PATCH 123/163] New translations body-multiple-params.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/body-multiple-params.md | 96 ++++++++++---------
1 file changed, 51 insertions(+), 45 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-multiple-params.md b/docs/zh/docs/tutorial/body-multiple-params.md
index b214092c9b175..6219c9aca93f2 100644
--- a/docs/zh/docs/tutorial/body-multiple-params.md
+++ b/docs/zh/docs/tutorial/body-multiple-params.md
@@ -1,12 +1,12 @@
-# Body - Multiple Parameters
+# 请求体 - 多个参数
-Now that we have seen how to use `Path` and `Query`, let's see more advanced uses of request body declarations.
+既然我们已经知道了如何使用 `Path` 和 `Query`,下面让我们来了解一下请求体声明的更高级用法。
-## Mix `Path`, `Query` and body parameters
+## 混合使用 `Path`、`Query` 和请求体参数
-First, of course, you can mix `Path`, `Query` and request body parameter declarations freely and **FastAPI** will know what to do.
+首先,毫无疑问地,你可以随意地混合使用 `Path`、`Query` 和请求体参数声明,**FastAPI** 会知道该如何处理。
-And you can also declare body parameters as optional, by setting the default to `None`:
+你还可以通过将默认值设置为 `None` 来将请求体参数声明为可选参数:
=== "Python 3.10+"
@@ -44,12 +44,12 @@ And you can also declare body parameters as optional, by setting the default to
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
```
-!!! note
- Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value.
+!!! !!! note
+ 请注意,在这种情况下,将从请求体获取的 `item` 是可选的。 因为它的默认值为 `None`。
-## Multiple body parameters
+## 多个请求体参数
-In the previous example, the *path operations* would expect a JSON body with the attributes of an `Item`, like:
+在上面的示例中,*路径操作*将期望一个具有 `Item` 的属性的 JSON 请求体,就像:
```JSON
{
@@ -60,7 +60,7 @@ In the previous example, the *path operations* would expect a JSON body with the
}
```
-But you can also declare multiple body parameters, e.g. `item` and `user`:
+但是你也可以声明多个请求体参数,例如 `item` 和 `user`:
=== "Python 3.10+"
@@ -71,12 +71,12 @@ But you can also declare multiple body parameters, e.g. `item` and `user`:
=== "Python 3.6+"
```Python hl_lines="22"
- {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
+ {!../../../docs_src/body_multiple_params/tutorial002.py!}
```
-In this case, **FastAPI** will notice that there are more than one body parameters in the function (two parameters that are Pydantic models).
+如果你就按原样声明它,因为它是一个单一值,**FastAPI** 将假定它是一个查询参数。
-So, it will then use the parameter names as keys (field names) in the body, and expect a body like:
+因此,它将使用参数名称作为请求体中的键(字段名称),并期望一个类似于以下内容的请求体:
```JSON
{
@@ -97,19 +97,19 @@ So, it will then use the parameter names as keys (field names) in the body, and
Notice that even though the `item` was declared the same way as before, it is now expected to be inside of the body with a key `item`.
-**FastAPI** will do the automatic conversion from the request, so that the parameter `item` receives it's specific content and the same for `user`.
+**FastAPI** 将自动对请求中的数据进行转换,因此 `item` 参数将接收指定的内容,`user` 参数也是如此。
-It will perform the validation of the compound data, and will document it like that for the OpenAPI schema and automatic docs.
+它将执行对复合数据的校验,并且像现在这样为 OpenAPI 模式和自动化文档对其进行记录。
-## Singular values in body
+## 请求体中的单一值
-The same way there is a `Query` and `Path` to define extra data for query and path parameters, **FastAPI** provides an equivalent `Body`.
+与使用 `Query` 和 `Path` 为查询参数和路径参数定义额外数据的方式相同,**FastAPI** 提供了一个同等的 `Body`。
-For example, extending the previous model, you could decide that you want to have another key `importance` in the same body, besides the `item` and `user`.
+例如,为了扩展先前的模型,你可能决定除了 `item` 和 `user` 之外,还想在同一请求体中具有另一个键 `importance`。
-If you declare it as is, because it is a singular value, **FastAPI** will assume that it is a query parameter.
+在这种情况下,**FastAPI** 将注意到该函数中有多个请求体参数(两个 Pydantic 模型参数)。
-But you can instruct **FastAPI** to treat it as another body key using `Body`:
+但是你可以使用 `Body` 指示 **FastAPI** 将其作为请求体的另一个键进行处理。
=== "Python 3.10+"
@@ -120,13 +120,16 @@ But you can instruct **FastAPI** to treat it as another body key using `Body`:
=== "Python 3.9+"
```Python hl_lines="23"
- {!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
+ !!! info
+ Body 同样具有与 Query、Path 以及其他后面将看到的类完全相同的额外校验和元数据参数。
```
+ 同样具有与 Query、Path 以及其他后面将看到的类完全相同的额外校验和元数据参数。
+
=== "Python 3.6+"
```Python hl_lines="24"
- {!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
+ {!../../../docs_src/body_multiple_params/tutorial003.py!}
```
=== "Python 3.10+ non-Annotated"
@@ -135,7 +138,7 @@ But you can instruct **FastAPI** to treat it as another body key using `Body`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="20"
- {!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
+ {!../../../docs_src/body_multiple_params/tutorial004.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -144,10 +147,10 @@ But you can instruct **FastAPI** to treat it as another body key using `Body`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="22"
- {!> ../../../docs_src/body_multiple_params/tutorial003.py!}
+ {!../../../docs_src/body_multiple_params/tutorial005.py!}
```
-In this case, **FastAPI** will expect a body like:
+在这种情况下,**FastAPI** 将期望像这样的请求体:
```JSON
{
@@ -165,25 +168,28 @@ In this case, **FastAPI** will expect a body like:
}
```
-Again, it will convert the data types, validate, document, etc.
+同样的,它将转换数据类型,校验,生成文档等。
-## Multiple body params and query
+## 多个请求体参数和查询参数
-Of course, you can also declare additional query parameters whenever you need, additional to any body parameters.
+当然,除了请求体参数外,你还可以在任何需要的时候声明额外的查询参数。
-As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
+由于默认情况下单一值被解释为查询参数,因此你不必显式地添加 `Query`,你可以仅执行以下操作:
```Python
-q: Union[str, None] = None
+!!! note
+ 请注意,即使 item 的声明方式与之前相同,但现在它被期望通过 item 键内嵌在请求体中。
```
+ 的声明方式与之前相同,但现在它被期望通过 item 键内嵌在请求体中。
+
Or in Python 3.10 and above:
```Python
-q: str | None = None
+q: str = None
```
-For example:
+比如:
=== "Python 3.10+"
@@ -200,7 +206,7 @@ For example:
=== "Python 3.6+"
```Python hl_lines="28"
- {!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
+ {!../../../docs_src/body_multiple_params/tutorial001.py!}
```
=== "Python 3.10+ non-Annotated"
@@ -224,24 +230,24 @@ For example:
!!! info
`Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later.
-## Embed a single body parameter
+## 嵌入单个请求体参数
-Let's say you only have a single `item` body parameter from a Pydantic model `Item`.
+假设你只有一个来自 Pydantic 模型 `Item` 的请求体参数 `item`。
-By default, **FastAPI** will then expect its body directly.
+默认情况下,**FastAPI** 将直接期望这样的请求体。
-But if you want it to expect a JSON with a key `item` and inside of it the model contents, as it does when you declare extra body parameters, you can use the special `Body` parameter `embed`:
+但是,如果你希望它期望一个拥有 `item` 键并在值中包含模型内容的 JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的 `Body` 参数 `embed`:
```Python
item: Item = Body(embed=True)
```
-as in:
+比如:
=== "Python 3.10+"
```Python hl_lines="17"
- {!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
+ 总结
```
=== "Python 3.9+"
@@ -274,7 +280,7 @@ as in:
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
```
-In this case **FastAPI** will expect a body like:
+在这种情况下,**FastAPI** 将期望像这样的请求体:
```JSON hl_lines="2"
{
@@ -287,7 +293,7 @@ In this case **FastAPI** will expect a body like:
}
```
-instead of:
+而不是:
```JSON
{
@@ -300,10 +306,10 @@ instead of:
## Recap
-You can add multiple body parameters to your *path operation function*, even though a request can only have a single body.
+你可以添加多个请求体参数到*路径操作函数*中,即使一个请求只能有一个请求体。
-But **FastAPI** will handle it, give you the correct data in your function, and validate and document the correct schema in the *path operation*.
+但是 **FastAPI** 会处理它,在函数中为你提供正确的数据,并在*路径操作*中校验并记录正确的模式。
-You can also declare singular values to be received as part of the body.
+你还可以声明将作为请求体的一部分所接收的单一值。
-And you can instruct **FastAPI** to embed the body in a key even when there is only a single parameter declared.
+你还可以指示 **FastAPI** 在仅声明了一个请求体参数的情况下,将原本的请求体嵌入到一个键中。
From 0c1f9711926601d7fb81fbd3886a18e7035adf13 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:28 +0800
Subject: [PATCH 124/163] New translations body-nested-models.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/body-nested-models.md | 189 +++++++++++---------
1 file changed, 101 insertions(+), 88 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md
index 7adfd8c03d396..7d4819642168f 100644
--- a/docs/zh/docs/tutorial/body-nested-models.md
+++ b/docs/zh/docs/tutorial/body-nested-models.md
@@ -1,10 +1,10 @@
-# Body - Nested Models
+# 请求体 - 嵌套模型
-With **FastAPI**, you can define, validate, document, and use arbitrarily deeply nested models (thanks to Pydantic).
+使用 **FastAPI**,你可以定义、校验、记录文档并使用任意深度嵌套的模型(归功于Pydantic)。
-## List fields
+## List 字段
-You can define an attribute to be a subtype. For example, a Python `list`:
+你可以将一个属性定义为拥有子元素的类型。 例如 Python `list`:
=== "Python 3.10+"
@@ -15,31 +15,33 @@ You can define an attribute to be a subtype. For example, a Python `list`:
=== "Python 3.6+"
```Python hl_lines="14"
- {!> ../../../docs_src/body_nested_models/tutorial001.py!}
+ 除了普通的单一值类型(如 str、int、float 等)外,你还可以使用从 str 继承的更复杂的单一值类型。
```
+、int、float 等)外,你还可以使用从 str 继承的更复杂的单一值类型。
+
-This will make `tags` be a list, although it doesn't declare the type of the elements of the list.
+这将使 `tags` 成为一个由元素组成的列表。 不过它没有声明每个元素的类型。
-## List fields with type parameter
+## 具有子类型的 List 字段
-But Python has a specific way to declare lists with internal types, or "type parameters":
+但是 Python 有一种特定的方法来声明具有子类型的列表:
-### Import typing's `List`
+### 从 typing 导入 `List`
In Python 3.9 and above you can use the standard `list` to declare these type annotations as we'll see below. 💡
-But in Python versions before 3.9 (3.6 and above), you first need to import `List` from standard Python's `typing` module:
+首先,从 Python 的标准库 `typing` 模块中导入 `List`:
```Python hl_lines="1"
-{!> ../../../docs_src/body_nested_models/tutorial002.py!}
+{!../../../docs_src/body_nested_models/tutorial001.py!}
```
-### Declare a `list` with a type parameter
+### 声明具有子类型的 List
-To declare types that have type parameters (internal types), like `list`, `dict`, `tuple`:
+要声明具有子类型的类型,例如 `list`、`dict`、`tuple`:
* If you are in a Python version lower than 3.9, import their equivalent version from the `typing` module
-* Pass the internal type(s) as "type parameters" using square brackets: `[` and `]`
+* 使用方括号 `[` 和 `]` 将子类型作为「类型参数」传入
In Python 3.9 it would be:
@@ -55,16 +57,16 @@ from typing import List
my_list: List[str]
```
-That's all standard Python syntax for type declarations.
+这完全是用于类型声明的标准 Python 语法。
-Use that same standard syntax for model attributes with internal types.
+对具有子类型的模型属性也使用相同的标准语法。
-So, in our example, we can make `tags` be specifically a "list of strings":
+因此,在我们的示例中,我们可以将 `tags` 明确地指定为一个「字符串列表」:
=== "Python 3.10+"
```Python hl_lines="12"
- {!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
+ {!../../../docs_src/body_nested_models/tutorial002.py!}
```
=== "Python 3.9+"
@@ -76,21 +78,21 @@ So, in our example, we can make `tags` be specifically a "list of strings":
=== "Python 3.6+"
```Python hl_lines="14"
- {!> ../../../docs_src/body_nested_models/tutorial002.py!}
+ {!../../../docs_src/body_nested_models/tutorial002.py!}
```
-## Set types
+## Set 类型
-But then we think about it, and realize that tags shouldn't repeat, they would probably be unique strings.
+但是随后我们考虑了一下,意识到标签不应该重复,它们很大可能会是唯一的字符串。
-And Python has a special data type for sets of unique items, the `set`.
+Python 具有一种特殊的数据类型来保存一组唯一的元素,即 `set`。
-Then we can declare `tags` as a set of strings:
+然后我们可以导入 `Set` 并将 `tag` 声明为一个由 `str` 组成的 `set`:
=== "Python 3.10+"
```Python hl_lines="12"
- {!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
+ {!../../../docs_src/body_nested_models/tutorial009.py!}
```
=== "Python 3.9+"
@@ -102,33 +104,33 @@ Then we can declare `tags` as a set of strings:
=== "Python 3.6+"
```Python hl_lines="1 14"
- {!> ../../../docs_src/body_nested_models/tutorial003.py!}
+ {!../../../docs_src/body_nested_models/tutorial003.py!}
```
-With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
+这样,即使你收到带有重复数据的请求,这些数据也会被转换为一组唯一项。
-And whenever you output that data, even if the source had duplicates, it will be output as a set of unique items.
+而且,每当你输出该数据时,即使源数据有重复,它们也将作为一组唯一项输出。
-And it will be annotated / documented accordingly too.
+并且还会被相应地标注 / 记录文档。
-## Nested Models
+## 嵌套模型
-Each attribute of a Pydantic model has a type.
+Pydantic 模型的每个属性都具有类型。
-But that type can itself be another Pydantic model.
+但是这个类型本身可以是另一个 Pydantic 模型。
-So, you can declare deeply nested JSON "objects" with specific attribute names, types and validations.
+因此,你可以声明拥有特定属性名称、类型和校验的深度嵌套的 JSON 对象。
All that, arbitrarily nested.
-### Define a submodel
+### 定义子模型
-For example, we can define an `Image` model:
+例如,我们可以定义一个 `Image` 模型:
=== "Python 3.10+"
```Python hl_lines="7-9"
- {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ {!../../../docs_src/body_nested_models/tutorial004.py!}
```
=== "Python 3.9+"
@@ -140,17 +142,17 @@ For example, we can define an `Image` model:
=== "Python 3.6+"
```Python hl_lines="9-11"
- {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ {!../../../docs_src/body_nested_models/tutorial004.py!}
```
-### Use the submodel as a type
+### 将子模型用作类型
-And then we can use it as the type of an attribute:
+然后我们可以将其用作一个属性的类型:
=== "Python 3.10+"
```Python hl_lines="18"
- {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ 例如:
```
=== "Python 3.9+"
@@ -162,10 +164,12 @@ And then we can use it as the type of an attribute:
=== "Python 3.6+"
```Python hl_lines="20"
- {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ 从 typing 模块导入它们
```
+ 模块导入它们
+
-This would mean that **FastAPI** would expect a body similar to:
+这意味着 **FastAPI** 将期望类似于以下内容的请求体:
```JSON
{
@@ -181,25 +185,25 @@ This would mean that **FastAPI** would expect a body similar to:
}
```
-Again, doing just that declaration, with **FastAPI** you get:
+再一次,仅仅进行这样的声明,你将通过 **FastAPI** 获得:
-* Editor support (completion, etc), even for nested models
-* Data conversion
-* Data validation
-* Automatic documentation
+* 对被嵌入的模型也适用的编辑器支持(自动补全等)
+* 数据转换
+* 数据校验
+* 自动生成文档
-## Special types and validation
+## 特殊的类型和校验
Apart from normal singular types like `str`, `int`, `float`, etc. You can use more complex singular types that inherit from `str`.
-To see all the options you have, checkout the docs for Pydantic's exotic types. You will see some examples in the next chapter.
+要了解所有的可用选项,请查看关于 来自 Pydantic 的外部类型 的文档。 你将在下一章节中看到一些示例。
-For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `HttpUrl`:
+例如,在 `Image` 模型中我们有一个 `url` 字段,我们可以把它声明为 Pydantic 的 `HttpUrl`,而不是 `str`:
=== "Python 3.10+"
```Python hl_lines="2 8"
- {!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
+ {!../../../docs_src/body_nested_models/tutorial005.py!}
```
=== "Python 3.9+"
@@ -211,19 +215,22 @@ For example, as in the `Image` model we have a `url` field, we can declare it to
=== "Python 3.6+"
```Python hl_lines="4 10"
- {!> ../../../docs_src/body_nested_models/tutorial005.py!}
+ !!! info
+ 请注意 images 键现在具有一组 image 对象是如何发生的。
```
+ 键现在具有一组 image 对象是如何发生的。
+
-The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
+该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。
-## Attributes with lists of submodels
+## 带有一组子模型的属性
-You can also use Pydantic models as subtypes of `list`, `set`, etc:
+你还可以将 Pydantic 模型用作 `list`、`set` 等的子类型:
=== "Python 3.10+"
```Python hl_lines="18"
- {!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
+ {!../../../docs_src/body_nested_models/tutorial006.py!}
```
=== "Python 3.9+"
@@ -235,10 +242,13 @@ You can also use Pydantic models as subtypes of `list`, `set`, etc:
=== "Python 3.6+"
```Python hl_lines="20"
- {!> ../../../docs_src/body_nested_models/tutorial006.py!}
+ !!! tip
+ 请记住 JSON 仅支持将 str 作为键。
```
+ 作为键。
+
-This will expect (convert, validate, document, etc) a JSON body like:
+这将期望(转换,校验,记录文档等)下面这样的 JSON 请求体:
```JSON hl_lines="11"
{
@@ -267,34 +277,34 @@ This will expect (convert, validate, document, etc) a JSON body like:
!!! info
Notice how the `images` key now has a list of image objects.
-## Deeply nested models
+## 深度嵌套模型
-You can define arbitrarily deeply nested models:
+你可以定义任意深度的嵌套模型:
=== "Python 3.10+"
```Python hl_lines="7 12 18 21 25"
- {!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
+ 上述这些都可以任意的嵌套。
```
=== "Python 3.9+"
```Python hl_lines="9 14 20 23 27"
- {!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
+ 总结
```
=== "Python 3.6+"
```Python hl_lines="9 14 20 23 27"
- {!> ../../../docs_src/body_nested_models/tutorial007.py!}
+ {!../../../docs_src/body_nested_models/tutorial007.py!}
```
!!! info
Notice how `Offer` has a list of `Item`s, which in turn have an optional list of `Image`s
-## Bodies of pure lists
+## 纯列表请求体
-If the top level value of the JSON body you expect is a JSON `array` (a Python `list`), you can declare the type in the parameter of the function, the same as in Pydantic models:
+如果你期望的 JSON 请求体的最外层是一个 JSON `array`(即 Python `list`),则可以在路径操作函数的参数中声明此类型,就像声明 Pydantic 模型一样:
```Python
images: List[Image]
@@ -317,66 +327,69 @@ as in:
=== "Python 3.6+"
```Python hl_lines="15"
- {!> ../../../docs_src/body_nested_models/tutorial008.py!}
+ {!../../../docs_src/body_nested_models/tutorial008.py!}
```
-## Editor support everywhere
+## 无处不在的编辑器支持
-And you get editor support everywhere.
+你可以随处获得编辑器支持。
-Even for items inside of lists:
+即使是列表中的元素:
-You couldn't get this kind of editor support if you were working directly with `dict` instead of Pydantic models.
+如果你直接使用 `dict` 而不是 Pydantic 模型,那你将无法获得这种编辑器支持。
-But you don't have to worry about them either, incoming dicts are converted automatically and your output is converted automatically to JSON too.
+但是你根本不必担心这两者,传入的字典会自动被转换,你的输出也会自动被转换为 JSON。
-## Bodies of arbitrary `dict`s
+## 任意 `dict` 构成的请求体
-You can also declare a body as a `dict` with keys of some type and values of other type.
+你也可以将请求体声明为使用某类型的键和其他类型值的 `dict`。
-Without having to know beforehand what are the valid field/attribute names (as would be the case with Pydantic models).
+无需事先知道有效的字段/属性(在使用 Pydantic 模型的场景)名称是什么。
-This would be useful if you want to receive keys that you don't already know.
+如果你想接收一些尚且未知的键,这将很有用。
---
-Other useful case is when you want to have keys of other type, e.g. `int`.
+其他有用的场景是当你想要接收其他类型的键时,例如 `int`。
-That's what we are going to see here.
+这也是我们在接下来将看到的。
-In this case, you would accept any `dict` as long as it has `int` keys with `float` values:
+在下面的例子中,你将接受任意键为 `int` 类型并且值为 `float` 类型的 `dict`:
=== "Python 3.9+"
```Python hl_lines="7"
- {!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
+ https://fastapi.tiangolo.com/img/tutorial/body-nested-models/image01.png
```
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/body_nested_models/tutorial009.py!}
+ !!! info
+ 请注意 Offer 拥有一组 Item 而反过来 Item 又是一个可选的 Image 列表是如何发生的。
```
+ 拥有一组 Item 而反过来 Item 又是一个可选的 Image 列表是如何发生的。
+
!!! tip
Have in mind that JSON only supports `str` as keys.
- But Pydantic has automatic data conversion.
+ 但是 Pydantic 具有自动转换数据的功能。
- This means that, even though your API clients can only send strings as keys, as long as those strings contain pure integers, Pydantic will convert them and validate them.
+ 这意味着,即使你的 API 客户端只能将字符串作为键发送,只要这些字符串内容仅包含整数,Pydantic 就会对其进行转换并校验。
- And the `dict` you receive as `weights` will actually have `int` keys and `float` values.
+ 然后你接收的名为 `weights` 的 `dict` 实际上将具有 `int` 类型的键和 `float` 类型的值。
## Recap
-With **FastAPI** you have the maximum flexibility provided by Pydantic models, while keeping your code simple, short and elegant.
+使用 **FastAPI** 你可以拥有 Pydantic 模型提供的极高灵活性,同时保持代码的简单、简短和优雅。
-But with all the benefits:
+而且还具有下列好处:
-* Editor support (completion everywhere!)
+* 编辑器支持(处处皆可自动补全!)
* Data conversion (a.k.a. parsing / serialization)
-* Data validation
-* Schema documentation
-* Automatic docs
+* 数据校验
+* 模式文档
+* 自动生成的文档
From ed63cd779b8180d0c4d9643ebb6c12deec206461 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:29 +0800
Subject: [PATCH 125/163] New translations body-updates.md (Chinese Simplified)
---
docs/zh/docs/tutorial/body-updates.md | 96 +++++++++++++--------------
1 file changed, 47 insertions(+), 49 deletions(-)
diff --git a/docs/zh/docs/tutorial/body-updates.md b/docs/zh/docs/tutorial/body-updates.md
index 1c1dfea522e7d..e5a080eb6aafb 100644
--- a/docs/zh/docs/tutorial/body-updates.md
+++ b/docs/zh/docs/tutorial/body-updates.md
@@ -1,34 +1,34 @@
-# Body - Updates
+# 请求体 - 更新数据
-## Update replacing with `PUT`
+## 用 `PUT` 更新数据
-To update an item you can use the HTTP `PUT` operation.
+更新数据请用 HTTP `PUT` 操作。
-You can use the `jsonable_encoder` to convert the input data to data that can be stored as JSON (e.g. with a NoSQL database). For example, converting `datetime` to `str`.
+把输入数据转换为以 JSON 格式存储的数据(比如,使用 NoSQL 数据库时),可以使用 `jsonable_encoder`。 例如,把 `datetime` 转换为 `str`。
=== "Python 3.10+"
```Python hl_lines="28-33"
- {!> ../../../docs_src/body_updates/tutorial001_py310.py!}
+ !!! note "笔记"
```
=== "Python 3.9+"
```Python hl_lines="30-35"
- {!> ../../../docs_src/body_updates/tutorial001_py39.py!}
+ !!! tip "提示"
```
=== "Python 3.6+"
```Python hl_lines="30-35"
- {!> ../../../docs_src/body_updates/tutorial001.py!}
+ {!../../../docs_src/body_updates/tutorial001.py!}
```
-`PUT` is used to receive data that should replace the existing data.
+`PUT` 用于接收替换现有数据的数据。
### Warning about replacing
-That means that if you want to update the item `bar` using `PUT` with a body containing:
+用 `PUT` 把数据项 `bar` 更新为以下内容时:
```Python
{
@@ -38,39 +38,39 @@ That means that if you want to update the item `bar` using `PUT` with a body con
}
```
-because it doesn't include the already stored attribute `"tax": 20.2`, the input model would take the default value of `"tax": 10.5`.
+因为上述数据未包含已存储的属性 `"tax": 20.2`,新的输入模型会把 `"tax": 10.5` 作为默认值。
-And the data would be saved with that "new" `tax` of `10.5`.
+因此,本次操作把 `tax` 的值「更新」为 `10.5`。
-## Partial updates with `PATCH`
+## 用 `PATCH` 进行部分更新
-You can also use the HTTP `PATCH` operation to *partially* update data.
+HTTP `PATCH` 操作用于更新 *部分* 数据。
-This means that you can send only the data that you want to update, leaving the rest intact.
+即,只发送要更新的数据,其余数据保持不变。
!!! Note
`PATCH` is less commonly used and known than `PUT`.
- And many teams use only `PUT`, even for partial updates.
+ 很多人甚至只用 `PUT` 实现部分更新。
- You are **free** to use them however you want, **FastAPI** doesn't impose any restrictions.
+ **FastAPI** 对此没有任何限制,可以**随意**互换使用这两种操作。
- But this guide shows you, more or less, how they are intended to be used.
+ 但本指南也会分别介绍这两种操作各自的用途。
-### Using Pydantic's `exclude_unset` parameter
+### 使用 Pydantic 的 `exclude_unset` 参数
-If you want to receive partial updates, it's very useful to use the parameter `exclude_unset` in Pydantic's model's `.dict()`.
+更新部分数据时,可以在 Pydantic 模型的 `.dict()` 中使用 `exclude_unset` 参数。
-Like `item.dict(exclude_unset=True)`.
+比如,`item.dict(exclude_unset=True)`。
-That would generate a `dict` with only the data that was set when creating the `item` model, excluding default values.
+这段代码生成的 `dict` 只包含创建 `item` 模型时显式设置的数据,而不包括默认值。
-Then you can use this to generate a `dict` with only the data that was set (sent in the request), omitting default values:
+然后再用它生成一个只含已设置(在请求中所发送)数据,且省略了默认值的 `dict`:
=== "Python 3.10+"
```Python hl_lines="32"
- {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ 关于更新数据的警告
```
=== "Python 3.9+"
@@ -82,19 +82,19 @@ Then you can use this to generate a `dict` with only the data that was set (sent
=== "Python 3.6+"
```Python hl_lines="34"
- {!> ../../../docs_src/body_updates/tutorial002.py!}
+ {!../../../docs_src/body_updates/tutorial002.py!}
```
-### Using Pydantic's `update` parameter
+### 使用 Pydantic 的 `update` 参数
-Now, you can create a copy of the existing model using `.copy()`, and pass the `update` parameter with a `dict` containing the data to update.
+接下来,用 `.copy()` 为已有模型创建调用 `update` 参数的副本,该参数为包含更新数据的 `dict`。
-Like `stored_item_model.copy(update=update_data)`:
+例如,`stored_item_model.copy(update=update_data)`:
=== "Python 3.10+"
```Python hl_lines="33"
- {!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+ !!! Note "笔记"
```
=== "Python 3.9+"
@@ -106,23 +106,23 @@ Like `stored_item_model.copy(update=update_data)`:
=== "Python 3.6+"
```Python hl_lines="35"
- {!> ../../../docs_src/body_updates/tutorial002.py!}
+ {!../../../docs_src/body_updates/tutorial002.py!}
```
-### Partial updates recap
+### 更新部分数据小结
-In summary, to apply partial updates you would:
+简而言之,更新部分数据应:
-* (Optionally) use `PATCH` instead of `PUT`.
-* Retrieve the stored data.
-* Put that data in a Pydantic model.
-* Generate a `dict` without default values from the input model (using `exclude_unset`).
- * This way you can update only the values actually set by the user, instead of overriding values already stored with default values in your model.
-* Create a copy of the stored model, updating it's attributes with the received partial updates (using the `update` parameter).
-* Convert the copied model to something that can be stored in your DB (for example, using the `jsonable_encoder`).
- * This is comparable to using the model's `.dict()` method again, but it makes sure (and converts) the values to data types that can be converted to JSON, for example, `datetime` to `str`.
-* Save the data to your DB.
-* Return the updated model.
+* 使用 `PATCH` 而不是 `PUT` (可选,也可以用 `PUT`);
+* 提取存储的数据;
+* 把数据放入 Pydantic 模型;
+* 生成不含输入模型默认值的 `dict` (使用 `exclude_unset` 参数);
+ * 只更新用户设置过的值,不用模型中的默认值覆盖已存储过的值。
+* 为已存储的模型创建副本,用接收的数据更新其属性 (使用 `update` 参数)。
+* 把模型副本转换为可存入数据库的形式(比如,使用 `jsonable_encoder`)。
+ * 这种方式与 Pydantic 模型的 `.dict()` 方法类似,但能确保把值转换为适配 JSON 的数据类型,例如, 把 `datetime` 转换为 `str` 。
+* 把数据保存至数据库;
+* 返回更新后的模型。
=== "Python 3.10+"
@@ -139,17 +139,15 @@ In summary, to apply partial updates you would:
=== "Python 3.6+"
```Python hl_lines="30-37"
- {!> ../../../docs_src/body_updates/tutorial002.py!}
+ {!../../../docs_src/body_updates/tutorial002.py!}
```
-!!! tip
- You can actually use this same technique with an HTTP `PUT` operation.
+!!! 实际上,HTTP `PUT` 也可以完成相同的操作。
- But the example here uses `PATCH` because it was created for these use cases.
+ 但本节以 `PATCH` 为例的原因是,该操作就是为了这种用例创建的。
-!!! note
- Notice that the input model is still validated.
+!!! 注意,输入模型仍需验证。
- So, if you want to receive partial updates that can omit all the attributes, you need to have a model with all the attributes marked as optional (with default values or `None`).
+ 因此,如果希望接收的部分更新数据可以省略其他所有属性,则要把模型中所有的属性标记为可选(使用默认值或 `None`)。
- To distinguish from the models with all optional values for **updates** and models with required values for **creation**, you can use the ideas described in [Extra Models](extra-models.md){.internal-link target=_blank}.
+ 为了区分用于**更新**所有可选值的模型与用于**创建**包含必选值的模型,请参照[更多模型](extra-models.md){.internal-link target=_blank} 一节中的思路。
From 859556d9929f7e64b78fb287d4d7af085734dae9 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:30 +0800
Subject: [PATCH 126/163] New translations body.md (Chinese Simplified)
---
docs/zh/docs/tutorial/body.md | 132 +++++++++++++++++-----------------
1 file changed, 67 insertions(+), 65 deletions(-)
diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md
index 9462df2c65f86..7d840d8ade353 100644
--- a/docs/zh/docs/tutorial/body.md
+++ b/docs/zh/docs/tutorial/body.md
@@ -1,57 +1,59 @@
-# Request Body
+# 请求体
-When you need to send data from a client (let's say, a browser) to your API, you send it as a **request body**.
+当你需要将数据从客户端(例如浏览器)发送给 API 时,你将其作为「请求体」发送。
-A **request** body is data sent by the client to your API. A **response** body is the data your API sends to the client.
+**请求**体是客户端发送给 API 的数据。 **响应**体是 API 发送给客户端的数据。
-Your API almost always has to send a **response** body. But clients don't necessarily need to send **request** bodies all the time.
+你的 API 几乎总是要发送**响应**体。 但是客户端并不总是需要发送**请求**体。
-To declare a **request** body, you use Pydantic models with all their power and benefits.
+我们使用 Pydantic 模型来声明**请求**体,并能够获得它们所具有的所有能力和优点。
-!!! info
- To send data, you should use one of: `POST` (the more common), `PUT`, `DELETE` or `PATCH`.
+!!! 要发送数据,你必须使用下列方法之一:`POST`(较常见)、`PUT`、`DELETE` 或 `PATCH`。
Sending a body with a `GET` request has an undefined behavior in the specifications, nevertheless, it is supported by FastAPI, only for very complex/extreme use cases.
As it is discouraged, the interactive docs with Swagger UI won't show the documentation for the body when using `GET`, and proxies in the middle might not support it.
-## Import Pydantic's `BaseModel`
+## 导入 Pydantic 的 `BaseModel`
-First, you need to import `BaseModel` from `pydantic`:
+首先,你需要从 `pydantic` 中导入 `BaseModel`:
=== "Python 3.10+"
```Python hl_lines="2"
- {!> ../../../docs_src/body/tutorial001_py310.py!}
+ https://fastapi.tiangolo.com/img/tutorial/body/image03.png
```
=== "Python 3.6+"
```Python hl_lines="4"
- {!> ../../../docs_src/body/tutorial001.py!}
+ {!../../../docs_src/body/tutorial001.py!}
```
-## Create your data model
+## 创建数据模型
-Then you declare your data model as a class that inherits from `BaseModel`.
+然后,将你的数据模型声明为继承自 `BaseModel` 的类。
-Use standard Python types for all the attributes:
+使用标准的 Python 类型来声明所有属性:
=== "Python 3.10+"
```Python hl_lines="5-9"
- {!> ../../../docs_src/body/tutorial001_py310.py!}
+ !!! info
+ 你不能使用 GET 操作(HTTP 方法)发送请求体。
```
+ 操作(HTTP 方法)发送请求体。
+
=== "Python 3.6+"
```Python hl_lines="7-11"
- {!> ../../../docs_src/body/tutorial001.py!}
+ {!../../../docs_src/body/tutorial001.py!}
```
-The same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. Use `None` to make it just optional.
+和声明查询参数时一样,当一个模型属性具有默认值时,它不是必需的。 否则它是一个必需属性。 将默认值设为 `None` 可使其成为可选属性。
-For example, this model above declares a JSON "`object`" (or Python `dict`) like:
+例如,上面的模型声明了一个这样的 JSON「`object`」(或 Python `dict`):
```JSON
{
@@ -62,7 +64,7 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
}
```
-...as `description` and `tax` are optional (with a default value of `None`), this JSON "`object`" would also be valid:
+...由于 `description` 和 `tax` 是可选的(它们的默认值为 `None`),下面的 JSON「`object`」也将是有效的:
```JSON
{
@@ -71,66 +73,66 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
}
```
-## Declare it as a parameter
+## 声明为参数
-To add it to your *path operation*, declare it the same way you declared path and query parameters:
+使用与声明路径和查询参数的相同方式声明请求体,即可将其添加到「路径操作」中:
=== "Python 3.10+"
```Python hl_lines="16"
- {!> ../../../docs_src/body/tutorial001_py310.py!}
+ https://fastapi.tiangolo.com/img/tutorial/body/image05.png
```
=== "Python 3.6+"
```Python hl_lines="18"
- {!> ../../../docs_src/body/tutorial001.py!}
+ {!../../../docs_src/body/tutorial001.py!}
```
-...and declare its type as the model you created, `Item`.
+...并且将它的类型声明为你创建的 `Item` 模型。
-## Results
+## 结果
-With just that Python type declaration, **FastAPI** will:
+仅仅使用了 Python 类型声明,**FastAPI** 将会:
-* Read the body of the request as JSON.
-* Convert the corresponding types (if needed).
-* Validate the data.
- * If the data is invalid, it will return a nice and clear error, indicating exactly where and what was the incorrect data.
-* Give you the received data in the parameter `item`.
- * As you declared it in the function to be of type `Item`, you will also have all the editor support (completion, etc) for all of the attributes and their types.
-* Generate JSON Schema definitions for your model, you can also use them anywhere else you like if it makes sense for your project.
-* Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentation UIs.
+* 将请求体作为 JSON 读取。
+* 转换为相应的类型(在需要时)。
+* 校验数据。
+ * 如果数据无效,将返回一条清晰易读的错误信息,指出不正确数据的确切位置和内容。
+* 将接收的数据赋值到参数 `item` 中。
+ * 由于你已经在函数中将它声明为 `Item` 类型,你还将获得对于所有属性及其类型的一切编辑器支持(代码补全等)。
+* 为你的模型生成 JSON 模式 定义,你还可以在其他任何对你的项目有意义的地方使用它们。
+* 这些模式将成为生成的 OpenAPI 模式的一部分,并且被自动化文档 UI 所使用。
-## Automatic docs
+## 自动化文档
-The JSON Schemas of your models will be part of your OpenAPI generated schema, and will be shown in the interactive API docs:
+你所定义模型的 JSON 模式将成为生成的 OpenAPI 模式的一部分,并且在交互式 API 文档中展示:
-And will be also used in the API docs inside each *path operation* that needs them:
+而且还将在每一个需要它们的*路径操作*的 API 文档中使用:
-## Editor support
+## 编辑器支持
-In your editor, inside your function you will get type hints and completion everywhere (this wouldn't happen if you received a `dict` instead of a Pydantic model):
+在你的编辑器中,你会在函数内部的任意地方得到类型提示和代码补全(如果你接收的是一个 `dict` 而不是 Pydantic 模型,则不会发生这种情况):
-You also get error checks for incorrect type operations:
+你还会获得对不正确的类型操作的错误检查:
-This is not by chance, the whole framework was built around that design.
+这并非偶然,整个框架都是围绕该设计而构建。
-And it was thoroughly tested at the design phase, before any implementation, to ensure it would work with all the editors.
+并且在进行任何实现之前,已经在设计阶段经过了全面测试,以确保它可以在所有的编辑器中生效。
-There were even some changes to Pydantic itself to support this.
+Pydantic 本身甚至也进行了一些更改以支持此功能。
-The previous screenshots were taken with Visual Studio Code.
+上面的截图取自 Visual Studio Code。
-But you would get the same editor support with PyCharm and most of the other Python editors:
+但是在 PyCharm 和绝大多数其他 Python 编辑器中你也会获得同样的编辑器支持:
@@ -145,69 +147,69 @@ But you would get the same editor support with ../../../docs_src/body/tutorial002_py310.py!}
+ https://fastapi.tiangolo.com/img/tutorial/body/image01.png
```
=== "Python 3.6+"
```Python hl_lines="21"
- {!> ../../../docs_src/body/tutorial002.py!}
+ {!../../../docs_src/body/tutorial002.py!}
```
-## Request body + path parameters
+## 请求体 + 路径参数
-You can declare path parameters and request body at the same time.
+你可以同时声明路径参数和请求体。
-**FastAPI** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared to be Pydantic models should be **taken from the request body**.
+**FastAPI** 将识别出与路径参数匹配的函数参数应**从路径中获取**,而声明为 Pydantic 模型的函数参数应**从请求体中获取**。
=== "Python 3.10+"
```Python hl_lines="15-16"
- {!> ../../../docs_src/body/tutorial003_py310.py!}
+ https://fastapi.tiangolo.com/img/tutorial/body/image04.png
```
=== "Python 3.6+"
```Python hl_lines="17-18"
- {!> ../../../docs_src/body/tutorial003.py!}
+ {!../../../docs_src/body/tutorial003.py!}
```
-## Request body + path + query parameters
+## 请求体 + 路径参数 + 查询参数
-You can also declare **body**, **path** and **query** parameters, all at the same time.
+你还可以同时声明**请求体**、**路径参数**和**查询参数**。
-**FastAPI** will recognize each of them and take the data from the correct place.
+**FastAPI** 会识别它们中的每一个,并从正确的位置获取数据。
=== "Python 3.10+"
```Python hl_lines="16"
- {!> ../../../docs_src/body/tutorial004_py310.py!}
+ https://fastapi.tiangolo.com/img/tutorial/body/image02.png
```
=== "Python 3.6+"
```Python hl_lines="18"
- {!> ../../../docs_src/body/tutorial004.py!}
+ {!../../../docs_src/body/tutorial004.py!}
```
-The function parameters will be recognized as follows:
+函数参数将依次按如下规则进行识别:
-* If the parameter is also declared in the **path**, it will be used as a path parameter.
-* If the parameter is of a **singular type** (like `int`, `float`, `str`, `bool`, etc) it will be interpreted as a **query** parameter.
-* If the parameter is declared to be of the type of a **Pydantic model**, it will be interpreted as a request **body**.
+* 如果在**路径**中也声明了该参数,它将被用作路径参数。
+* 如果参数属于**单一类型**(比如 `int`、`float`、`str`、`bool` 等)它将被解释为**查询**参数。
+* 如果参数的类型被声明为一个 **Pydantic 模型**,它将被解释为**请求体**。
!!! note
FastAPI will know that the value of `q` is not required because of the default value `= None`.
The `Union` in `Union[str, None]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
-## Without Pydantic
+## 不使用 Pydantic
-If you don't want to use Pydantic models, you can also use **Body** parameters. See the docs for [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
+如果你不想使用 Pydantic 模型,你还可以使用 **Body** 参数。 请参阅文档 [请求体 - 多个参数:请求体中的单一值](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}。
From ecaef02de3c1db14f1215376d7e559a5d495bd94 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:31 +0800
Subject: [PATCH 127/163] New translations cookie-params.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/cookie-params.md | 34 +++++++++++++++-----------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/docs/zh/docs/tutorial/cookie-params.md b/docs/zh/docs/tutorial/cookie-params.md
index 111e93458e686..5e9a59af732f5 100644
--- a/docs/zh/docs/tutorial/cookie-params.md
+++ b/docs/zh/docs/tutorial/cookie-params.md
@@ -1,10 +1,10 @@
-# Cookie Parameters
+# Cookie 参数
-You can define Cookie parameters the same way you define `Query` and `Path` parameters.
+你可以像定义 `Query` 参数和 `Path` 参数一样来定义 `Cookie` 参数。
-## Import `Cookie`
+## 导入 `Cookie`
-First import `Cookie`:
+首先,导入 `Cookie`:
=== "Python 3.10+"
@@ -30,7 +30,7 @@ First import `Cookie`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
- {!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
+ {!../../../docs_src/cookie_params/tutorial001.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -39,19 +39,22 @@ First import `Cookie`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
- {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ !!! info
+ 你需要使用 Cookie 来声明 cookie 参数,否则参数将会被解释为查询参数。
```
+ 来声明 cookie 参数,否则参数将会被解释为查询参数。
+
-## Declare `Cookie` parameters
+## 声明 `Cookie` 参数
-Then declare the cookie parameters using the same structure as with `Path` and `Query`.
+声明 `Cookie` 参数的结构与声明 `Query` 参数和 `Path` 参数时相同。
-The first value is the default value, you can pass all the extra validation or annotation parameters:
+第一个值是参数的默认值,同时也可以传递所有验证参数或注释参数,来校验参数:
=== "Python 3.10+"
```Python hl_lines="9"
- {!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
+ 总结
```
=== "Python 3.9+"
@@ -63,7 +66,7 @@ The first value is the default value, you can pass all the extra validation or a
=== "Python 3.6+"
```Python hl_lines="10"
- {!> ../../../docs_src/cookie_params/tutorial001_an.py!}
+ {!../../../docs_src/cookie_params/tutorial001.py!}
```
=== "Python 3.10+ non-Annotated"
@@ -81,17 +84,20 @@ The first value is the default value, you can pass all the extra validation or a
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
- {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ !!! note "技术细节"
+ Cookie 、Path 、Query是兄弟类,它们都继承自公共的 Param 类
```
+ 、Path 、Query是兄弟类,它们都继承自公共的 Param 类
+
!!! note "Technical Details"
`Cookie` is a "sister" class of `Path` and `Query`. It also inherits from the same common `Param` class.
- But remember that when you import `Query`, `Path`, `Cookie` and others from `fastapi`, those are actually functions that return special classes.
+ 但请记住,当你从 `fastapi` 导入的 `Query`、`Path`、`Cookie` 或其他参数声明函数,这些实际上是返回特殊类的函数。
!!! info
To declare cookies, you need to use `Cookie`, because otherwise the parameters would be interpreted as query parameters.
## Recap
-Declare cookies with `Cookie`, using the same common pattern as `Query` and `Path`.
+使用 `Cookie` 声明 cookie 参数,使用方式与 `Query` 和 `Path` 类似。
From a396bd319da0c3167bcf4c77eaf4a5443ca3b205 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:32 +0800
Subject: [PATCH 128/163] New translations cors.md (Chinese Simplified)
---
docs/zh/docs/tutorial/cors.md | 86 +++++++++++++++++------------------
1 file changed, 43 insertions(+), 43 deletions(-)
diff --git a/docs/zh/docs/tutorial/cors.md b/docs/zh/docs/tutorial/cors.md
index 33b11983b32b5..171989cf1da18 100644
--- a/docs/zh/docs/tutorial/cors.md
+++ b/docs/zh/docs/tutorial/cors.md
@@ -1,84 +1,84 @@
-# CORS (Cross-Origin Resource Sharing)
+# CORS(跨域资源共享)
-CORS or "Cross-Origin Resource Sharing" refers to the situations when a frontend running in a browser has JavaScript code that communicates with a backend, and the backend is in a different "origin" than the frontend.
+CORS 或者「跨域资源共享」 指浏览器中运行的前端拥有与后端通信的 JavaScript 代码,而后端处于与前端不同的「源」的情况。
-## Origin
+## 源
-An origin is the combination of protocol (`http`, `https`), domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`), and port (`80`, `443`, `8080`).
+源是协议(`http`,`https`)、域(`myapp.com`,`localhost`,`localhost.tiangolo.com`)以及端口(`80`、`443`、`8080`)的组合。
-So, all these are different origins:
+因此,这些都是不同的源:
* `http://localhost`
* `https://localhost`
* `http://localhost:8080`
-Even if they are all in `localhost`, they use different protocols or ports, so, they are different "origins".
+即使它们都在 `localhost` 中,但是它们使用不同的协议或者端口,所以它们都是不同的「源」。
-## Steps
+## 步骤
-So, let's say you have a frontend running in your browser at `http://localhost:8080`, and its JavaScript is trying to communicate with a backend running at `http://localhost` (because we don't specify a port, the browser will assume the default port `80`).
+假设你的浏览器中有一个前端运行在 `http://localhost:8080`,并且它的 JavaScript 正在尝试与运行在 `http://localhost` 的后端通信(因为我们没有指定端口,浏览器会采用默认的端口 `80`)。
-Then, the browser will send an HTTP `OPTIONS` request to the backend, and if the backend sends the appropriate headers authorizing the communication from this different origin (`http://localhost:8080`) then the browser will let the JavaScript in the frontend send its request to the backend.
+然后,浏览器会向后端发送一个 HTTP `OPTIONS` 请求,如果后端发送适当的 headers 来授权来自这个不同源(`http://localhost:8080`)的通信,浏览器将允许前端的 JavaScript 向后端发送请求。
-To achieve this, the backend must have a list of "allowed origins".
+为此,后端必须有一个「允许的源」列表。
-In this case, it would have to include `http://localhost:8080` for the frontend to work correctly.
+在这种情况下,它必须包含 `http://localhost:8080`,前端才能正常工作。
## Wildcards
-It's also possible to declare the list as `"*"` (a "wildcard") to say that all are allowed.
+也可以使用 `"*"`(一个「通配符」)声明这个列表,表示全部都是允许的。
-But that will only allow certain types of communication, excluding everything that involves credentials: Cookies, Authorization headers like those used with Bearer Tokens, etc.
+但这仅允许某些类型的通信,不包括所有涉及凭据的内容:像 Cookies 以及那些使用 Bearer 令牌的授权 headers 等。
-So, for everything to work correctly, it's better to specify explicitly the allowed origins.
+因此,为了一切都能正常工作,最好显式地指定允许的源。
-## Use `CORSMiddleware`
+## 使用 `CORSMiddleware`
-You can configure it in your **FastAPI** application using the `CORSMiddleware`.
+你可以在 **FastAPI** 应用中使用 `CORSMiddleware` 来配置它。
-* Import `CORSMiddleware`.
-* Create a list of allowed origins (as strings).
-* Add it as a "middleware" to your **FastAPI** application.
+* 导入 `CORSMiddleware`。
+* 创建一个允许的源列表(由字符串组成)。
+* 将其作为「中间件」添加到你的 **FastAPI** 应用中。
-You can also specify if your backend allows:
+你也可以指定后端是否允许:
-* Credentials (Authorization headers, Cookies, etc).
-* Specific HTTP methods (`POST`, `PUT`) or all of them with the wildcard `"*"`.
-* Specific HTTP headers or all of them with the wildcard `"*"`.
+* 凭证(授权 headers,Cookies 等)。
+* 特定的 HTTP 方法(`POST`,`PUT`)或者使用通配符 `"*"` 允许所有方法。
+* 特定的 HTTP headers 或者使用通配符 `"*"` 允许所有 headers。
```Python hl_lines="2 6-11 13-19"
{!../../../docs_src/cors/tutorial001.py!}
```
-The default parameters used by the `CORSMiddleware` implementation are restrictive by default, so you'll need to explicitly enable particular origins, methods, or headers, in order for browsers to be permitted to use them in a Cross-Domain context.
+默认情况下,这个 `CORSMiddleware` 实现所使用的默认参数较为保守,所以你需要显式地启用特定的源、方法或者 headers,以便浏览器能够在跨域上下文中使用它们。
-The following arguments are supported:
+支持以下参数:
-* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. E.g. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
-* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`.
-* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
-* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for simple CORS requests.
-* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified.
-* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
-* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.
+* `allow_origins` - 一个允许跨域请求的源列表。 E.g. 例如 `['https://example.org', 'https://www.example.org']`。 你可以使用 `['*']` 允许任何源。
+* `allow_origin_regex` - 一个正则表达式字符串,匹配的源允许跨域请求。 例如 `'https://.*\.example\.org'`。
+* `allow_methods` - 一个允许跨域请求的 HTTP 方法列表。 默认为 `['GET']`。 你可以使用 `['*']` 来允许所有标准方法。
+* `allow_headers` - 一个允许跨域请求的 HTTP 请求头列表。 默认为 `[]`。 你可以使用 `['*']` 允许所有的请求头。 `Accept`、`Accept-Language`、`Content-Language` 以及 `Content-Type` 请求头总是允许 CORS 请求。
+* `allow_credentials` - 指示跨域请求支持 cookies。 默认是 `False`。 另外,允许凭证时 `allow_origins` 不能设定为 `['*']`,必须指定源。
+* `expose_headers` - 指示可以被浏览器访问的响应头。 默认为 `[]`。
+* `max_age` - 设定浏览器缓存 CORS 响应的最长时间,单位是秒。 默认为 `600`。
-The middleware responds to two particular types of HTTP request...
+中间件响应两种特定类型的 HTTP 请求……
-### CORS preflight requests
+### CORS 预检请求
-These are any `OPTIONS` request with `Origin` and `Access-Control-Request-Method` headers.
+这是些带有 `Origin` 和 `Access-Control-Request-Method` 请求头的 `OPTIONS` 请求。
-In this case the middleware will intercept the incoming request and respond with appropriate CORS headers, and either a `200` or `400` response for informational purposes.
+在这种情况下,中间件将拦截传入的请求并进行响应,出于提供信息的目的返回一个使用了适当的 CORS headers 的 `200` 或 `400` 响应。
-### Simple requests
+### 简单请求
-Any request with an `Origin` header. In this case the middleware will pass the request through as normal, but will include appropriate CORS headers on the response.
+任何带有 `Origin` 请求头的请求。 在这种情况下,中间件将像平常一样传递请求,但是在响应中包含适当的 CORS headers。
-## More info
+## 更多信息
-For more info about CORS, check the Mozilla CORS documentation.
+更多关于 CORS 的信息,请查看 Mozilla CORS 文档。
-!!! note "Technical Details"
- You could also use `from starlette.middleware.cors import CORSMiddleware`.
+!!! !!! note "技术细节"
+ 你也可以使用 `from starlette.middleware.cors import CORSMiddleware`。
- **FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette.
+ 出于方便,**FastAPI** 在 `fastapi.middleware` 中为开发者提供了几个中间件。 但是大多数可用的中间件都是直接来自 Starlette。
From 6193f9e28efcba9b45dbfe97953d12b20f564158 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:33 +0800
Subject: [PATCH 129/163] New translations debugging.md (Chinese Simplified)
---
docs/zh/docs/tutorial/debugging.md | 58 +++++++++++++++---------------
1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/docs/zh/docs/tutorial/debugging.md b/docs/zh/docs/tutorial/debugging.md
index 8d76347cffcba..10a7a31a05296 100644
--- a/docs/zh/docs/tutorial/debugging.md
+++ b/docs/zh/docs/tutorial/debugging.md
@@ -1,18 +1,18 @@
# Debugging
-You can connect the debugger in your editor, for example with Visual Studio Code or PyCharm.
+你可以在编辑器中连接调试器,例如使用 Visual Studio Code 或 PyCharm。
-## Call `uvicorn`
+## 调用 `uvicorn`
-In your FastAPI application, import and run `uvicorn` directly:
+在你的 FastAPI 应用中直接导入 `uvicorn` 并运行:
```Python hl_lines="1 15"
{!../../../docs_src/debugging/tutorial001.py!}
```
-### About `__name__ == "__main__"`
+### 关于 `__name__ == "__main__"`
-The main purpose of the `__name__ == "__main__"` is to have some code that is executed when your file is called with:
+`__name__ == "__main__"` 的主要目的是使用以下代码调用文件时执行一些代码:
---
-If you use Pycharm, you can:
+如果使用 Pycharm,你可以:
-* Open the "Run" menu.
+* 打开「运行」菜单。
* Select the option "Debug...".
-* Then a context menu shows up.
-* Select the file to debug (in this case, `main.py`).
+* 然后出现一个上下文菜单。
+* 选择要调试的文件(本例中的 `main.py`)。
-It will then start the server with your **FastAPI** code, stop at your breakpoints, etc.
+然后它会使用你的 **FastAPI** 代码开启服务器,停在断点处,等等。
-Here's how it might look:
+看起来可能是这样:
From 06f45ba92af687ca6a772ef3748f936d5d5076be Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:34 +0800
Subject: [PATCH 130/163] New translations classes-as-dependencies.md (Chinese
Simplified)
---
.../dependencies/classes-as-dependencies.md | 119 +++++++++---------
1 file changed, 60 insertions(+), 59 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
index a1409c8f88701..7da62b650bca0 100644
--- a/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
+++ b/docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -1,10 +1,10 @@
-# Classes as Dependencies
+# 类作为依赖项
-Before diving deeper into the **Dependency Injection** system, let's upgrade the previous example.
+在深入探究 **依赖注入** 系统之前,让我们升级之前的例子。
-## A `dict` from the previous example
+## 来自前一个例子的`dict`
-In the previous example, we were returning a `dict` from our dependency ("dependable"):
+在前面的例子中, 我们从依赖项 ("可依赖对象") 中返回了一个 `dict`:
=== "Python 3.10+"
@@ -42,29 +42,29 @@ In the previous example, we were returning a `dict` from our dependency ("depend
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
-But then we get a `dict` in the parameter `commons` of the *path operation function*.
+但是后面我们在路径操作函数的参数 `commons` 中得到了一个 `dict`。
-And we know that editors can't provide a lot of support (like completion) for `dict`s, because they can't know their keys and value types.
+我们知道编辑器不能为 `dict` 提供很多支持(比如补全),因为编辑器不知道 `dict` 的键和值类型。
-We can do better...
+对此,我们可以做的更好...
-## What makes a dependency
+## 什么构成了依赖项?
-Up to now you have seen dependencies declared as functions.
+到目前为止,您看到的依赖项都被声明为函数。
-But that's not the only way to declare dependencies (although it would probably be the more common).
+但这并不是声明依赖项的唯一方法(尽管它可能是更常见的方法)。
The key factor is that a dependency should be a "callable".
-A "**callable**" in Python is anything that Python can "call" like a function.
+Python 中的 "**可调用对象**" 是指任何 Python 可以像函数一样 "调用" 的对象。
-So, if you have an object `something` (that might _not_ be a function) and you can "call" it (execute it) like:
+所以,如果你有一个对象 `something` (可能*不是*一个函数),你可以 "调用" 它(执行它),就像:
```Python
something()
```
-or
+或者
```Python
something(some_argument, some_keyword_argument="foo")
@@ -72,11 +72,11 @@ something(some_argument, some_keyword_argument="foo")
then it is a "callable".
-## Classes as dependencies
+## 类作为依赖项
-You might notice that to create an instance of a Python class, you use that same syntax.
+您可能会注意到,要创建一个 Python 类的实例,您可以使用相同的语法。
-For example:
+举个例子:
```Python
class Cat:
@@ -87,21 +87,21 @@ class Cat:
fluffy = Cat(name="Mr Fluffy")
```
-In this case, `fluffy` is an instance of the class `Cat`.
+在这个例子中, `fluffy` 是一个 `Cat` 类的实例。
-And to create `fluffy`, you are "calling" `Cat`.
+为了创建 `fluffy`,你调用了 `Cat` 。
-So, a Python class is also a **callable**.
+所以,Python 类也是 **可调用对象**。
-Then, in **FastAPI**, you could use a Python class as a dependency.
+因此,在 **FastAPI** 中,你可以使用一个 Python 类作为一个依赖项。
-What FastAPI actually checks is that it is a "callable" (function, class or anything else) and the parameters defined.
+实际上 FastAPI 检查的是它是一个 "可调用对象"(函数,类或其他任何类型)以及定义的参数。
-If you pass a "callable" as a dependency in **FastAPI**, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a *path operation function*. Including sub-dependencies.
+如果您在 **FastAPI** 中传递一个 "可调用对象" 作为依赖项,它将分析该 "可调用对象" 的参数,并以处理路径操作函数的参数的方式来处理它们。 包括子依赖项。
-That also applies to callables with no parameters at all. The same as it would be for *path operation functions* with no parameters.
+这也适用于完全没有参数的可调用对象。 这与不带参数的路径操作函数一样。
-Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParams`:
+所以,我们可以将上面的依赖项 "可依赖对象" `common_parameters` 更改为类 `CommonQueryParams`:
=== "Python 3.10+"
@@ -139,7 +139,7 @@ Then, we can change the dependency "dependable" `common_parameters` from above t
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-Pay attention to the `__init__` method used to create the instance of the class:
+注意用于创建类实例的 `__init__` 方法:
=== "Python 3.10+"
@@ -177,7 +177,7 @@ Pay attention to the `__init__` method used to create the instance of the class:
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-...it has the same parameters as our previous `common_parameters`:
+...它与我们以前的 `common_parameters` 具有相同的参数:
=== "Python 3.10+"
@@ -215,19 +215,19 @@ Pay attention to the `__init__` method used to create the instance of the class:
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
-Those parameters are what **FastAPI** will use to "solve" the dependency.
+这些参数就是 **FastAPI** 用来 "处理" 依赖项的。
-In both cases, it will have:
+在两个例子下,都有:
-* An optional `q` query parameter that is a `str`.
-* A `skip` query parameter that is an `int`, with a default of `0`.
-* A `limit` query parameter that is an `int`, with a default of `100`.
+* 一个可选的 `q` 查询参数,是 `str` 类型。
+* 一个 `skip` 查询参数,是 `int` 类型,默认值为 `0`。
+* 一个 `limit` 查询参数,是 `int` 类型,默认值为 `100`。
-In both cases the data will be converted, validated, documented on the OpenAPI schema, etc.
+在两个例子下,数据都将被转换、验证、在 OpenAPI schema 上文档化,等等。
-## Use it
+## 使用它
-Now you can declare your dependency using this class.
+现在,您可以使用这个类来声明你的依赖项了。
=== "Python 3.10+"
@@ -265,11 +265,11 @@ Now you can declare your dependency using this class.
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
-**FastAPI** calls the `CommonQueryParams` class. This creates an "instance" of that class and the instance will be passed as the parameter `commons` to your function.
+**FastAPI** 调用 `CommonQueryParams` 类。 这将创建该类的一个 "实例",该实例将作为参数 `commons` 被传递给你的函数。
-## Type annotation vs `Depends`
+## 类型注解 vs `Depends`
-Notice how we write `CommonQueryParams` twice in the above code:
+注意,我们在上面的代码中编写了两次`CommonQueryParams`:
=== "Python 3.6+ non-Annotated"
@@ -283,27 +283,27 @@ Notice how we write `CommonQueryParams` twice in the above code:
=== "Python 3.6+"
```Python
- commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
+ ... = Depends(CommonQueryParams)
```
-The last `CommonQueryParams`, in:
+最后的 `CommonQueryParams`:
```Python
... Depends(CommonQueryParams)
```
-...is what **FastAPI** will actually use to know what is the dependency.
+...实际上是 **Fastapi** 用来知道依赖项是什么的。
-From it is that FastAPI will extract the declared parameters and that is what FastAPI will actually call.
+FastAPI 将从依赖项中提取声明的参数,这才是 FastAPI 实际调用的。
---
-In this case, the first `CommonQueryParams`, in:
+在本例中,第一个 `CommonQueryParams` :
=== "Python 3.6+"
```Python
- commons: Annotated[CommonQueryParams, ...
+ 这就是 "可调用对象"。
```
=== "Python 3.6+ non-Annotated"
@@ -315,14 +315,15 @@ In this case, the first `CommonQueryParams`, in:
commons: CommonQueryParams ...
```
-...doesn't have any special meaning for **FastAPI**. FastAPI won't use it for data conversion, validation, etc. (as it is using the `Depends(CommonQueryParams)` for that).
+...对于 **FastAPI** 没有任何特殊的意义。 FastAPI 不会使用它进行数据转换、验证等 (因为对于这,它使用 `= Depends(CommonQueryParams)`)。
-You could actually write just:
+你实际上可以只这样编写:
=== "Python 3.6+"
```Python
- commons: Annotated[Any, Depends(CommonQueryParams)]
+ !!! tip
+ 如果这看起来更加混乱而不是更加有帮助,那么请忽略它,你不需要它。
```
=== "Python 3.6+ non-Annotated"
@@ -334,7 +335,7 @@ You could actually write just:
commons = Depends(CommonQueryParams)
```
-..as in:
+..就像:
=== "Python 3.10+"
@@ -372,13 +373,13 @@ You could actually write just:
{!> ../../../docs_src/dependencies/tutorial003.py!}
```
-But declaring the type is encouraged as that way your editor will know what will be passed as the parameter `commons`, and then it can help you with code completion, type checks, etc:
+但是声明类型是被鼓励的,因为那样你的编辑器就会知道将传递什么作为参数 `commons` ,然后它可以帮助你完成代码,类型检查,等等:
-## Shortcut
+## 快捷方式
-But you see that we are having some code repetition here, writing `CommonQueryParams` twice:
+但是您可以看到,我们在这里有一些代码重复了,编写了`CommonQueryParams`两次:
=== "Python 3.6+ non-Annotated"
@@ -395,11 +396,11 @@ But you see that we are having some code repetition here, writing `CommonQueryPa
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
-**FastAPI** provides a shortcut for these cases, in where the dependency is *specifically* a class that **FastAPI** will "call" to create an instance of the class itself.
+**FastAPI** 为这些情况提供了一个快捷方式,在这些情况下,依赖项 *明确地* 是一个类,**FastAPI** 将 "调用" 它来创建类本身的一个实例。
-For those specific cases, you can do the following:
+对于这些特定的情况,您可以跟随以下操作:
-Instead of writing:
+不是写成这样:
=== "Python 3.6+"
@@ -416,12 +417,12 @@ Instead of writing:
commons: CommonQueryParams = Depends(CommonQueryParams)
```
-...you write:
+...而是这样写:
=== "Python 3.6+"
```Python
- commons: Annotated[CommonQueryParams, Depends()]
+ 关键因素是依赖项应该是 "可调用对象"。
```
=== "Python 3.6 non-Annotated"
@@ -433,9 +434,9 @@ Instead of writing:
commons: CommonQueryParams = Depends()
```
-You declare the dependency as the type of the parameter, and you use `Depends()` without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
+您声明依赖项作为参数的类型,并使用 `Depends()` 作为该函数的参数的 "默认" 值(在 `=` 之后),而在 `Depends()` 中没有任何参数,而不是在 `Depends(CommonQueryParams)` 编写完整的类。
-The same example would then look like:
+同样的例子看起来像这样:
=== "Python 3.10+"
@@ -473,9 +474,9 @@ The same example would then look like:
{!> ../../../docs_src/dependencies/tutorial004.py!}
```
-...and **FastAPI** will know what to do.
+... **FastAPI** 会知道怎么处理。
!!! tip
If that seems more confusing than helpful, disregard it, you don't *need* it.
- It is just a shortcut. Because **FastAPI** cares about helping you minimize code repetition.
+ 这只是一个快捷方式。 因为 **FastAPI** 关心的是帮助您减少代码重复。
From f5f32f9d9c63aa204d4c74eb23a639b455f2199a Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:35 +0800
Subject: [PATCH 131/163] New translations
dependencies-in-path-operation-decorators.md (Chinese Simplified)
---
...pendencies-in-path-operation-decorators.md | 66 +++++++++----------
1 file changed, 32 insertions(+), 34 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
index 00a90424934af..f7961ad050a95 100644
--- a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
+++ b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
@@ -1,18 +1,18 @@
-# Dependencies in path operation decorators
+# 路径操作装饰器依赖项
-In some cases you don't really need the return value of a dependency inside your *path operation function*.
+有时,我们并不需要在*路径操作函数*中使用依赖项的返回值。
-Or the dependency doesn't return a value.
+或者说,有些依赖项不返回值。
But you still need it to be executed/solved.
-For those cases, instead of declaring a *path operation function* parameter with `Depends`, you can add a `list` of `dependencies` to the *path operation decorator*.
+对于这种情况,不必在声明*路径操作函数*的参数时使用 `Depends`,而是可以在*路径操作装饰器*中添加一个由 `dependencies` 组成的 `list`。
-## Add `dependencies` to the *path operation decorator*
+## 在*路径操作装饰器*中添加 `dependencies` 参数
-The *path operation decorator* receives an optional argument `dependencies`.
+*路径操作装饰器*支持可选参数 ~ `dependencies`。
-It should be a `list` of `Depends()`:
+该参数的值是由 `Depends()` 组成的 `list`:
=== "Python 3.9+"
@@ -23,7 +23,7 @@ It should be a `list` of `Depends()`:
=== "Python 3.6+"
```Python hl_lines="18"
- {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ !!! tip "提示"
```
=== "Python 3.6 non-Annotated"
@@ -32,30 +32,28 @@ It should be a `list` of `Depends()`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
- {!> ../../../docs_src/dependencies/tutorial006.py!}
+ {!../../../docs_src/dependencies/tutorial006.py!}
```
These dependencies will be executed/solved the same way normal dependencies. But their value (if they return any) won't be passed to your *path operation function*.
-!!! tip
- Some editors check for unused function parameters, and show them as errors.
+!!! 有些编辑器会检查代码中没使用过的函数参数,并显示错误提示。
- Using these `dependencies` in the *path operation decorator* you can make sure they are executed while avoiding editor/tooling errors.
+ 在*路径操作装饰器*中使用 `dependencies` 参数,可以确保在执行依赖项的同时,避免编辑器显示错误提示。
It might also help avoid confusion for new developers that see an unused parameter in your code and could think it's unnecessary.
-!!! info
- In this example we use invented custom headers `X-Key` and `X-Token`.
+!!! 本例中,使用的是自定义响应头 `X-Key` 和 `X-Token`。
- But in real cases, when implementing security, you would get more benefits from using the integrated [Security utilities (the next chapter)](../security/index.md){.internal-link target=_blank}.
+ 但实际开发中,尤其是在实现安全措施时,最好使用 FastAPI 内置的[安全工具](../security/index.md){.internal-link target=_blank}(详见下一章)。
-## Dependencies errors and return values
+## 依赖项错误和返回值
-You can use the same dependency *functions* you use normally.
+路径装饰器依赖项也可以使用普通的依赖项*函数*。
-### Dependency requirements
+### 依赖项的需求项
-They can declare request requirements (like headers) or other sub-dependencies:
+路径装饰器依赖项可以声明请求的需求项(比如响应头)或其他子依赖项:
=== "Python 3.9+"
@@ -66,7 +64,7 @@ They can declare request requirements (like headers) or other sub-dependencies:
=== "Python 3.6+"
```Python hl_lines="7 12"
- {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ !!! info "说明"
```
=== "Python 3.6 non-Annotated"
@@ -75,23 +73,23 @@ They can declare request requirements (like headers) or other sub-dependencies:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6 11"
- {!> ../../../docs_src/dependencies/tutorial006.py!}
+ {!../../../docs_src/dependencies/tutorial006.py!}
```
### Raise exceptions
-These dependencies can `raise` exceptions, the same as normal dependencies:
+路径装饰器依赖项与正常的依赖项一样,可以 `raise` 异常:
=== "Python 3.9+"
```Python hl_lines="10 15"
- {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ 但仍要执行或解析该依赖项。
```
=== "Python 3.6+"
```Python hl_lines="9 14"
- {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ 无论路径装饰器依赖项是否返回值,路径操作都不会使用这些值。
```
=== "Python 3.6 non-Annotated"
@@ -100,25 +98,25 @@ These dependencies can `raise` exceptions, the same as normal dependencies:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8 13"
- {!> ../../../docs_src/dependencies/tutorial006.py!}
+ {!../../../docs_src/dependencies/tutorial006.py!}
```
-### Return values
+### 返回值
And they can return values or not, the values won't be used.
-So, you can re-use a normal dependency (that returns a value) you already use somewhere else, and even though the value won't be used, the dependency will be executed:
+因此,可以复用在其他位置使用过的、(能返回值的)普通依赖项,即使没有使用这个值,也会执行该依赖项:
=== "Python 3.9+"
```Python hl_lines="11 16"
- {!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
+ 路径操作装饰器依赖项(以下简称为“路径装饰器依赖项”)的执行或解析方式和普通依赖项一样,但就算这些依赖项会返回值,它们的值也不会传递给路径操作函数。
```
=== "Python 3.6+"
```Python hl_lines="10 15"
- {!> ../../../docs_src/dependencies/tutorial006_an.py!}
+ 触发异常
```
=== "Python 3.6 non-Annotated"
@@ -127,13 +125,13 @@ So, you can re-use a normal dependency (that returns a value) you already use so
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9 14"
- {!> ../../../docs_src/dependencies/tutorial006.py!}
+ {!../../../docs_src/dependencies/tutorial006.py!}
```
-## Dependencies for a group of *path operations*
+## 为一组路径操作定义依赖项
-Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
+稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md){.internal-link target=\_blank}一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,您将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。
-## Global Dependencies
+## 全局依赖项
-Next we will see how to add dependencies to the whole `FastAPI` application, so that they apply to each *path operation*.
+接下来,我们将学习如何为 `FastAPI` 应用程序添加全局依赖项,创建应用于每个*路径操作*的依赖项。
From 993ae5bd944cf277fdc9f6290d1aee100486bc71 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:36 +0800
Subject: [PATCH 132/163] New translations global-dependencies.md (Chinese
Simplified)
---
.../tutorial/dependencies/global-dependencies.md | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/global-dependencies.md b/docs/zh/docs/tutorial/dependencies/global-dependencies.md
index 0989b31d46205..33e768bbe2f9d 100644
--- a/docs/zh/docs/tutorial/dependencies/global-dependencies.md
+++ b/docs/zh/docs/tutorial/dependencies/global-dependencies.md
@@ -1,21 +1,21 @@
-# Global Dependencies
+# 全局依赖项
For some types of applications you might want to add dependencies to the whole application.
-Similar to the way you can [add `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, you can add them to the `FastAPI` application.
+通过与定义[*路径装饰器依赖项*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 类似的方式,可以把依赖项添加至整个 `FastAPI` 应用。
-In that case, they will be applied to all the *path operations* in the application:
+这样一来,就可以为所有*路径操作*应用该依赖项:
=== "Python 3.9+"
```Python hl_lines="16"
- {!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
+ 有时,我们要为整个应用添加依赖项。
```
=== "Python 3.6+"
```Python hl_lines="16"
- {!> ../../../docs_src/dependencies/tutorial012_an.py!}
+ 为一组路径操作定义依赖项
```
=== "Python 3.6 non-Annotated"
@@ -24,11 +24,11 @@ In that case, they will be applied to all the *path operations* in the applicati
Prefer to use the `Annotated` version if possible.
```Python hl_lines="15"
- {!> ../../../docs_src/dependencies/tutorial012.py!}
+ {!../../../docs_src/dependencies/tutorial012.py!}
```
-And all the ideas in the section about [adding `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} still apply, but in this case, to all of the *path operations* in the app.
+[*路径装饰器依赖项*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 一章的思路均适用于全局依赖项, 在本例中,这些依赖项可以用于应用中的所有*路径操作*。
## Dependencies for groups of *path operations*
-Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
+稍后,[大型应用 - 多文件](../../tutorial/bigger-applications.md){.internal-link target=_blank}一章中会介绍如何使用多个文件创建大型应用程序,在这一章中,您将了解到如何为一组*路径操作*声明单个 `dependencies` 参数。
From a080f090542842631bdfa212f11e110588eb2f5e Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:38 +0800
Subject: [PATCH 133/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/tutorial/dependencies/index.md | 185 ++++++++++----------
1 file changed, 92 insertions(+), 93 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/index.md b/docs/zh/docs/tutorial/dependencies/index.md
index a8679d1d8175a..18a301d8e46b0 100644
--- a/docs/zh/docs/tutorial/dependencies/index.md
+++ b/docs/zh/docs/tutorial/dependencies/index.md
@@ -1,52 +1,52 @@
-# Dependencies
+# 依赖项
-**FastAPI** has a very powerful but intuitive **Dependency Injection** system.
+FastAPI 提供了简单易用,但功能强大的**依赖注入**系统。
-It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
+这个依赖系统设计的简单易用,可以让开发人员轻松地把组件集成至 **FastAPI**。
-## What is "Dependency Injection"
+## 什么是「依赖注入」
-**"Dependency Injection"** means, in programming, that there is a way for your code (in this case, your *path operation functions*) to declare things that it requires to work and use: "dependencies".
+编程中的**「依赖注入」**是声明代码(本文中为*路径操作函数* )运行所需的,或要使用的「依赖」的一种方式。
-And then, that system (in this case **FastAPI**) will take care of doing whatever is needed to provide your code with those needed dependencies ("inject" the dependencies).
+然后,由系统(本文中为 **FastAPI**)负责执行任意需要的逻辑,为代码提供这些依赖(「注入」依赖项)。
This is very useful when you need to:
-* Have shared logic (the same code logic again and again).
-* Share database connections.
-* Enforce security, authentication, role requirements, etc.
+* 共享业务逻辑(复用相同的代码逻辑)
+* 共享数据库连接
+* 实现安全、验证、角色权限
* And many other things...
All these, while minimizing code repetition.
-## First Steps
+## 第一步
Let's see a very simple example. It will be so simple that it is not very useful, for now.
-But this way we can focus on how the **Dependency Injection** system works.
+但通过这个例子,您可以初步了解「依赖注入」的工作机制。
-### Create a dependency, or "dependable"
+### 创建依赖项
-Let's first focus on the dependency.
+首先,要关注的是依赖项。
-It is just a function that can take all the same parameters that a *path operation function* can take:
+依赖项就是一个函数,且可以使用与*路径操作函数*相同的参数:
=== "Python 3.10+"
```Python hl_lines="8-9"
- {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ 这里只能传给 Depends 一个参数。
```
=== "Python 3.9+"
```Python hl_lines="8-11"
- {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ !!! check "检查"
```
=== "Python 3.6+"
```Python hl_lines="9-12"
- {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ 下一章介绍,除了函数还有哪些「对象」可以用作依赖项。
```
=== "Python 3.10+ non-Annotated"
@@ -55,7 +55,7 @@ It is just a function that can take all the same parameters that a *path operati
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6-7"
- {!> ../../../docs_src/dependencies/tutorial001_py310.py!}
+ {!../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -64,26 +64,26 @@ It is just a function that can take all the same parameters that a *path operati
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8-11"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ {!../../../docs_src/dependencies/tutorial001.py!}
```
That's it.
-**2 lines**.
+只用了**2 行**代码。
-And it has the same shape and structure that all your *path operation functions* have.
+依赖项函数的形式和结构与*路径操作函数*一样。
-You can think of it as a *path operation function* without the "decorator" (without the `@app.get("/some-path")`).
+因此,可以把依赖项当作没有「装饰器」(即,没有 `@app.get("/some-path")` )的路径操作函数。
And it can return anything you want.
-In this case, this dependency expects:
+本例中的依赖项预期接收如下参数:
-* An optional query parameter `q` that is a `str`.
-* An optional query parameter `skip` that is an `int`, and by default is `0`.
-* An optional query parameter `limit` that is an `int`, and by default is `100`.
+* 类型为 `str` 的可选查询参数 `q`
+* 类型为 `int` 的可选查询参数 `skip`,默认值是 `0`
+* 类型为 `int` 的可选查询参数 `limit`,默认值是 `100`
-And then it just returns a `dict` containing those values.
+然后,依赖项函数返回包含这些值的 `dict`。
!!! info
FastAPI added support for `Annotated` (and started recommending it) in version 0.95.0.
@@ -92,24 +92,24 @@ And then it just returns a `dict` containing those values.
Make sure you [Upgrade the FastAPI version](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
-### Import `Depends`
+### 导入 `Depends`
=== "Python 3.10+"
```Python hl_lines="3"
- {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ 如里不了解异步,请参阅[异步:*“着急了?”*](../../async.md){.internal-link target=_blank} 一章中 `async` 和 `await` 的内容。
```
=== "Python 3.9+"
```Python hl_lines="3"
- {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ 大功告成。
```
=== "Python 3.6+"
```Python hl_lines="3"
- {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ 依赖注入常用于以下场景:
```
=== "Python 3.10+ non-Annotated"
@@ -127,29 +127,29 @@ And then it just returns a `dict` containing those values.
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ {!../../../docs_src/dependencies/tutorial001.py!}
```
### Declare the dependency, in the "dependant"
-The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
+与在*路径操作函数*参数中使用 `Body`、`Query` 的方式相同,声明依赖项需要使用 `Depends` 和一个新的参数:
=== "Python 3.10+"
```Python hl_lines="13 18"
- {!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
+ 外部支持库
```
=== "Python 3.9+"
```Python hl_lines="15 20"
- {!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
+ 声明依赖项
```
=== "Python 3.6+"
```Python hl_lines="16 21"
- {!> ../../../docs_src/dependencies/tutorial001_an.py!}
+ !!! tip "提示"
```
=== "Python 3.10+ non-Annotated"
@@ -167,27 +167,27 @@ The same way you use `Body`, `Query`, etc. with your *path operation function* p
Prefer to use the `Annotated` version if possible.
```Python hl_lines="15 20"
- {!> ../../../docs_src/dependencies/tutorial001.py!}
+ !!! note "笔记"
```
-Although you use `Depends` in the parameters of your function the same way you use `Body`, `Query`, etc, `Depends` works a bit differently.
+虽然,在路径操作函数的参数中使用 `Depends` 的方式与 `Body`、`Query` 相同,但 `Depends` 的工作方式略有不同。
You only give `Depends` a single parameter.
-This parameter must be something like a function.
+且该参数必须是可调用对象,比如函数。
-You **don't call it** directly (don't add the parenthesis at the end), you just pass it as a parameter to `Depends()`.
+上述场景均可以使用**依赖注入**,将代码重复最小化。
-And that function takes parameters in the same way that *path operation functions* do.
+该函数接收的参数和*路径操作函数*的参数一样。
!!! tip
You'll see what other "things", apart from functions, can be used as dependencies in the next chapter.
-Whenever a new request arrives, **FastAPI** will take care of:
+接收到新的请求时,**FastAPI** 执行如下操作:
-* Calling your dependency ("dependable") function with the correct parameters.
-* Get the result from your function.
-* Assign that result to the parameter in your *path operation function*.
+* 用正确的参数调用依赖项函数(「可依赖项」)
+* 获取函数返回的结果
+* 把函数返回的结果赋值给*路径操作函数*的参数
```mermaid
graph TB
@@ -200,16 +200,15 @@ common_parameters --> read_items
common_parameters --> read_users
```
-This way you write shared code once and **FastAPI** takes care of calling it for your *path operations*.
+这样,只编写一次代码,**FastAPI** 就可以为多个*路径操作*共享这段代码 。
-!!! check
- Notice that you don't have to create a special class and pass it somewhere to **FastAPI** to "register" it or anything similar.
+!!! 注意,无需创建专门的类,并将之传递给 **FastAPI** 以进行「注册」或执行类似的操作。
- You just pass it to `Depends` and **FastAPI** knows how to do the rest.
+ 只要把它传递给 `Depends`,**FastAPI** 就知道该如何执行后续操作。
## Share `Annotated` dependencies
-In the examples above, you see that there's a tiny bit of **code duplication**.
+接下来,我们学习一个非常简单的例子,尽管它过于简单,不是很实用。
When you need to use the `common_parameters()` dependency, you have to write the whole parameter with the type annotation and `Depends()`:
@@ -222,19 +221,19 @@ But because we are using `Annotated`, we can store that `Annotated` value in a v
=== "Python 3.10+"
```Python hl_lines="12 16 21"
- {!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
+ 开发人员可以使用依赖项及其子依赖项为这些路径操作添加不同的权限:
```
=== "Python 3.9+"
```Python hl_lines="14 18 23"
- {!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
+ 等……
```
=== "Python 3.6+"
```Python hl_lines="15 19 24"
- {!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
+ 依赖项可以返回各种内容。
```
!!! tip
@@ -244,77 +243,77 @@ But because we are using `Annotated`, we can store that `Annotated` value in a v
The dependencies will keep working as expected, and the **best part** is that the **type information will be preserved**, which means that your editor will be able to keep providing you with **autocompletion**, **inline errors**, etc. The same for other tools like `mypy`.
-This will be especially useful when you use it in a **large code base** where you use **the same dependencies** over and over again in ***many ***path operations******.
+上述这些操作都是可行的,**FastAPI** 知道该怎么处理。
-## To `async` or not to `async`
+## 要不要使用 `async`?
-As dependencies will also be called by **FastAPI** (the same as your *path operation functions*), the same rules apply while defining your functions.
+**FastAPI** 调用依赖项的方式与*路径操作函数*一样,因此,定义依赖项函数,也要应用与路径操作函数相同的规则。
-You can use `async def` or normal `def`.
+即,既可以使用异步的 `async def`,也可以使用普通的 `def` 定义依赖项。
-And you can declare dependencies with `async def` inside of normal `def` *path operation functions*, or `def` dependencies inside of `async def` *path operation functions*, etc.
+在普通的 `def` *路径操作函数*中,可以声明异步的 `async def` 依赖项;也可以在异步的 `async def` *路径操作函数*中声明普通的 `def` 依赖项。
-It doesn't matter. **FastAPI** will know what to do.
+It doesn't matter. 然后,**FastAPI** 会用正确的参数调用函数,并提取请求中的数据。
!!! note
If you don't know, check the [Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank} section about `async` and `await` in the docs.
-## Integrated with OpenAPI
+## 与 OpenAPI 集成
-All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
+依赖项及子依赖项的所有请求声明、验证和需求都可以集成至同一个 OpenAPI 概图。
-So, the interactive docs will have all the information from these dependencies too:
+所以,交互文档里也会显示依赖项的所有信息:
-## Simple usage
+## 简单用法
-If you look at it, *path operation functions* are declared to be used whenever a *path* and *operation* matches, and then **FastAPI** takes care of calling the function with the correct parameters, extracting the data from the request.
+开发人员永远都不需要直接调用这些函数,这些函数是由框架(在此为 **FastAPI** )调用的。
-Actually, all (or most) of the web frameworks work in this same way.
+实际上,所有(或大多数)网络框架的工作方式都是这样的。
You never call those functions directly. They are called by your framework (in this case, **FastAPI**).
-With the Dependency Injection system, you can also tell **FastAPI** that your *path operation function* also "depends" on something else that should be executed before your *path operation function*, and **FastAPI** will take care of executing it and "injecting" the results.
+通过依赖注入系统,只要告诉 **FastAPI** *路径操作函数* 还要「依赖」其他在*路径操作函数*之前执行的内容,**FastAPI** 就会执行函数代码,并「注入」函数返回的结果。
-Other common terms for this same idea of "dependency injection" are:
+其他与「依赖注入」概念相同的术语为:
-* resources
-* providers
-* services
-* injectables
-* components
+* 资源(Resource)
+* 提供方(Provider)
+* 服务(Service)
+* 可注入(Injectable)
+* 组件(Component)
-## **FastAPI** plug-ins
+## **FastAPI** 兼容性
-Integrations and "plug-in"s can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your *path operation functions*.
+**依赖注入**系统支持构建集成和「插件」。 但实际上,FastAPI 根本**不需要创建「插件」**,因为使用依赖项可以声明不限数量的、可用于*路径操作函数*的集成与交互。
-And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, *literally*.
+创建依赖项非常简单、直观,并且还支持导入 Python 包。 毫不夸张地说,只要几行代码就可以把需要的 Python 包与 API 函数集成在一起。
-You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
+下一章将详细介绍在关系型数据库、NoSQL 数据库、安全等方面使用依赖项的例子。
-## **FastAPI** compatibility
+## **FastAPI** 插件
-The simplicity of the dependency injection system makes **FastAPI** compatible with:
+依赖注入系统如此简洁的特性,让 **FastAPI** 可以与下列系统兼容:
-* all the relational databases
-* NoSQL databases
+* 关系型数据库
+* NoSQL 数据库
* external packages
-* external APIs
-* authentication and authorization systems
-* API usage monitoring systems
-* response data injection systems
-* etc.
+* 外部 API
+* 认证和鉴权系统
+* API 使用监控系统
+* 响应数据注入系统
+* 等等……
-## Simple and Powerful
+## 简单而强大
-Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
+虽然,**层级式依赖注入系统**的定义与使用十分简单,但它却非常强大。
-You can define dependencies that in turn can define dependencies themselves.
+比如,可以定义依赖其他依赖项的依赖项。
-In the end, a hierarchical tree of dependencies is built, and the **Dependency Injection** system takes care of solving all these dependencies for you (and their sub-dependencies) and providing (injecting) the results at each step.
+最后,依赖项层级树构建后,**依赖注入系统**会处理所有依赖项及其子依赖项,并为每一步操作提供(注入)结果。
-For example, let's say you have 4 API endpoints (*path operations*):
+比如,下面有 4 个 API 路径操作(*端点*):
* `/items/public/`
* `/items/private/`
@@ -346,8 +345,8 @@ admin_user --> activate_user
paying_user --> pro_items
```
-## Integrated with **OpenAPI**
+## 与 **OpenAPI** 集成
-All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your *path operations*.
+在声明需求时,所有这些依赖项还会把参数、验证等功能添加至路径操作。
-**FastAPI** will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.
+**FastAPI** 负责把上述内容全部添加到 OpenAPI 概图,并显示在交互文档中。
From 03fa91065e1151a3e68a9d44ca3e1ed9f52b28fa Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:38 +0800
Subject: [PATCH 134/163] New translations sub-dependencies.md (Chinese
Simplified)
---
.../tutorial/dependencies/sub-dependencies.md | 74 ++++++++++---------
1 file changed, 38 insertions(+), 36 deletions(-)
diff --git a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md
index b89844a1ffd66..fa61d94fa0bb3 100644
--- a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md
+++ b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md
@@ -1,31 +1,31 @@
-# Sub-dependencies
+# 子依赖项
-You can create dependencies that have **sub-dependencies**.
+FastAPI 支持创建含**子依赖项**的依赖项。
-They can be as **deep** as you need them to be.
+并且,可以按需声明任意**深度**的子依赖项嵌套层级。
-**FastAPI** will take care of solving them.
+**FastAPI** 负责处理解析不同深度的子依赖项。
-## First dependency "dependable"
+## 第一层依赖项
You could create a first dependency ("dependable") like:
=== "Python 3.10+"
```Python hl_lines="8-9"
- {!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
+ 这个函数很简单(不过也没什么用),但却有助于让我们专注于了解子依赖项的工作方式。
```
=== "Python 3.9+"
```Python hl_lines="8-9"
- {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ 小结
```
=== "Python 3.6+"
```Python hl_lines="9-10"
- {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ !!! tip "提示"
```
=== "Python 3.10 non-Annotated"
@@ -34,7 +34,7 @@ You could create a first dependency ("dependable") like:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6-7"
- {!> ../../../docs_src/dependencies/tutorial005_py310.py!}
+ {!../../../docs_src/dependencies/tutorial005.py!}
```
=== "Python 3.6 non-Annotated"
@@ -46,13 +46,13 @@ You could create a first dependency ("dependable") like:
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
-It declares an optional query parameter `q` as a `str`, and then it just returns it.
+这段代码声明了类型为 `str` 的可选查询参数 `q`,然后返回这个查询参数。
This is quite simple (not very useful), but will help us focus on how the sub-dependencies work.
## Second dependency, "dependable" and "dependant"
-Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
+接下来,创建另一个依赖项函数,并同时用该依赖项自身再声明一个依赖项(所以这也是一个「依赖项」):
=== "Python 3.10+"
@@ -63,7 +63,7 @@ Then you can create another dependency function (a "dependable") that at the sam
=== "Python 3.9+"
```Python hl_lines="13"
- {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ 下列代码创建了第一层依赖项:
```
=== "Python 3.6+"
@@ -87,19 +87,19 @@ Then you can create another dependency function (a "dependable") that at the sam
Prefer to use the `Annotated` version if possible.
```Python hl_lines="13"
- {!> ../../../docs_src/dependencies/tutorial005.py!}
+ {!../../../docs_src/dependencies/tutorial005.py!}
```
-Let's focus on the parameters declared:
+这里重点说明一下声明的参数:
-* Even though this function is a dependency ("dependable") itself, it also declares another dependency (it "depends" on something else).
- * It depends on the `query_extractor`, and assigns the value returned by it to the parameter `q`.
-* It also declares an optional `last_query` cookie, as a `str`.
- * If the user didn't provide any query `q`, we use the last query used, which we saved to a cookie before.
+* 尽管该函数自身是依赖项,但还声明了另一个依赖项(它「依赖」于其他对象)
+ * 该函数依赖 `query_extractor`, 并把 `query_extractor` 的返回值赋给参数 `q`
+* 同时,该函数还声明了类型是 `str` 的可选 cookie(`last_query`)
+ * 用户未提供查询参数 `q` 时,则使用上次使用后保存在 cookie 中的查询
-## Use the dependency
+## 使用依赖项
-Then we can use the dependency with:
+接下来,就可以使用依赖项:
=== "Python 3.10+"
@@ -110,13 +110,13 @@ Then we can use the dependency with:
=== "Python 3.9+"
```Python hl_lines="23"
- {!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
+ 第二层依赖项
```
=== "Python 3.6+"
```Python hl_lines="24"
- {!> ../../../docs_src/dependencies/tutorial005_an.py!}
+ !!! info "信息"
```
=== "Python 3.10 non-Annotated"
@@ -134,13 +134,12 @@ Then we can use the dependency with:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="22"
- {!> ../../../docs_src/dependencies/tutorial005.py!}
+ {!../../../docs_src/dependencies/tutorial005.py!}
```
-!!! info
- Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`.
+!!! 注意,这里在*路径操作函数*中只声明了一个依赖项,即 `query_or_cookie_extractor` 。
- But **FastAPI** will know that it has to solve `query_extractor` first, to pass the results of that to `query_or_cookie_extractor` while calling it.
+ 但 **FastAPI** 必须先处理 `query_extractor`,以便在调用 `query_or_cookie_extractor` 时使用 `query_extractor` 返回的结果。
```mermaid
graph TB
@@ -153,19 +152,22 @@ read_query["/items/"]
query_extractor --> query_or_cookie_extractor --> read_query
```
-## Using the same dependency multiple times
+## 多次使用同一个依赖项
-If one of your dependencies is declared multiple times for the same *path operation*, for example, multiple dependencies have a common sub-dependency, **FastAPI** will know to call that sub-dependency only once per request.
+如果在同一个*路径操作* 多次声明了同一个依赖项,例如,多个依赖项共用一个子依赖项,**FastAPI** 在处理同一请求时,只调用一次该子依赖项。
-And it will save the returned value in a "cache" and pass it to all the "dependants" that need it in that specific request, instead of calling the dependency multiple times for the same request.
+FastAPI 不会为同一个请求多次调用同一个依赖项,而是把依赖项的返回值进行「缓存」,并把它传递给同一请求中所有需要使用该返回值的「依赖项」。
-In an advanced scenario where you know you need the dependency to be called at every step (possibly multiple times) in the same request instead of using the "cached" value, you can set the parameter `use_cache=False` when using `Depends`:
+在高级使用场景中,如果不想使用「缓存」值,而是为需要在同一请求的每一步操作(多次)中都实际调用依赖项,可以把 `Depends` 的参数 `use_cache` 的值设置为 `False` :
=== "Python 3.6+"
```Python hl_lines="1"
- async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
- return {"fresh_value": fresh_value}
+ 这些简单的例子现在看上去虽然没有什么实用价值,
+
+但在**安全**一章中,您会了解到这些例子的用途,
+
+以及这些例子所能节省的代码量。
```
=== "Python 3.6+ non-Annotated"
@@ -175,16 +177,16 @@ In an advanced scenario where you know you need the dependency to be called at e
```Python hl_lines="1"
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
- return {"fresh_value": fresh_value}
+ return {"fresh_value": fresh_value}
```
## Recap
-Apart from all the fancy words used here, the **Dependency Injection** system is quite simple.
+千万别被本章里这些花里胡哨的词藻吓倒了,其实**依赖注入**系统非常简单。
-Just functions that look the same as the *path operation functions*.
+依赖注入无非是与*路径操作函数*一样的函数罢了。
-But still, it is very powerful, and allows you to declare arbitrarily deeply nested dependency "graphs" (trees).
+但它依然非常强大,能够声明任意嵌套深度的「图」或树状的依赖结构。
!!! tip
All this might not seem as useful with these simple examples.
From 341db049a8242692222de3264de94ca1c054d668 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:40 +0800
Subject: [PATCH 135/163] New translations encoder.md (Chinese Simplified)
---
docs/zh/docs/tutorial/encoder.md | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/docs/zh/docs/tutorial/encoder.md b/docs/zh/docs/tutorial/encoder.md
index 735aa2209ffed..3c0b9152fc1dd 100644
--- a/docs/zh/docs/tutorial/encoder.md
+++ b/docs/zh/docs/tutorial/encoder.md
@@ -1,24 +1,24 @@
-# JSON Compatible Encoder
+# JSON 兼容编码器
-There are some cases where you might need to convert a data type (like a Pydantic model) to something compatible with JSON (like a `dict`, `list`, etc).
+在某些情况下,您可能需要将数据类型(如Pydantic模型)转换为与JSON兼容的数据类型(如`dict`、`list`等)。
-For example, if you need to store it in a database.
+比如,如果您需要将其存储在数据库中。
-For that, **FastAPI** provides a `jsonable_encoder()` function.
+对于这种要求, **FastAPI**提供了`jsonable_encoder()`函数。
-## Using the `jsonable_encoder`
+## 使用`jsonable_encoder`
-Let's imagine that you have a database `fake_db` that only receives JSON compatible data.
+让我们假设你有一个数据库名为`fake_db`,它只能接收与JSON兼容的数据。
-For example, it doesn't receive `datetime` objects, as those are not compatible with JSON.
+例如,它不接收`datetime`这类的对象,因为这些对象与JSON不兼容。
-So, a `datetime` object would have to be converted to a `str` containing the data in ISO format.
+因此,`datetime`对象必须将转换为包含ISO格式化的`str`类型对象。
-The same way, this database wouldn't receive a Pydantic model (an object with attributes), only a `dict`.
+同样,这个数据库也不会接收Pydantic模型(带有属性的对象),而只接收`dict`。
-You can use `jsonable_encoder` for that.
+对此你可以使用`jsonable_encoder`。
-It receives an object, like a Pydantic model, and returns a JSON compatible version:
+它接收一个对象,比如Pydantic模型,并会返回一个JSON兼容的版本:
=== "Python 3.10+"
@@ -32,11 +32,11 @@ It receives an object, like a Pydantic model, and returns a JSON compatible vers
{!> ../../../docs_src/encoder/tutorial001.py!}
```
-In this example, it would convert the Pydantic model to a `dict`, and the `datetime` to a `str`.
+在这个例子中,它将Pydantic模型转换为`dict`,并将`datetime`转换为`str`。
-The result of calling it is something that can be encoded with the Python standard `json.dumps()`.
+调用它的结果后就可以使用Python标准编码中的`json.dumps()`。
-It doesn't return a large `str` containing the data in JSON format (as a string). It returns a Python standard data structure (e.g. a `dict`) with values and sub-values that are all compatible with JSON.
+这个操作不会返回一个包含JSON格式(作为字符串)数据的庞大的`str`。 它将返回一个Python标准数据结构(例如`dict`),其值和子值都与JSON兼容。
-!!! note
- `jsonable_encoder` is actually used by **FastAPI** internally to convert data. But it is useful in many other scenarios.
+!!! !!! note
+ `jsonable_encoder`实际上是FastAPI内部用来转换数据的。 但是它在许多其他场景中也很有用。
From a945c014f40d84283f417ddeeba5514c7993bacb Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:41 +0800
Subject: [PATCH 136/163] New translations extra-data-types.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/extra-data-types.md | 72 +++++++++++------------
1 file changed, 36 insertions(+), 36 deletions(-)
diff --git a/docs/zh/docs/tutorial/extra-data-types.md b/docs/zh/docs/tutorial/extra-data-types.md
index 7d6ffbc780cb0..60fc4c3bc68df 100644
--- a/docs/zh/docs/tutorial/extra-data-types.md
+++ b/docs/zh/docs/tutorial/extra-data-types.md
@@ -1,59 +1,59 @@
-# Extra Data Types
+# 额外数据类型
-Up to now, you have been using common data types, like:
+到目前为止,您一直在使用常见的数据类型,如:
* `int`
* `float`
* `str`
* `bool`
-But you can also use more complex data types.
+但是您也可以使用更复杂的数据类型。
-And you will still have the same features as seen up to now:
+您仍然会拥有现在已经看到的相同的特性:
-* Great editor support.
-* Data conversion from incoming requests.
-* Data conversion for response data.
-* Data validation.
-* Automatic annotation and documentation.
+* 很棒的编辑器支持。
+* 传入请求的数据转换。
+* 响应数据转换。
+* 数据验证。
+* 自动补全和文档。
-## Other data types
+## 其他数据类型
-Here are some of the additional data types you can use:
+下面是一些你可以使用的其他数据类型:
* `UUID`:
- * A standard "Universally Unique Identifier", common as an ID in many databases and systems.
- * In requests and responses will be represented as a `str`.
+ * 一种标准的 "通用唯一标识符" ,在许多数据库和系统中用作ID。
+ * 在请求和响应中将以 `str` 表示。
* `datetime.datetime`:
- * A Python `datetime.datetime`.
- * In requests and responses will be represented as a `str` in ISO 8601 format, like: `2008-09-15T15:53:00+05:00`.
+ * 一个 Python `datetime.datetime`.
+ * 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `2008-09-15T15:53:00+05:00`.
* `datetime.date`:
* Python `datetime.date`.
- * In requests and responses will be represented as a `str` in ISO 8601 format, like: `2008-09-15`.
+ * 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `2008-09-15`.
* `datetime.time`:
- * A Python `datetime.time`.
- * In requests and responses will be represented as a `str` in ISO 8601 format, like: `14:23:55.003`.
+ * 一个 Python `datetime.time`.
+ * 在请求和响应中将表示为 ISO 8601 格式的 `str` ,比如: `14:23:55.003`.
* `datetime.timedelta`:
- * A Python `datetime.timedelta`.
- * In requests and responses will be represented as a `float` of total seconds.
- * Pydantic also allows representing it as a "ISO 8601 time diff encoding", see the docs for more info.
+ * 一个 Python `datetime.timedelta`.
+ * 在请求和响应中将表示为 `float` 代表总秒数。
+ * Pydantic 也允许将其表示为 "ISO 8601 时间差异编码", 查看文档了解更多信息。
* `frozenset`:
- * In requests and responses, treated the same as a `set`:
- * In requests, a list will be read, eliminating duplicates and converting it to a `set`.
- * In responses, the `set` will be converted to a `list`.
- * The generated schema will specify that the `set` values are unique (using JSON Schema's `uniqueItems`).
+ * 在请求和响应中,作为 `set` 对待:
+ * 在请求中,列表将被读取,消除重复,并将其转换为一个 `set`。
+ * 在响应中 `set` 将被转换为 `list` 。
+ * 产生的模式将指定那些 `set` 的值是唯一的 (使用 JSON 模式的 `uniqueItems`)。
* `bytes`:
- * Standard Python `bytes`.
- * In requests and responses will be treated as `str`.
- * The generated schema will specify that it's a `str` with `binary` "format".
+ * 标准的 Python `bytes`。
+ * 在请求和相应中被当作 `str` 处理。
+ * 生成的模式将指定这个 `str` 是 `binary` "格式"。
* `Decimal`:
- * Standard Python `Decimal`.
- * In requests and responses, handled the same as a `float`.
-* You can check all the valid pydantic data types here: Pydantic data types.
+ * 标准的 Python `Decimal`。
+ * 在请求和相应中被当做 `float` 一样处理。
+* 您可以在这里检查所有有效的pydantic数据类型: Pydantic data types.
-## Example
+## 例子
-Here's an example *path operation* with parameters using some of the above types.
+下面是一个*路径操作*的示例,其中的参数使用了上面的一些类型。
=== "Python 3.10+"
@@ -79,7 +79,7 @@ Here's an example *path operation* with parameters using some of the above types
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 2 11-15"
- {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ {!../../../docs_src/extra_data_types/tutorial001.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -88,10 +88,10 @@ Here's an example *path operation* with parameters using some of the above types
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 2 12-16"
- {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ {!../../../docs_src/extra_data_types/tutorial001.py!}
```
-Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
+注意,函数内的参数有原生的数据类型,你可以,例如,执行正常的日期操作,如:
=== "Python 3.10+"
From ec22cf1d35a2ddb6489a41ece35942d9c17f96a8 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:42 +0800
Subject: [PATCH 137/163] New translations extra-models.md (Chinese Simplified)
---
docs/zh/docs/tutorial/extra-models.md | 127 +++++++++++++-------------
1 file changed, 64 insertions(+), 63 deletions(-)
diff --git a/docs/zh/docs/tutorial/extra-models.md b/docs/zh/docs/tutorial/extra-models.md
index e91e879e41672..1a1f3c3354ca8 100644
--- a/docs/zh/docs/tutorial/extra-models.md
+++ b/docs/zh/docs/tutorial/extra-models.md
@@ -1,21 +1,21 @@
-# Extra Models
+# 额外的模型
-Continuing with the previous example, it will be common to have more than one related model.
+我们从前面的示例继续,拥有多个相关的模型是很常见的。
-This is especially the case for user models, because:
+对用户模型来说尤其如此,因为:
-* The **input model** needs to be able to have a password.
-* The **output model** should not have a password.
-* The **database model** would probably need to have a hashed password.
+* **输入模型**需要拥有密码属性。
+* **输出模型**不应该包含密码。
+* **数据库模型**很可能需要保存密码的哈希值。
-!!! danger
- Never store user's plaintext passwords. Always store a "secure hash" that you can then verify.
+!!! !!! danger
+ 永远不要存储用户的明文密码。 始终存储一个可以用于验证的「安全哈希值」。
- If you don't know, you will learn what a "password hash" is in the [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.
+ 如果你尚未了解该知识,你可以在[安全章节](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}中学习何为「密码哈希值」。
-## Multiple models
+## 多个模型
-Here's a general idea of how the models could look like with their password fields and the places where they are used:
+下面是应该如何根据它们的密码字段以及使用位置去定义模型的大概思路:
=== "Python 3.10+"
@@ -26,38 +26,38 @@ Here's a general idea of how the models could look like with their password fiel
=== "Python 3.6+"
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
- {!> ../../../docs_src/extra_models/tutorial001.py!}
+ {!../../../docs_src/extra_models/tutorial001.py!}
```
-### About `**user_in.dict()`
+### 关于 `**user_in.dict()`
-#### Pydantic's `.dict()`
+#### Pydantic 的 `.dict()`
-`user_in` is a Pydantic model of class `UserIn`.
+`user_in` 是一个 `UserIn` 类的 Pydantic 模型.
-Pydantic models have a `.dict()` method that returns a `dict` with the model's data.
+Pydantic 模型具有 `.dict()` 方法,该方法返回一个拥有模型数据的 `dict`。
-So, if we create a Pydantic object `user_in` like:
+因此,如果我们像下面这样创建一个 Pydantic 对象 `user_in`:
```Python
user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
```
-and then we call:
+然后我们调用:
```Python
user_dict = user_in.dict()
```
-we now have a `dict` with the data in the variable `user_dict` (it's a `dict` instead of a Pydantic model object).
+现在我们有了一个数据位于变量 `user_dict` 中的 `dict`(它是一个 `dict` 而不是 Pydantic 模型对象)。
-And if we call:
+如果我们调用:
```Python
print(user_dict)
```
-we would get a Python `dict` with:
+我们将获得一个这样的 Python `dict`:
```Python
{
@@ -68,17 +68,17 @@ we would get a Python `dict` with:
}
```
-#### Unwrapping a `dict`
+#### 解包 `dict`
-If we take a `dict` like `user_dict` and pass it to a function (or class) with `**user_dict`, Python will "unwrap" it. It will pass the keys and values of the `user_dict` directly as key-value arguments.
+如果我们将 `user_dict` 这样的 `dict` 以 `**user_dict` 形式传递给一个函数(或类),Python将对其进行「解包」。 它会将 `user_dict` 的键和值作为关键字参数直接传递。
-So, continuing with the `user_dict` from above, writing:
+因此,从上面的 `user_dict` 继续,编写:
```Python
UserInDB(**user_dict)
```
-Would result in something equivalent to:
+会产生类似于以下的结果:
```Python
UserInDB(
@@ -89,7 +89,7 @@ UserInDB(
)
```
-Or more exactly, using `user_dict` directly, with whatever contents it might have in the future:
+或者更确切地,直接使用 `user_dict` 来表示将来可能包含的任何内容:
```Python
UserInDB(
@@ -100,34 +100,34 @@ UserInDB(
)
```
-#### A Pydantic model from the contents of another
+#### 来自于其他模型内容的 Pydantic 模型
-As in the example above we got `user_dict` from `user_in.dict()`, this code:
+...因为 `user_in.dict()` 是一个 `dict`,然后我们通过以`**`开头传递给 `UserInDB` 来使 Python「解包」它。
```Python
user_dict = user_in.dict()
UserInDB(**user_dict)
```
-would be equivalent to:
+等同于:
```Python
UserInDB(**user_in.dict())
```
-...because `user_in.dict()` is a `dict`, and then we make Python "unwrap" it by passing it to `UserInDB` prepended with `**`.
+如上例所示,我们从 `user_in.dict()` 中获得了 `user_dict`,此代码:
-So, we get a Pydantic model from the data in another Pydantic model.
+这样,我们获得了一个来自于其他 Pydantic 模型中的数据的 Pydantic 模型。
-#### Unwrapping a `dict` and extra keywords
+#### 解包 `dict` 和额外关键字
-And then adding the extra keyword argument `hashed_password=hashed_password`, like in:
+然后添加额外的关键字参数 `hashed_password=hashed_password`,例如:
```Python
UserInDB(**user_in.dict(), hashed_password=hashed_password)
```
-...ends up being like:
+...最终的结果如下:
```Python
UserInDB(
@@ -142,21 +142,21 @@ UserInDB(
!!! warning
The supporting additional functions are just to demo a possible flow of the data, but they of course are not providing any real security.
-## Reduce duplication
+## 减少重复
-Reducing code duplication is one of the core ideas in **FastAPI**.
+减少代码重复是 **FastAPI** 的核心思想之一。
-As code duplication increments the chances of bugs, security issues, code desynchronization issues (when you update in one place but not in the others), etc.
+因为代码重复会增加出现 bug、安全性问题、代码失步问题(当你在一个位置更新了代码但没有在其他位置更新)等的可能性。
-And these models are all sharing a lot of the data and duplicating attribute names and types.
+上面的这些模型都共享了大量数据,并拥有重复的属性名称和类型。
-We could do better.
+我们可以做得更好。
-We can declare a `UserBase` model that serves as a base for our other models. And then we can make subclasses of that model that inherit its attributes (type declarations, validation, etc).
+我们可以声明一个 `UserBase` 模型作为其他模型的基类。 然后我们可以创建继承该模型属性(类型声明,校验等)的子类。
-All the data conversion, validation, documentation, etc. will still work as normally.
+所有的数据转换、校验、文档生成等仍将正常运行。
-That way, we can declare just the differences between the models (with plaintext `password`, with `hashed_password` and without password):
+这样,我们可以仅声明模型之间的差异部分(具有明文的 `password`、具有 `hashed_password` 以及不包括密码)。
=== "Python 3.10+"
@@ -167,19 +167,19 @@ That way, we can declare just the differences between the models (with plaintext
=== "Python 3.6+"
```Python hl_lines="9 15-16 19-20 23-24"
- {!> ../../../docs_src/extra_models/tutorial002.py!}
+ {!../../../docs_src/extra_models/tutorial002.py!}
```
-## `Union` or `anyOf`
+## `Union` 或者 `anyOf`
-You can declare a response to be the `Union` of two types, that means, that the response would be any of the two.
+你可以将一个响应声明为两种类型的 `Union`,这意味着该响应将是两种类型中的任何一种。
-It will be defined in OpenAPI with `anyOf`.
+这将在 OpenAPI 中使用 `anyOf` 进行定义。
-To do that, use the standard Python type hint `typing.Union`:
+为此,请使用标准的 Python 类型提示 `typing.Union`:
-!!! note
- When defining a `Union`, include the most specific type first, followed by the less specific type. In the example below, the more specific `PlaneItem` comes before `CarItem` in `Union[PlaneItem, CarItem]`.
+!!! !!! note
+ 定义一个 `Union` 类型时,首先包括最详细的类型,然后是不太详细的类型。 在下面的示例中,更详细的 `PlaneItem` 位于 `Union[PlaneItem,CarItem]` 中的 `CarItem` 之前。
=== "Python 3.10+"
@@ -190,7 +190,7 @@ To do that, use the standard Python type hint ../../../docs_src/extra_models/tutorial003.py!}
+ {!../../../docs_src/extra_models/tutorial003.py!}
```
### `Union` in Python 3.10
@@ -207,46 +207,47 @@ some_variable: PlaneItem | CarItem
But if we put that in `response_model=PlaneItem | CarItem` we would get an error, because Python would try to perform an **invalid operation** between `PlaneItem` and `CarItem` instead of interpreting that as a type annotation.
-## List of models
+## 模型列表
-The same way, you can declare responses of lists of objects.
+你可以用同样的方式声明由对象列表构成的响应。
-For that, use the standard Python `typing.List` (or just `list` in Python 3.9 and above):
+为此,请使用标准的 Python `typing.List`:
=== "Python 3.9+"
```Python hl_lines="18"
- {!> ../../../docs_src/extra_models/tutorial004_py39.py!}
+ !!! warning
+ 辅助性的额外函数只是为了演示可能的数据流,但它们显然不能提供任何真正的安全性。
```
=== "Python 3.6+"
```Python hl_lines="1 20"
- {!> ../../../docs_src/extra_models/tutorial004.py!}
+ {!../../../docs_src/extra_models/tutorial004.py!}
```
-## Response with arbitrary `dict`
+## 任意 `dict` 构成的响应
-You can also declare a response using a plain arbitrary `dict`, declaring just the type of the keys and values, without using a Pydantic model.
+你还可以使用一个任意的普通 `dict` 声明响应,仅声明键和值的类型,而不使用 Pydantic 模型。
-This is useful if you don't know the valid field/attribute names (that would be needed for a Pydantic model) beforehand.
+如果你事先不知道有效的字段/属性名称(对于 Pydantic 模型是必需的),这将很有用。
-In this case, you can use `typing.Dict` (or just `dict` in Python 3.9 and above):
+在这种情况下,你可以使用 `typing.Dict`:
=== "Python 3.9+"
```Python hl_lines="6"
- {!> ../../../docs_src/extra_models/tutorial005_py39.py!}
+ 总结
```
=== "Python 3.6+"
```Python hl_lines="1 8"
- {!> ../../../docs_src/extra_models/tutorial005.py!}
+ {!../../../docs_src/extra_models/tutorial005.py!}
```
## Recap
-Use multiple Pydantic models and inherit freely for each case.
+使用多个 Pydantic 模型,并针对不同场景自由地继承。
-You don't need to have a single data model per entity if that entity must be able to have different "states". As the case with the user "entity" with a state including `password`, `password_hash` and no password.
+如果一个实体必须能够具有不同的「状态」,你无需为每个状态的实体定义单独的数据模型。 以用户「实体」为例,其状态有包含 `password`、包含 `password_hash` 以及不含密码。
From 48337df42af95b521b5eb996d73642ce6a896e5a Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:43 +0800
Subject: [PATCH 138/163] New translations first-steps.md (Chinese Simplified)
---
docs/zh/docs/tutorial/first-steps.md | 210 ++++++++++++++-------------
1 file changed, 106 insertions(+), 104 deletions(-)
diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md
index 1368b89c76081..597e8e6f89acf 100644
--- a/docs/zh/docs/tutorial/first-steps.md
+++ b/docs/zh/docs/tutorial/first-steps.md
@@ -1,14 +1,14 @@
-# First Steps
+# 第一步
-The simplest FastAPI file could look like this:
+最简单的 FastAPI 文件可能像下面这样:
```Python
{!../../../docs_src/first_steps/tutorial001.py!}
```
-Copy that to a file `main.py`.
+将其复制到 `main.py` 文件中。
-Run the live server:
+运行实时服务器:
get operation
+* 请求路径为 `/`
+* 使用 get 操作
-!!! info "`@decorator` Info" That `@something` syntax in Python is called a "decorator".
+!!! !!! info "`@decorator` Info" `@something` 语法在 Python 中被称为「装饰器」。
- You put it on top of a function. Like a pretty decorative hat (I guess that's where the term came from).
+ You put it on top of a function. 像一顶漂亮的装饰帽一样,将它放在一个函数的上方(我猜测这个术语的命名就是这么来的)。
- A "decorator" takes the function below and does something with it.
+ 装饰器接收位于其下方的函数并且用它完成一些工作。
- In our case, this decorator tells **FastAPI** that the function below corresponds to the **path** `/` with an **operation** `get`.
+ 在我们的例子中,这个装饰器告诉 **FastAPI** 位于其下方的函数对应着**路径** `/` 加上 `get` **操作**。
- It is the "**path operation decorator**".
+ 它是一个「**路径操作装饰器**」。
-You can also use the other operations:
+你也可以使用其他的操作:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
-And the more exotic ones:
+以及更少见的:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
-!!! tip
- You are free to use each operation (HTTP method) as you wish.
+!!! !!! tip
+ 您可以随意使用任何一个操作(HTTP方法)。
- **FastAPI** doesn't enforce any specific meaning.
+ **FastAPI** 没有强制要求操作有任何特定的含义。
- The information here is presented as a guideline, not a requirement.
+ 此处提供的信息仅作为指导,而不是要求。
- For example, when using GraphQL you normally perform all the actions using only `POST` operations.
+ 比如,当使用 GraphQL 时通常你所有的动作都通过 `post` 一种方法执行。
-### Step 4: define the **path operation function**
+### 步骤 4:定义**路径操作函数**
-This is our "**path operation function**":
+这是我们的「**路径操作函数**」:
-* **path**: is `/`.
-* **operation**: is `get`.
-* **function**: is the function below the "decorator" (below `@app.get("/")`).
+* **路径**:是 `/`。
+* **操作**:是 `get`。
+* **函数**:是位于「装饰器」下方的函数(位于 `@app.get("/")` 下方)。
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial001.py!}
```
-This is a Python function.
+这是一个 Python 函数。
-It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using a `GET` operation.
+每当 **FastAPI** 接收一个使用 `GET` 方法访问 URL「`/`」的请求时这个函数会被调用。
-In this case, it is an `async` function.
+在这个例子中,它是一个 `async` 函数。
---
-You could also define it as a normal function instead of `async def`:
+你也可以将其定义为常规函数而不使用 `async def`:
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial003.py!}
```
-!!! note
- If you don't know the difference, check the [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
+!!! !!! note
+ 如果你不知道两者的区别,请查阅 [Async: *"In a hurry?"*](https://fastapi.tiangolo.com/async/#in-a-hurry){.internal-link target=_blank}。
-### Step 5: return the content
+### 步骤 5:返回内容
```Python hl_lines="8"
{!../../../docs_src/first_steps/tutorial001.py!}
```
-You can return a `dict`, `list`, singular values as `str`, `int`, etc.
+你可以返回一个 `dict`、`list`,像 `str`、`int` 一样的单个值,等等。
-You can also return Pydantic models (you'll see more about that later).
+你还可以返回 Pydantic 模型(稍后你将了解更多)。
-There are many other objects and models that will be automatically converted to JSON (including ORMs, etc). Try using your favorite ones, it's highly probable that they are already supported.
+还有许多其他将会自动转换为 JSON 的对象和模型(包括 ORM 对象等)。 尝试下使用你最喜欢的一种,它很有可能已经被支持。
## Recap
-* Import `FastAPI`.
-* Create an `app` instance.
-* Write a **path operation decorator** (like `@app.get("/")`).
-* Write a **path operation function** (like `def root(): ...` above).
-* Run the development server (like `uvicorn main:app --reload`).
+* 导入 `FastAPI`。
+* 创建一个 `app` 实例。
+* 编写一个**路径操作装饰器**(如 `@app.get("/")`)。
+* 编写一个**路径操作函数**(如上面的 `def root(): ...`)。
+* 运行开发服务器(如 `uvicorn main:app --reload`)。
From 1c5356f4f1c2535e5d33d39f14824bc06d7442ab Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:43 +0800
Subject: [PATCH 139/163] New translations handling-errors.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/handling-errors.md | 139 +++++++++++------------
1 file changed, 68 insertions(+), 71 deletions(-)
diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md
index b150201e797d3..46a31245ea790 100644
--- a/docs/zh/docs/tutorial/handling-errors.md
+++ b/docs/zh/docs/tutorial/handling-errors.md
@@ -1,53 +1,53 @@
-# Handling Errors
+# 处理错误
-There are many situations in where you need to notify an error to a client that is using your API.
+某些情况下,需要向客户端返回错误提示。
-This client could be a browser with a frontend, a code from someone else, an IoT device, etc.
+这里所谓的客户端包括前端浏览器、其他应用程序、物联网设备等。
You could need to tell the client that:
-* The client doesn't have enough privileges for that operation.
-* The client doesn't have access to that resource.
-* The item the client was trying to access doesn't exist.
+* 客户端没有执行操作的权限
+* 客户端没有访问资源的权限
+* 客户端要访问的项目不存在
* etc.
-In these cases, you would normally return an **HTTP status code** in the range of **400** (from 400 to 499).
+遇到这些情况时,通常要返回 **4XX**(400 至 499)**HTTP 状态码**。
This is similar to the 200 HTTP status codes (from 200 to 299). Those "200" status codes mean that somehow there was a "success" in the request.
The status codes in the 400 range mean that there was an error from the client.
-Remember all those **"404 Not Found"** errors (and jokes)?
+大家都知道**「404 Not Found」**错误,还有调侃这个错误的笑话吧?
-## Use `HTTPException`
+## 使用 `HTTPException`
-To return HTTP responses with errors to the client you use `HTTPException`.
+向客户端返回 HTTP 错误响应,可以使用 `HTTPException`。
-### Import `HTTPException`
+### 导入 `HTTPException`
```Python hl_lines="1"
{!../../../docs_src/handling_errors/tutorial001.py!}
```
-### Raise an `HTTPException` in your code
+### 触发 `HTTPException`
-`HTTPException` is a normal Python exception with additional data relevant for APIs.
+`HTTPException` 是额外包含了和 API 有关数据的常规 Python 异常。
-Because it's a Python exception, you don't `return` it, you `raise` it.
+因为是 Python 异常,所以不能 `return`,只能 `raise`。
-This also means that if you are inside a utility function that you are calling inside of your *path operation function*, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the *path operation function*, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client.
+如在调用*路径操作函数*里的工具函数时,触发了 `HTTPException`,FastAPI 就不再继续执行*路径操作函数*中的后续代码,而是立即终止请求,并把 `HTTPException` 的 HTTP 错误发送至客户端。
-The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security.
+在介绍依赖项与安全的章节中,您可以了解更多用 `raise` 异常代替 `return` 值的优势。
-In this example, when the client requests an item by an ID that doesn't exist, raise an exception with a status code of `404`:
+本例中,客户端用 `ID` 请求的 `item` 不存在时,触发状态码为 `404` 的异常:
```Python hl_lines="11"
{!../../../docs_src/handling_errors/tutorial001.py!}
```
-### The resulting response
+### 响应结果
-If the client requests `http://example.com/items/foo` (an `item_id` `"foo"`), that client will receive an HTTP status code of 200, and a JSON response of:
+请求为 `http://example.com/items/foo`(`item_id` 为 `「foo」`)时,客户端会接收到 HTTP 状态码 - 200 及如下 JSON 响应结果:
```JSON
{
@@ -55,7 +55,7 @@ If the client requests `http://example.com/items/foo` (an `item_id` `"foo"`), th
}
```
-But if the client requests `http://example.com/items/bar` (a non-existent `item_id` `"bar"`), that client will receive an HTTP status code of 404 (the "not found" error), and a JSON response of:
+但如果客户端请求 `http://example.com/items/bar`(`item_id` `「bar」` 不存在时),则会接收到 HTTP 状态码 - 404(「未找到」错误)及如下 JSON 响应结果:
```JSON
{
@@ -63,77 +63,74 @@ But if the client requests `http://example.com/items/bar` (a non-existent `item_
}
```
-!!! tip
- When raising an `HTTPException`, you can pass any value that can be converted to JSON as the parameter `detail`, not only `str`.
+!!! 触发 `HTTPException` 时,可以用参数 `detail` 传递任何能转换为 JSON 的值,不仅限于 `str`。
- You could pass a `dict`, a `list`, etc.
-
- They are handled automatically by **FastAPI** and converted to JSON.
+ 还支持传递 `dict`、`list` 等数据结构。 **FastAPI** 能自动处理这些数据,并将之转换为 JSON。
-## Add custom headers
+## 添加自定义响应头
-There are some situations in where it's useful to be able to add custom headers to the HTTP error. For example, for some types of security.
+有些场景下要为 HTTP 错误添加自定义响应头。 例如,出于某些方面的安全需要。
-You probably won't need to use it directly in your code.
+一般情况下可能不会需要在代码中直接使用响应头。
-But in case you needed it for an advanced scenario, you can add custom headers:
+但对于某些高级应用场景,还是需要添加自定义响应头:
```Python hl_lines="14"
{!../../../docs_src/handling_errors/tutorial002.py!}
```
-## Install custom exception handlers
+## 安装自定义异常处理器
-You can add custom exception handlers with the same exception utilities from Starlette.
+添加自定义处理器,要使用 [Starlette 的异常工具](https://www.starlette.io/exceptions/)。
-Let's say you have a custom exception `UnicornException` that you (or a library you use) might `raise`.
+假设要触发的自定义异常叫作 `UnicornException`。
-And you want to handle this exception globally with FastAPI.
+且需要 FastAPI 实现全局处理该异常。
-You could add a custom exception handler with `@app.exception_handler()`:
+此时,可以用 `@app.exception_handler()` 添加自定义异常控制器:
```Python hl_lines="5-7 13-18 24"
{!../../../docs_src/handling_errors/tutorial003.py!}
```
-Here, if you request `/unicorns/yolo`, the *path operation* will `raise` a `UnicornException`.
+请求 `/unicorns/yolo` 时,路径操作会触发 `UnicornException`。
-But it will be handled by the `unicorn_exception_handler`.
+但该异常将会被 `unicorn_exception_handler` 处理。
-So, you will receive a clean error, with an HTTP status code of `418` and a JSON content of:
+接收到的错误信息清晰明了,HTTP 状态码为 `418`,JSON 内容如下:
```JSON
-{"message": "Oops! yolo did something. There goes a rainbow..."}
+{"message": "Oops! yolo did something. {"message": "Oops! yolo did something. There goes a rainbow..."}
```
!!! note "Technical Details"
You could also use `from starlette.requests import Request` and `from starlette.responses import JSONResponse`.
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `Request`.
+ `from starlette.requests import Request` 和 `from starlette.responses import JSONResponse` 也可以用于导入 `Request` 和 `JSONResponse`。 **FastAPI** 提供了与 `starlette.responses` 相同的 `fastapi.responses` 作为快捷方式,但大部分响应操作都可以直接从 Starlette 导入。 同理,`Request` 也是如此。
## Override the default exception handlers
-**FastAPI** has some default exception handlers.
+**FastAPI** 自带了一些默认异常处理器。
-These handlers are in charge of returning the default JSON responses when you `raise` an `HTTPException` and when the request has invalid data.
+触发 `HTTPException` 或请求无效数据时,这些处理器返回默认的 JSON 响应结果。
You can override these exception handlers with your own.
-### Override request validation exceptions
+### 覆盖请求验证异常
-When a request contains invalid data, **FastAPI** internally raises a `RequestValidationError`.
+请求中包含无效数据时,**FastAPI** 内部会触发 `RequestValidationError`。
And it also includes a default exception handler for it.
-To override it, import the `RequestValidationError` and use it with `@app.exception_handler(RequestValidationError)` to decorate the exception handler.
+覆盖默认异常处理器时需要导入 `RequestValidationError`,并用 `@app.excption_handler(RequestValidationError)` 装饰异常处理器。
-The exception handler will receive a `Request` and the exception.
+这样,异常处理器就可以接收 `Request` 与异常。
```Python hl_lines="2 14-16"
{!../../../docs_src/handling_errors/tutorial004.py!}
```
-Now, if you go to `/items/foo`, instead of getting the default JSON error with:
+访问 `/items/foo`,可以看到以下内容替换了默认 JSON 错误信息:
```JSON
{
@@ -163,21 +160,21 @@ path -> item_id
!!! warning
These are technical details that you might skip if it's not important for you now.
-`RequestValidationError` is a sub-class of Pydantic's `ValidationError`.
+`RequestValidationError` 是 Pydantic 的 `ValidationError` 的子类。
-**FastAPI** uses it so that, if you use a Pydantic model in `response_model`, and your data has an error, you will see the error in your log.
+**FastAPI** 调用的就是 `RequestValidationError` 类,因此,如果在 `response_model` 中使用 Pydantic 模型,且数据有错误时,在日志中就会看到这个错误。
-But the client/user will not see it. Instead, the client will receive an "Internal Server Error" with a HTTP status code `500`.
+但客户端或用户看不到这个错误。 反之,客户端接收到的是 HTTP 状态码为 `500` 的「内部服务器错误」。
-It should be this way because if you have a Pydantic `ValidationError` in your *response* or anywhere in your code (not in the client's *request*), it's actually a bug in your code.
+这是因为在*响应*或代码(不是在客户端的请求里)中出现的 Pydantic `ValidationError` 是代码的 bug。
-And while you fix it, your clients/users shouldn't have access to internal information about the error, as that could expose a security vulnerability.
+修复错误时,客户端或用户不能访问错误的内部信息,否则会造成安全隐患。
-### Override the `HTTPException` error handler
+### 覆盖 `HTTPException` 错误处理器
-The same way, you can override the `HTTPException` handler.
+同理,也可以覆盖 `HTTPException` 处理器。
-For example, you could want to return a plain text response instead of JSON for these errors:
+例如,只为错误返回纯文本响应,而不是返回 JSON 格式的内容:
```Python hl_lines="3-4 9-11 22"
{!../../../docs_src/handling_errors/tutorial004.py!}
@@ -186,19 +183,19 @@ For example, you could want to return a plain text response instead of JSON for
!!! note "Technical Details"
You could also use `from starlette.responses import PlainTextResponse`.
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+ 还可以使用 `from starlette.responses import PlainTextResponse`。 **FastAPI** 提供了与 `starlette.responses` 相同的 `fastapi.responses` 作为快捷方式,但大部分响应都可以直接从 Starlette 导入。
-### Use the `RequestValidationError` body
+### 使用 `RequestValidationError` 的请求体
-The `RequestValidationError` contains the `body` it received with invalid data.
+`RequestValidationError` 包含其接收到的无效数据请求的 `body` 。
-You could use it while developing your app to log the body and debug it, return it to the user, etc.
+开发时,可以用这个请求体生成日志、调试错误,并返回给用户。
```Python hl_lines="14"
{!../../../docs_src/handling_errors/tutorial005.py!}
```
-Now try sending an invalid item like:
+现在试着发送一个无效的 `item`,例如:
```JSON
{
@@ -207,7 +204,7 @@ Now try sending an invalid item like:
}
```
-You will receive a response telling you that the data is invalid containing the received body:
+收到的响应包含 `body` 信息,并说明数据是无效的:
```JSON hl_lines="12-15"
{
@@ -228,31 +225,31 @@ You will receive a response telling you that the data is invalid containing the
}
```
-#### FastAPI's `HTTPException` vs Starlette's `HTTPException`
+#### FastAPI `HTTPException` vs Starlette `HTTPException`
-**FastAPI** has its own `HTTPException`.
+**FastAPI** 也提供了自有的 `HTTPException`。
-And **FastAPI**'s `HTTPException` error class inherits from Starlette's `HTTPException` error class.
+**FastAPI** 的 `HTTPException` 继承自 Starlette 的 `HTTPException` 错误类。
-The only difference, is that **FastAPI**'s `HTTPException` allows you to add headers to be included in the response.
+它们之间的唯一区别是,**FastAPI** 的 `HTTPException` 可以在响应中添加响应头。
-This is needed/used internally for OAuth 2.0 and some security utilities.
+OAuth 2.0 等安全工具需要在内部调用这些响应头。
-So, you can keep raising **FastAPI**'s `HTTPException` as normally in your code.
+因此你可以继续像平常一样在代码中触发 **FastAPI** 的 `HTTPException` 。
-But when you register an exception handler, you should register it for Starlette's `HTTPException`.
+但注册异常处理器时,应该注册到来自 Starlette 的 `HTTPException`。
-This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises a Starlette `HTTPException`, your handler will be able to catch and handle it.
+这样做是为了,当 Starlette 的内部代码、扩展或插件触发 Starlette `HTTPException` 时,处理程序能够捕获、并处理此异常。
-In this example, to be able to have both `HTTPException`s in the same code, Starlette's exceptions is renamed to `StarletteHTTPException`:
+注意,本例代码中同时使用了这两个 `HTTPException`,此时,要把 Starlette 的 `HTTPException` 命名为 `StarletteHTTPException`:
```Python
from starlette.exceptions import HTTPException as StarletteHTTPException
```
-### Re-use **FastAPI**'s exception handlers
+### 复用 **FastAPI** 异常处理器
-If you want to use the exception along with the same default exception handlers from **FastAPI**, You can import and re-use the default exception handlers from `fastapi.exception_handlers`:
+FastAPI 支持先对异常进行某些处理,然后再使用 **FastAPI** 中处理该异常的默认异常处理器。
```Python hl_lines="2-5 15 21"
{!../../../docs_src/handling_errors/tutorial006.py!}
From 935cf2646a4327dfd34dcb595186d26fe48d5dfe Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:44 +0800
Subject: [PATCH 140/163] New translations header-params.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/header-params.md | 74 ++++++++++++++------------
1 file changed, 40 insertions(+), 34 deletions(-)
diff --git a/docs/zh/docs/tutorial/header-params.md b/docs/zh/docs/tutorial/header-params.md
index 9e928cdc6b482..945345f38ef25 100644
--- a/docs/zh/docs/tutorial/header-params.md
+++ b/docs/zh/docs/tutorial/header-params.md
@@ -1,10 +1,10 @@
-# Header Parameters
+# Header 参数
-You can define Header parameters the same way you define `Query`, `Path` and `Cookie` parameters.
+你可以使用定义 `Query`, `Path` 和 `Cookie` 参数一样的方法定义 Header 参数。
-## Import `Header`
+## 导入 `Header`
-First import `Header`:
+首先导入 `Header`:
=== "Python 3.10+"
@@ -30,7 +30,7 @@ First import `Header`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
- {!> ../../../docs_src/header_params/tutorial001_py310.py!}
+ {!../../../docs_src/header_params/tutorial001.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -39,14 +39,14 @@ First import `Header`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
- {!> ../../../docs_src/header_params/tutorial001.py!}
+ {!../../../docs_src/header_params/tutorial002.py!}
```
-## Declare `Header` parameters
+## 声明 `Header` 参数
-Then declare the header parameters using the same structure as with `Path`, `Query` and `Cookie`.
+然后使用和`Path`, `Query` and `Cookie` 一样的结构定义 header 参数
-The first value is the default value, you can pass all the extra validation or annotation parameters:
+第一个值是默认值,你可以传递所有的额外验证或注释参数:
=== "Python 3.10+"
@@ -84,29 +84,29 @@ The first value is the default value, you can pass all the extra validation or a
{!> ../../../docs_src/header_params/tutorial001.py!}
```
-!!! note "Technical Details"
- `Header` is a "sister" class of `Path`, `Query` and `Cookie`. It also inherits from the same common `Param` class.
+!!! !!! note "技术细节"
+ `Header` 是 `Path`, `Query` 和 `Cookie` 的兄弟类型。 它也继承自通用的 `Param` 类.
- But remember that when you import `Query`, `Path`, `Header`, and others from `fastapi`, those are actually functions that return special classes.
+ 但是请记得,当你从`fastapi`导入 `Query`, `Path`, `Header`, 或其他时,实际上导入的是返回特定类型的函数。
!!! info
To declare headers, you need to use `Header`, because otherwise the parameters would be interpreted as query parameters.
-## Automatic conversion
+## 自动转换
-`Header` has a little extra functionality on top of what `Path`, `Query` and `Cookie` provide.
+`Header` 在 `Path`, `Query` 和 `Cookie` 提供的功能之上有一点额外的功能。
-Most of the standard headers are separated by a "hyphen" character, also known as the "minus symbol" (`-`).
+大多数标准的headers用 "连字符" 分隔,也称为 "减号" (`-`)。
-But a variable like `user-agent` is invalid in Python.
+但是像 `user-agent` 这样的变量在Python中是无效的。
-So, by default, `Header` will convert the parameter names characters from underscore (`_`) to hyphen (`-`) to extract and document the headers.
+因此, 默认情况下, `Header` 将把参数名称的字符从下划线 (`_`) 转换为连字符 (`-`) 来提取并记录 headers.
-Also, HTTP headers are case-insensitive, so, you can declare them with standard Python style (also known as "snake_case").
+同时,HTTP headers 是大小写不敏感的,因此,因此可以使用标准Python样式(也称为 "snake_case")声明它们。
-So, you can use `user_agent` as you normally would in Python code, instead of needing to capitalize the first letters as `User_Agent` or something similar.
+因此,您可以像通常在Python代码中那样使用 `user_agent` ,而不需要将首字母大写为 `User_Agent` 或类似的东西。
-If for some reason you need to disable automatic conversion of underscores to hyphens, set the parameter `convert_underscores` of `Header` to `False`:
+如果出于某些原因,你需要禁用下划线到连字符的自动转换,设置`Header`的参数 `convert_underscores` 为 `False`:
=== "Python 3.10+"
@@ -117,8 +117,11 @@ If for some reason you need to disable automatic conversion of underscores to hy
=== "Python 3.9+"
```Python hl_lines="11"
- {!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
+ !!! info
+ 为了声明headers, 你需要使用Header, 因为否则参数将被解释为查询参数。
```
+, 因为否则参数将被解释为查询参数。
+
=== "Python 3.6+"
@@ -141,21 +144,21 @@ If for some reason you need to disable automatic conversion of underscores to hy
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
- {!> ../../../docs_src/header_params/tutorial002.py!}
+ {!../../../docs_src/header_params/tutorial001.py!}
```
!!! warning
Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores.
-## Duplicate headers
+## 重复的 headers
-It is possible to receive duplicate headers. That means, the same header with multiple values.
+有可能收到重复的headers。 这意味着,相同的header具有多个值。
-You can define those cases using a list in the type declaration.
+您可以在类型声明中使用一个list来定义这些情况。
-You will receive all the values from the duplicate header as a Python `list`.
+你可以通过一个Python `list` 的形式获得重复header的所有值。
-For example, to declare a header of `X-Token` that can appear more than once, you can write:
+比如, 为了声明一个 `X-Token` header 可以出现多次,你可以这样写:
=== "Python 3.10+"
@@ -190,8 +193,11 @@ For example, to declare a header of `X-Token` that can appear more than once, yo
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
- {!> ../../../docs_src/header_params/tutorial003_py39.py!}
+ !!! warning
+ 在设置 convert_underscores 为 False 之前,请记住,一些HTTP代理和服务器不允许使用带有下划线的headers。
```
+ 为 False 之前,请记住,一些HTTP代理和服务器不允许使用带有下划线的headers。
+
=== "Python 3.6+ non-Annotated"
@@ -199,17 +205,17 @@ For example, to declare a header of `X-Token` that can appear more than once, yo
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
- {!> ../../../docs_src/header_params/tutorial003.py!}
+ {!../../../docs_src/header_params/tutorial003.py!}
```
-If you communicate with that *path operation* sending two HTTP headers like:
+如果你与*路径操作*通信时发送两个HTTP headers,就像:
```
X-Token: foo
X-Token: bar
```
-The response would be like:
+响应会是:
```JSON
{
@@ -220,8 +226,8 @@ The response would be like:
}
```
-## Recap
+## 回顾
-Declare headers with `Header`, using the same common pattern as `Query`, `Path` and `Cookie`.
+使用 `Header` 来声明 header , 使用和 `Query`, `Path` 与 `Cookie` 相同的模式。
-And don't worry about underscores in your variables, **FastAPI** will take care of converting them.
+不用担心变量中的下划线,**FastAPI** 会负责转换它们。
From 81e05aab9faef4bfcc8a4d81843e87a8eef59e22 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:45 +0800
Subject: [PATCH 141/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/tutorial/index.md | 42 ++++++++++++++++++----------------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md
index d592f4744650a..2753a8e3c9442 100644
--- a/docs/zh/docs/tutorial/index.md
+++ b/docs/zh/docs/tutorial/index.md
@@ -1,6 +1,6 @@
-# Tutorial - User Guide
+# 教程 - 用户指南
-This tutorial shows you how to use **FastAPI** with most of its features, step by step.
+本教程将一步步向你展示如何使用 **FastAPI** 的绝大部分特性。
Each section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
@@ -8,11 +8,11 @@ It is also built to work as a future reference.
So you can come back and see exactly what you need.
-## Run the code
+## 运行代码
-All the code blocks can be copied and used directly (they are actually tested Python files).
+所有代码片段都可以复制后直接使用(它们实际上是经过测试的 Python 文件)。
-To run any of the examples, copy the code to a file `main.py`, and start `uvicorn` with:
+要运行任何示例,请将代码复制到 `main.py` 文件中,然后使用以下命令启动 `uvicorn`:
contact fields| Parameter | Type | Description |
|---|---|---|
name | str | The identifying name of the contact person/organization. |
url | str | The URL pointing to the contact information. MUST be in the format of a URL. |
email | str | The email address of the contact person/organization. MUST be in the format of an email address. |
license_info fields| Parameter | Type | Description |
|---|---|---|
name | str | REQUIRED (if a license_info is set). The license name used for the API. |
identifier | str | An SPDX license expression for the API. The identifier field is mutually exclusive of the url field. Available since OpenAPI 3.1.0, FastAPI 0.99.0. |
url | str | A URL to the license used for the API. MUST be in the format of a URL. |
@@ -39,38 +39,38 @@ For example:
{!../../../docs_src/metadata/tutorial001_1.py!}
```
-## Metadata for tags
+## 标签元数据
-You can also add additional metadata for the different tags used to group your path operations with the parameter `openapi_tags`.
+你也可以使用参数 `openapi_tags`,为用于分组路径操作的不同标签添加额外的元数据。
-It takes a list containing one dictionary for each tag.
+它接受一个列表,这个列表包含每个标签对应的一个字典。
-Each dictionary can contain:
+每个字典可以包含:
-* `name` (**required**): a `str` with the same tag name you use in the `tags` parameter in your *path operations* and `APIRouter`s.
-* `description`: a `str` with a short description for the tag. It can have Markdown and will be shown in the docs UI.
-* `externalDocs`: a `dict` describing external documentation with:
- * `description`: a `str` with a short description for the external docs.
- * `url` (**required**): a `str` with the URL for the external documentation.
+* `name`(**必要**):一个 `str`,它与*路径操作*和 `APIRouter` 中使用的 `tags` 参数有相同的标签名。
+* `description`:一个用于简短描述标签的 `str`。 它支持 Markdown 并且会在文档用户界面中显示。
+* `externalDocs`:一个描述外部文档的 `dict`:
+ * `description`:用于简短描述外部文档的 `str`。
+ * `url`(**必要**):外部文档的 URL `str`。
-### Create metadata for tags
+### 创建标签元数据
-Let's try that in an example with tags for `users` and `items`.
+让我们在带有标签的示例中为 `users` 和 `items` 试一下。
-Create metadata for your tags and pass it to the `openapi_tags` parameter:
+创建标签元数据并把它传递给 `openapi_tags` 参数:
```Python hl_lines="3-16 18"
{!../../../docs_src/metadata/tutorial004.py!}
```
-Notice that you can use Markdown inside of the descriptions, for example "login" will be shown in bold (**login**) and "fancy" will be shown in italics (_fancy_).
+注意你可以在描述内使用 Markdown,例如「login」会显示为粗体(**login**)以及「fancy」会显示为斜体(_fancy_)。
-!!! tip
- You don't have to add metadata for all the tags that you use.
+!!! !!! 提示
+ 不必为你使用的所有标签都添加元数据。
-### Use your tags
+### 使用你的标签
-Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assign them to different tags:
+将 `tags` 参数和*路径操作*(以及 `APIRouter`)一起使用,将其分配给不同的标签:
```Python hl_lines="21 26"
{!../../../docs_src/metadata/tutorial004.py!}
@@ -79,44 +79,44 @@ Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assig
!!! info
Read more about tags in [Path Operation Configuration](../path-operation-configuration/#tags){.internal-link target=_blank}.
-### Check the docs
+### 查看文档
-Now, if you check the docs, they will show all the additional metadata:
+如果你现在查看文档,它们会显示所有附加的元数据:
-### Order of tags
+### 标签顺序
-The order of each tag metadata dictionary also defines the order shown in the docs UI.
+每个标签元数据字典的顺序也定义了在文档用户界面显示的顺序。
-For example, even though `users` would go after `items` in alphabetical order, it is shown before them, because we added their metadata as the first dictionary in the list.
+例如按照字母顺序,即使 `users` 排在 `items` 之后,它也会显示在前面,因为我们将它的元数据添加为列表内的第一个字典。
## OpenAPI URL
-By default, the OpenAPI schema is served at `/openapi.json`.
+默认情况下,OpenAPI 模式服务于 `/openapi.json`。
-But you can configure it with the parameter `openapi_url`.
+但是你可以通过参数 `openapi_url` 对其进行配置。
-For example, to set it to be served at `/api/v1/openapi.json`:
+例如,将其设置为服务于 `/api/v1/openapi.json`:
```Python hl_lines="3"
{!../../../docs_src/metadata/tutorial002.py!}
```
-If you want to disable the OpenAPI schema completely you can set `openapi_url=None`, that will also disable the documentation user interfaces that use it.
+如果你想完全禁用 OpenAPI 模式,可以将其设置为 `openapi_url=None`,这样也会禁用使用它的文档用户界面。
-## Docs URLs
+## 文档 URLs
-You can configure the two documentation user interfaces included:
+你可以配置两个文档用户界面,包括:
-* **Swagger UI**: served at `/docs`.
- * You can set its URL with the parameter `docs_url`.
- * You can disable it by setting `docs_url=None`.
-* **ReDoc**: served at `/redoc`.
- * You can set its URL with the parameter `redoc_url`.
- * You can disable it by setting `redoc_url=None`.
+* **Swagger UI**:服务于 `/docs`。
+ * 可以使用参数 `docs_url` 设置它的 URL。
+ * 可以通过设置 `docs_url=None` 禁用它。
+* **Version**:API 版本,例如 `v2` 或者 `2.5.0`。
+ * 可以使用参数 `redoc_url` 设置它的 URL。
+ * 可以通过设置 `redoc_url=None` 禁用它。
-For example, to set Swagger UI to be served at `/documentation` and disable ReDoc:
+例如,设置 Swagger UI 服务于 `/documentation` 并禁用 ReDoc:
```Python hl_lines="3"
{!../../../docs_src/metadata/tutorial003.py!}
From b4af5cf316d568f57e8a1de6f3f86d5b44e0ca7c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:47 +0800
Subject: [PATCH 143/163] New translations middleware.md (Chinese Simplified)
---
docs/zh/docs/tutorial/middleware.md | 64 ++++++++++++++---------------
1 file changed, 32 insertions(+), 32 deletions(-)
diff --git a/docs/zh/docs/tutorial/middleware.md b/docs/zh/docs/tutorial/middleware.md
index 3c6868fe4de73..8be591d8ee697 100644
--- a/docs/zh/docs/tutorial/middleware.md
+++ b/docs/zh/docs/tutorial/middleware.md
@@ -1,61 +1,61 @@
-# Middleware
+# 中间件
-You can add middleware to **FastAPI** applications.
+你可以向 **FastAPI** 应用添加中间件.
-A "middleware" is a function that works with every **request** before it is processed by any specific *path operation*. And also with every **response** before returning it.
+"中间件"是一个函数,它在每个**请求**被特定的*路径操作*处理之前,以及在每个**响应**返回之前工作. And also with every **response** before returning it.
-* It takes each **request** that comes to your application.
-* It can then do something to that **request** or run any needed code.
-* Then it passes the **request** to be processed by the rest of the application (by some *path operation*).
-* It then takes the **response** generated by the application (by some *path operation*).
-* It can do something to that **response** or run any needed code.
-* Then it returns the **response**.
+* 它接收你的应用程序的每一个**请求**.
+* 然后它可以对这个**请求**做一些事情或者执行任何需要的代码.
+* 然后它将**请求**传递给应用程序的其他部分 (通过某种*路径操作*).
+* 然后它获取应用程序生产的**响应** (通过某种*路径操作*).
+* 它可以对该**响应**做些什么或者执行任何需要的代码.
+* 然后它返回这个 **响应**.
-!!! note "Technical Details"
- If you have dependencies with `yield`, the exit code will run *after* the middleware.
+!!! !!! note "技术细节"
+ 如果你使用了 `yield` 关键字依赖, 依赖中的退出代码将在执行中间件*后*执行.
- If there were any background tasks (documented later), they will run *after* all the middleware.
+ 如果有任何后台任务(稍后记录), 它们将在执行中间件*后*运行.
-## Create a middleware
+## 创建中间件
-To create a middleware you use the decorator `@app.middleware("http")` on top of a function.
+要创建中间件你可以在函数的顶部使用装饰器 `@app.middleware("http")`.
The middleware function receives:
-* The `request`.
-* A function `call_next` that will receive the `request` as a parameter.
- * This function will pass the `request` to the corresponding *path operation*.
- * Then it returns the `response` generated by the corresponding *path operation*.
-* You can then modify further the `response` before returning it.
+* `request`.
+* 一个函数 `call_next` 它将接收 `request` 作为参数.
+ * 这个函数将 `request` 传递给相应的 *路径操作*.
+ * 然后它将返回由相应的*路径操作*生成的 `response`.
+* 然后你可以在返回 `response` 前进一步修改它.
```Python hl_lines="8-9 11 14"
{!../../../docs_src/middleware/tutorial001.py!}
```
-!!! tip
- Have in mind that custom proprietary headers can be added using the 'X-' prefix.
+!!! !!! tip
+ 请记住可以 用'X-' 前缀添加专有自定义请求头.
- But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in Starlette's CORS docs.
+ 但是如果你想让浏览器中的客户端看到你的自定义请求头, 你需要把它们加到 CORS 配置 ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) 的 `expose_headers` 参数中,在 Starlette's CORS docs文档中.
-!!! note "Technical Details"
- You could also use `from starlette.requests import Request`.
+!!! !!! note "技术细节"
+ 你也可以使用 `from starlette.requests import Request`.
- **FastAPI** provides it as a convenience for you, the developer. But it comes directly from Starlette.
+ **FastAPI** 为了开发者方便提供了该对象. 但其实它直接来自于 Starlette. But it comes directly from Starlette.
-### Before and after the `response`
+### 在 `response` 的前和后
-You can add code to be run with the `request`, before any *path operation* receives it.
+在任何*路径操作*收到`request`前,可以添加要和请求一起运行的代码.
-And also after the `response` is generated, before returning it.
+也可以在*响应*生成但是返回之前添加代码.
-For example, you could add a custom header `X-Process-Time` containing the time in seconds that it took to process the request and generate a response:
+例如你可以添加自定义请求头 `X-Process-Time` 包含以秒为单位的接收请求和生成响应的时间:
```Python hl_lines="10 12-13"
{!../../../docs_src/middleware/tutorial001.py!}
```
-## Other middlewares
+## 其他中间件
-You can later read more about other middlewares in the [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.
+你可以稍后在 [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}阅读更多关于中间件的教程.
-You will read about how to handle CORS with a middleware in the next section.
+你将在下一节中学习如何使用中间件处理 CORS .
From 84da9df9da71489d3625385d6e3ebc9065b7cdf7 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:49 +0800
Subject: [PATCH 144/163] New translations path-operation-configuration.md
(Chinese Simplified)
---
.../tutorial/path-operation-configuration.md | 84 ++++++++++---------
1 file changed, 44 insertions(+), 40 deletions(-)
diff --git a/docs/zh/docs/tutorial/path-operation-configuration.md b/docs/zh/docs/tutorial/path-operation-configuration.md
index ee3b5cd0ad9f6..7102406acc732 100644
--- a/docs/zh/docs/tutorial/path-operation-configuration.md
+++ b/docs/zh/docs/tutorial/path-operation-configuration.md
@@ -1,66 +1,65 @@
-# Path Operation Configuration
+# 路径操作配置
-There are several parameters that you can pass to your *path operation decorator* to configure it.
+*路径操作装饰器*支持多种配置参数。
!!! warning
Notice that these parameters are passed directly to the *path operation decorator*, not to your *path operation function*.
-## Response Status Code
+## `status_code` 状态码
-You can define the (HTTP) `status_code` to be used in the response of your *path operation*.
+`status_code` 用于定义*路径操作*响应中的 HTTP 状态码。
-You can pass directly the `int` code, like `404`.
+可以直接传递 `int` 代码, 比如 `404`。
-But if you don't remember what each number code is for, you can use the shortcut constants in `status`:
+如果记不住数字码的涵义,也可以用 `status` 的快捷常量:
=== "Python 3.10+"
```Python hl_lines="1 15"
- {!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
+ 注意:以下参数应直接传递给**路径操作装饰器**,不能传递给*路径操作函数*。
```
=== "Python 3.9+"
```Python hl_lines="3 17"
- {!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
+ !!! check "检查"
```
=== "Python 3.6+"
```Python hl_lines="3 17"
- {!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
+ API 文档会把该路径操作标记为弃用:
```
-That status code will be used in the response and will be added to the OpenAPI schema.
+状态码在响应中使用,并会被添加到 OpenAPI 概图。
-!!! note "Technical Details"
- You could also use `from starlette import status`.
+!!! 也可以使用 `from starlette import status` 导入状态码。
- **FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
+ **FastAPI** 的`fastapi.status` 和 `starlette.status` 一样,只是快捷方式。 But it comes directly from Starlette.
## Tags
-You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
+`tags` 参数的值是由 `str` 组成的 `list` (一般只有一个 `str` ),`tags` 用于为*路径操作*添加标签:
=== "Python 3.10+"
```Python hl_lines="15 20 25"
- {!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
+ {!../../../docs_src/path_operation_configuration/tutorial005.py!}
```
=== "Python 3.9+"
```Python hl_lines="17 22 27"
- {!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
+ 注意,`response_description` 只用于描述响应,`description` 一般则用于描述*路径操作*。
```
=== "Python 3.6+"
```Python hl_lines="17 22 27"
- {!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
+ {!../../../docs_src/path_operation_configuration/tutorial002.py!}
```
-They will be added to the OpenAPI schema and used by the automatic documentation interfaces:
+OpenAPI 概图会自动添加标签,供 API 文档接口使用:
@@ -73,94 +72,99 @@ In these cases, it could make sense to store the tags in an `Enum`.
**FastAPI** supports that the same way as with plain strings:
```Python hl_lines="1 8-10 13 18"
-{!../../../docs_src/path_operation_configuration/tutorial002b.py!}
+{!../../../docs_src/path_operation_configuration/tutorial001.py!}
```
## Summary and description
-You can add a `summary` and `description`:
+`summary` 和 `description` 参数
=== "Python 3.10+"
```Python hl_lines="18-19"
- {!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
+ {!../../../docs_src/path_operation_configuration/tutorial003.py!}
```
=== "Python 3.9+"
```Python hl_lines="20-21"
- {!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
+ !!! warning "警告"
```
=== "Python 3.6+"
```Python hl_lines="20-21"
- {!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
+ 路径装饰器还支持 summary 和 description 这两个参数:
```
+ 和 description 这两个参数:
+
## Description from docstring
-As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function docstring and **FastAPI** will read it from there.
+描述内容比较长且占用多行时,可以在函数的 docstring 中声明*路径操作*的描述,**FastAPI** 支持从文档字符串中读取描述内容。
-You can write Markdown in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
+文档字符串支持 Markdown,能正确解析和显示 Markdown 的内容,但要注意文档字符串的缩进。
=== "Python 3.10+"
```Python hl_lines="17-25"
- {!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
+ {!../../../docs_src/path_operation_configuration/tutorial004.py!}
```
=== "Python 3.9+"
```Python hl_lines="19-27"
- {!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
+ 下图为 Markdown 文本在 API 文档中的显示效果:
```
=== "Python 3.6+"
```Python hl_lines="19-27"
- {!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
+ 文档字符串(docstring)
```
+)
+
It will be used in the interactive docs:
-## Response description
+## 响应描述
-You can specify the response description with the parameter `response_description`:
+`response_description` 参数用于定义响应的描述说明:
=== "Python 3.10+"
```Python hl_lines="19"
- {!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
+ !!! info "说明"
```
=== "Python 3.9+"
```Python hl_lines="21"
- {!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
+ !!! note "技术细节"
```
=== "Python 3.6+"
```Python hl_lines="21"
- {!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
+ tags 参数
```
+ 参数
+
!!! info
Notice that `response_description` refers specifically to the response, the `description` refers to the *path operation* in general.
-!!! check
- OpenAPI specifies that each *path operation* requires a response description.
+!!! OpenAPI 规定每个*路径操作*都要有响应描述。
- So, if you don't provide one, **FastAPI** will automatically generate one of "Successful response".
+ 如果没有定义响应描述,**FastAPI** 则自动生成内容为 "Successful response" 的响应描述。
-## Deprecate a *path operation*
+## 弃用*路径操作*
-If you need to mark a *path operation* as deprecated, but without removing it, pass the parameter `deprecated`:
+`deprecated` 参数可以把*路径操作*标记为弃用,无需直接删除:
```Python hl_lines="16"
{!../../../docs_src/path_operation_configuration/tutorial006.py!}
@@ -170,10 +174,10 @@ It will be clearly marked as deprecated in the interactive docs:
-Check how deprecated and non-deprecated *path operations* look like:
+下图显示了正常*路径操作*与弃用*路径操作* 的区别:
## Recap
-You can configure and add metadata for your *path operations* easily by passing parameters to the *path operation decorators*.
+通过传递参数给*路径操作装饰器* ,即可轻松地配置*路径操作*、添加元数据。
From 651faea64d0b2b7cb4f07ee9f92be6dbccfe450c Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:50 +0800
Subject: [PATCH 145/163] New translations path-params-numeric-validations.md
(Chinese Simplified)
---
.../path-params-numeric-validations.md | 113 +++++++++---------
1 file changed, 59 insertions(+), 54 deletions(-)
diff --git a/docs/zh/docs/tutorial/path-params-numeric-validations.md b/docs/zh/docs/tutorial/path-params-numeric-validations.md
index fd211224826c3..fc045d9b4b3a7 100644
--- a/docs/zh/docs/tutorial/path-params-numeric-validations.md
+++ b/docs/zh/docs/tutorial/path-params-numeric-validations.md
@@ -1,10 +1,10 @@
-# Path Parameters and Numeric Validations
+# 路径参数和数值校验
-In the same way that you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`.
+与使用 `Query` 为查询参数声明更多的校验和元数据的方式相同,你也可以使用 `Path` 为路径参数声明相同类型的校验和元数据。
-## Import Path
+## 导入 Path
-First, import `Path` from `fastapi`, and import `Annotated`:
+首先,从 `fastapi` 导入 `Path`:
=== "Python 3.10+"
@@ -30,7 +30,7 @@ First, import `Path` from `fastapi`, and import `Annotated`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ {!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -39,7 +39,7 @@ First, import `Path` from `fastapi`, and import `Annotated`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ {!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
!!! info
@@ -49,11 +49,11 @@ First, import `Path` from `fastapi`, and import `Annotated`:
Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
-## Declare metadata
+## 声明元数据
-You can declare all the same parameters as for `Query`.
+你可以声明与 `Query` 相同的所有参数。
-For example, to declare a `title` metadata value for the path parameter `item_id` you can type:
+例如,要声明路径参数 `item_id`的 `title` 元数据值,你可以输入:
=== "Python 3.10+"
@@ -79,7 +79,7 @@ For example, to declare a `title` metadata value for the path parameter `item_id
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ {!../../../docs_src/path_params_numeric_validations/tutorial005.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -94,28 +94,28 @@ For example, to declare a `title` metadata value for the path parameter `item_id
!!! note
A path parameter is always required as it has to be part of the path.
- So, you should declare it with `...` to mark it as required.
+ 所以,你应该在声明时使用 `...` 将其标记为必需参数。
- Nevertheless, even if you declared it with `None` or set a default value, it would not affect anything, it would still be always required.
+ 然而,即使你使用 `None` 声明路径参数或设置一个其他默认值也不会有任何影响,它依然会是必需参数。
-## Order the parameters as you need
+## 按需对参数排序
!!! tip
This is probably not as important or necessary if you use `Annotated`.
-Let's say that you want to declare the query parameter `q` as a required `str`.
+假设你想要声明一个必需的 `str` 类型查询参数 `q`。
-And you don't need to declare anything else for that parameter, so you don't really need to use `Query`.
+而且你不需要为该参数声明任何其他内容,所以实际上你并不需要使用 `Query`。
But you still need to use `Path` for the `item_id` path parameter. And you don't want to use `Annotated` for some reason.
-Python will complain if you put a value with a "default" before a value that doesn't have a "default".
+如果你将带有「默认值」的参数放在没有「默认值」的参数之前,Python 将会报错。
-But you can re-order them, and have the value without a default (the query parameter `q`) first.
+但是你可以对其重新排序,并将不带默认值的值(查询参数 `q`)放到最前面。
-It doesn't matter for **FastAPI**. It will detect the parameters by their names, types and default declarations (`Query`, `Path`, etc), it doesn't care about the order.
+对 **FastAPI** 来说这无关紧要。 它将通过参数的名称、类型和默认值声明(`Query`、`Path` 等)来检测参数,而不在乎参数的顺序。
-So, you can declare your function as:
+因此,你可以将函数声明为:
=== "Python 3.6 non-Annotated"
@@ -126,7 +126,8 @@ So, you can declare your function as:
{!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
-But have in mind that if you use `Annotated`, you won't have this problem, it won't matter as you're not using the function parameter default values for `Query()` or `Path()`.
+!!! note "技术细节"
+ 当你从 `fastapi` 导入 `Query`、`Path` 和其他同类对象时,它们实际上是函数。
=== "Python 3.9+"
@@ -137,10 +138,10 @@ But have in mind that if you use `Annotated`, you won't have this problem, it wo
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
+ {!../../../docs_src/path_params_numeric_validations/tutorial006.py!}
```
-## Order the parameters as you need, tricks
+## 按需对参数排序的技巧
!!! tip
This is probably not as important or necessary if you use `Annotated`.
@@ -149,16 +150,17 @@ Here's a **small trick** that can be handy, but you won't need it often.
If you want to:
-* declare the `q` query parameter without a `Query` nor any default value
-* declare the path parameter `item_id` using `Path`
+* !!! info
+ `Query`、`Path` 以及你后面会看到的其他类继承自一个共同的 `Param` 类(不需要直接使用它)。
+* 但是你仍然需要使用 `Path` 来声明路径参数 `item_id`。
* have them in a different order
* not use `Annotated`
...Python has a little special syntax for that.
-Pass `*`, as the first parameter of the function.
+传递 `*` 作为函数的第一个参数。
-Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as kwargs. Even if they don't have a default value.
+Python 不会对该 `*` 做任何事情,但是它将知道之后的所有参数都应作为关键字参数(键值对),也被称为 kwargs,来调用。 即使它们没有默认值。
```Python hl_lines="7"
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
@@ -177,14 +179,14 @@ Have in mind that if you use `Annotated`, as you are not using function paramete
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
+ {!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
-## Number validations: greater than or equal
+## 数值校验:大于等于
-With `Query` and `Path` (and others you'll see later) you can declare number constraints.
+使用 `Query` 和 `Path`(以及你将在后面看到的其他类)可以声明字符串约束,但也可以声明数值约束。
-Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`.
+像下面这样,添加 `ge=1` 后,`item_id` 将必须是一个大于(`g`reater than)或等于(`e`qual)`1` 的整数。
=== "Python 3.9+"
@@ -195,7 +197,7 @@ Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than o
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
+ {!../../../docs_src/path_params_numeric_validations/tutorial004.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -207,12 +209,12 @@ Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than o
{!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
```
-## Number validations: greater than and less than or equal
+## 数值校验:大于和小于等于
-The same applies for:
+同样的规则适用于:
-* `gt`: `g`reater `t`han
-* `le`: `l`ess than or `e`qual
+* `gt`:大于(`g`reater `t`han)
+* `ge`:大于等于(`g`reater than or `e`qual)
=== "Python 3.9+"
@@ -223,7 +225,7 @@ The same applies for:
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
+ 总结
```
=== "Python 3.6+ non-Annotated"
@@ -235,27 +237,30 @@ The same applies for:
{!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
```
-## Number validations: floats, greater than and less than
+## 数值校验:浮点数、大于和小于
-Number validations also work for `float` values.
+数值校验同样适用于 `float` 值。
-Here's where it becomes important to be able to declare gt and not just ge. As with it you can require, for example, that a value must be greater than `0`, even if it is less than `1`.
+能够声明 gt 而不仅仅是 ge 在这个前提下变得重要起来。 例如,你可以要求一个值必须大于 `0`,即使它小于 `1`。
-So, `0.5` would be a valid value. But `0.0` or `0` would not.
+因此,`0.5` 将是有效值。 但是 `0.0`或 `0` 不是。
-And the same for lt.
+对于 lt 也是一样的。
=== "Python 3.9+"
```Python hl_lines="13"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
+ !!! note
+ 路径参数总是必需的,因为它必须是路径的一部分。
```
=== "Python 3.6+"
```Python hl_lines="12"
- {!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
+ 如果你想不使用 Query 声明没有默认值的查询参数 q,同时使用 Path 声明路径参数 item_id,并使它们的顺序与上面不同,Python 对此有一些特殊的语法。
```
+ 声明没有默认值的查询参数 q,同时使用 Path 声明路径参数 item_id,并使它们的顺序与上面不同,Python 对此有一些特殊的语法。
+
=== "Python 3.6+ non-Annotated"
@@ -268,27 +273,27 @@ And the same for lt.
## Recap
-With `Query`, `Path` (and others you haven't seen yet) you can declare metadata and string validations in the same ways as with [Query Parameters and String Validations](query-params-str-validations.md){.internal-link target=_blank}.
+你能够以与 [查询参数和字符串校验](query-params-str-validations.md){.internal-link target=_blank} 相同的方式使用 `Query`、`Path`(以及其他你还没见过的类)声明元数据和字符串校验。
-And you can also declare numeric validations:
+而且你还可以声明数值校验:
-* `gt`: `g`reater `t`han
-* `ge`: `g`reater than or `e`qual
-* `lt`: `l`ess `t`han
-* `le`: `l`ess than or `e`qual
+* `gt`:大于(`g`reater `t`han)
+* `le`:小于等于(`l`ess than or `e`qual)
+* `lt`:小于(`l`ess `t`han)
+* `le`:小于等于(`l`ess than or `e`qual)
!!! info
`Query`, `Path`, and other classes you will see later are subclasses of a common `Param` class.
- All of them share the same parameters for additional validation and metadata you have seen.
+ 而且它们都共享相同的所有你已看到并用于添加额外校验和元数据的参数。
!!! note "Technical Details"
When you import `Query`, `Path` and others from `fastapi`, they are actually functions.
- That when called, return instances of classes of the same name.
+ 当被调用时,它们返回同名类的实例。
- So, you import `Query`, which is a function. And when you call it, it returns an instance of a class also named `Query`.
+ 如此,你导入 `Query` 这个函数。 当你调用它时,它将返回一个同样命名为 `Query` 的类的实例。
- These functions are there (instead of just using the classes directly) so that your editor doesn't mark errors about their types.
+ 因为使用了这些函数(而不是直接使用类),所以你的编辑器不会标记有关其类型的错误。
- That way you can use your normal editor and coding tools without having to add custom configurations to disregard those errors.
+ 这样,你可以使用常规的编辑器和编码工具,而不必添加自定义配置来忽略这些错误。
From 98419712837934baa99d04de160d9ac49bb067f7 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:51 +0800
Subject: [PATCH 146/163] New translations path-params.md (Chinese Simplified)
---
docs/zh/docs/tutorial/path-params.md | 172 +++++++++++++--------------
1 file changed, 86 insertions(+), 86 deletions(-)
diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md
index 6b14a69a6f553..a307010299d68 100644
--- a/docs/zh/docs/tutorial/path-params.md
+++ b/docs/zh/docs/tutorial/path-params.md
@@ -1,48 +1,48 @@
-# Path Parameters
+# 路径参数
-You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
+你可以使用与 Python 格式化字符串相同的语法来声明路径"参数"或"变量":
```Python hl_lines="6-7"
{!../../../docs_src/path_params/tutorial001.py!}
```
-The value of the path parameter `item_id` will be passed to your function as the argument `item_id`.
+路径参数 `item_id` 的值将作为参数 `item_id` 传递给你的函数。
-So, if you run this example and go to http://127.0.0.1:8000/items/foo, you will see a response of:
+所以,如果你运行示例并访问 http://127.0.0.1:8000/items/foo,将会看到如下响应:
```JSON
{"item_id":"foo"}
```
-## Path parameters with types
+## 有类型的路径参数
-You can declare the type of a path parameter in the function, using standard Python type annotations:
+你可以使用标准的 Python 类型标注为函数中的路径参数声明类型。
```Python hl_lines="7"
{!../../../docs_src/path_params/tutorial002.py!}
```
-In this case, `item_id` is declared to be an `int`.
+在这个例子中,`item_id` 被声明为 `int` 类型。
-!!! check
- This will give you editor support inside of your function, with error checks, completion, etc.
+!!! !!! check
+ 这将为你的函数提供编辑器支持,包括错误检查、代码补全等等。
-## Data conversion
+## 数据转换
-If you run this example and open your browser at http://127.0.0.1:8000/items/3, you will see a response of:
+如果你运行示例并打开浏览器访问 http://127.0.0.1:8000/items/3,将得到如下响应:
```JSON
{"item_id":3}
```
-!!! check
- Notice that the value your function received (and returned) is `3`, as a Python `int`, not a string `"3"`.
+!!! !!! check
+ 注意函数接收(并返回)的值为 3,是一个 Python `int` 值,而不是字符串 `"3"`。
- So, with that type declaration, **FastAPI** gives you automatic request "parsing".
+ 所以,**FastAPI** 通过上面的类型声明提供了对请求的自动"解析"。
-## Data validation
+## 数据校验
-But if you go to the browser at http://127.0.0.1:8000/items/foo, you will see a nice HTTP error of:
+但如果你通过浏览器访问 http://127.0.0.1:8000/items/foo,你会看到一个清晰可读的 HTTP 错误:
```JSON
{
@@ -59,61 +59,61 @@ But if you go to the browser at http://127.0.0.1:8000/items/4.2
+如果你提供的是 `float` 而非整数也会出现同样的错误,比如: http://127.0.0.1:8000/items/4.2
-!!! check
- So, with the same Python type declaration, **FastAPI** gives you data validation.
+!!! !!! check
+ 所以,通过同样的 Python 类型声明,**FastAPI** 提供了数据校验功能。
- Notice that the error also clearly states exactly the point where the validation didn't pass.
+ 注意上面的错误同样清楚地指出了校验未通过的具体原因。
- This is incredibly helpful while developing and debugging code that interacts with your API.
+ 在开发和调试与你的 API 进行交互的代码时,这非常有用。
-## Documentation
+## 文档
-And when you open your browser at http://127.0.0.1:8000/docs, you will see an automatic, interactive, API documentation like:
+当你打开浏览器访问 http://127.0.0.1:8000/docs,你将看到自动生成的交互式 API 文档:
-!!! check
- Again, just with that same Python type declaration, **FastAPI** gives you automatic, interactive documentation (integrating Swagger UI).
+!!! !!! check
+ 再一次,还是通过相同的 Python 类型声明,**FastAPI** 为你提供了自动生成的交互式文档(集成 Swagger UI)。
- Notice that the path parameter is declared to be an integer.
+ 注意这里的路径参数被声明为一个整数。
-## Standards-based benefits, alternative documentation
+## 基于标准的好处:可选文档
-And because the generated schema is from the OpenAPI standard, there are many compatible tools.
+由于生成的 API 模式来自于 OpenAPI 标准,所以有很多工具与其兼容。
-Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc), which you can access at http://127.0.0.1:8000/redoc:
+正因如此,**FastAPI** 内置了一个可选的 API 文档(使用 Redoc):
-The same way, there are many compatible tools. Including code generation tools for many languages.
+The same way, there are many compatible tools. 同样的,还有很多其他兼容的工具,包括适用于多种语言的代码生成工具。
## Pydantic
-All the data validation is performed under the hood by Pydantic, so you get all the benefits from it. And you know you are in good hands.
+所有的数据校验都由 Pydantic 在幕后完成,所以你可以从它所有的优点中受益。 并且你知道它在这方面非常胜任。
-You can use the same type declarations with `str`, `float`, `bool` and many other complex data types.
+你可以使用同样的类型声明来声明 `str`、`float`、`bool` 以及许多其他的复合数据类型。
-Several of these are explored in the next chapters of the tutorial.
+本教程的下一章节将探讨其中的一些内容。
## Order matters
-When creating *path operations*, you can find situations where you have a fixed path.
+在创建*路径操作*时,你会发现有些情况下路径是固定的。
-Like `/users/me`, let's say that it's to get data about the current user.
+比如 `/users/me`,我们假设它用来获取关于当前用户的数据.
-And then you can also have a path `/users/{user_id}` to get data about a specific user by some user ID.
+然后,你还可以使用路径 `/users/{user_id}` 来通过用户 ID 获取关于特定用户的数据。
-Because *path operations* are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
+由于*路径操作*是按顺序依次运行的,你需要确保路径 `/users/me` 声明在路径 `/users/{user_id}`之前:
```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
-Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`.
+否则,`/users/{user_id}` 的路径还将与 `/users/me` 相匹配,"认为"自己正在接收一个值为 `"me"` 的 `user_id` 参数。
Similarly, you cannot redefine a path operation:
@@ -123,70 +123,70 @@ Similarly, you cannot redefine a path operation:
The first one will always be used since the path matches first.
-## Predefined values
+## 预设值
-If you have a *path operation* that receives a *path parameter*, but you want the possible valid *path parameter* values to be predefined, you can use a standard Python `Enum`.
+如果你有一个接收路径参数的路径操作,但你希望预先设定可能的有效参数值,则可以使用标准的 Python `Enum` 类型。
-### Create an `Enum` class
+### 创建一个 `Enum` 类
-Import `Enum` and create a sub-class that inherits from `str` and from `Enum`.
+导入 `Enum` 并创建一个继承自 `str` 和 `Enum` 的子类。
-By inheriting from `str` the API docs will be able to know that the values must be of type `string` and will be able to render correctly.
+通过从 `str` 继承,API 文档将能够知道这些值必须为 `string` 类型并且能够正确地展示出来。
-Then create class attributes with fixed values, which will be the available valid values:
+然后创建具有固定值的类属性,这些固定值将是可用的有效值:
```Python hl_lines="1 6-9"
{!../../../docs_src/path_params/tutorial005.py!}
```
-!!! info
- Enumerations (or enums) are available in Python since version 3.4.
+!!! !!! info
+ 枚举(或 enums)从 3.4 版本起在 Python 中可用。
-!!! tip
- If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine Learning models.
+!!! !!! tip
+ 如果你想知道,"AlexNet"、"ResNet" 和 "LeNet" 只是机器学习中的模型名称。
-### Declare a *path parameter*
+### 声明*路径参数*
-Then create a *path parameter* with a type annotation using the enum class you created (`ModelName`):
+然后使用你定义的枚举类(`ModelName`)创建一个带有类型标注的*路径参数*:
```Python hl_lines="16"
{!../../../docs_src/path_params/tutorial005.py!}
```
-### Check the docs
+### 查看文档
-Because the available values for the *path parameter* are predefined, the interactive docs can show them nicely:
+*路径参数*的值将是一个*枚举成员*。
-### Working with Python *enumerations*
+### 使用 Python *枚举类型*
-The value of the *path parameter* will be an *enumeration member*.
+因为已经指定了*路径参数*的可用值,所以交互式文档可以恰当地展示它们:
-#### Compare *enumeration members*
+#### 比较*枚举成员*
-You can compare it with the *enumeration member* in your created enum `ModelName`:
+你可以将它与你创建的枚举类 `ModelName` 中的*枚举成员*进行比较:
```Python hl_lines="17"
{!../../../docs_src/path_params/tutorial005.py!}
```
-#### Get the *enumeration value*
+#### 获取*枚举值*
-You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
+你可以使用 `model_name.value` 或通常来说 `your_enum_member.value` 来获取实际的值(在这个例子中为 `str`):
```Python hl_lines="20"
{!../../../docs_src/path_params/tutorial005.py!}
```
-!!! tip
- You could also access the value `"lenet"` with `ModelName.lenet.value`.
+!!! !!! tip
+ 你也可以通过 `ModelName.lenet.value` 来获取值 `"lenet"`。
-#### Return *enumeration members*
+#### 返回*枚举成员*
-You can return *enum members* from your *path operation*, even nested in a JSON body (e.g. a `dict`).
+你可以从*路径操作*中返回*枚举成员*,即使嵌套在 JSON 结构中(例如一个 `dict` 中)。
-They will be converted to their corresponding values (strings in this case) before returning them to the client:
+在返回给客户端之前,它们将被转换为对应的值:
```Python hl_lines="18 21 23"
{!../../../docs_src/path_params/tutorial005.py!}
@@ -201,52 +201,52 @@ In your client you will get a JSON response like:
}
```
-## Path parameters containing paths
+## 包含路径的路径参数
-Let's say you have a *path operation* with a path `/files/{file_path}`.
+假设你有一个*路径操作*,它的路径为 `/files/{file_path}`。
-But you need `file_path` itself to contain a *path*, like `home/johndoe/myfile.txt`.
+但是你需要 `file_path` 自身也包含*路径*,比如 `home/johndoe/myfile.txt`。
-So, the URL for that file would be something like: `/files/home/johndoe/myfile.txt`.
+因此,该文件的URL将类似于这样:`/files/home/johndoe/myfile.txt`。
-### OpenAPI support
+### OpenAPI 支持
-OpenAPI doesn't support a way to declare a *path parameter* to contain a *path* inside, as that could lead to scenarios that are difficult to test and define.
+你可以使用直接来自 Starlette 的选项来声明一个包含*路径*的*路径参数*:
-Nevertheless, you can still do it in **FastAPI**, using one of the internal tools from Starlette.
+不过,你仍然可以通过 Starlette 的一个内部工具在 **FastAPI** 中实现它。
-And the docs would still work, although not adding any documentation telling that the parameter should contain a path.
+而且文档依旧可以使用,但是不会添加任何该参数应包含路径的说明。
-### Path convertor
+### 路径转换器
-Using an option directly from Starlette you can declare a *path parameter* containing a *path* using a URL like:
+OpenAPI 不支持任何方式去声明*路径参数*以在其内部包含*路径*,因为这可能会导致难以测试和定义的情况出现。
```
/files/{file_path:path}
```
-In this case, the name of the parameter is `file_path`, and the last part, `:path`, tells it that the parameter should match any *path*.
+在这种情况下,参数的名称为 `file_path`,结尾部分的 `:path` 说明该参数应匹配任意的*路径*。
-So, you can use it with:
+因此,你可以这样使用它:
```Python hl_lines="6"
{!../../../docs_src/path_params/tutorial004.py!}
```
-!!! tip
- You could need the parameter to contain `/home/johndoe/myfile.txt`, with a leading slash (`/`).
+!!! !!! tip
+ 你可能会需要参数包含 `/home/johndoe/myfile.txt`,以斜杠(`/`)开头。
- In that case, the URL would be: `/files//home/johndoe/myfile.txt`, with a double slash (`//`) between `files` and `home`.
+ 在这种情况下,URL 将会是 `/files//home/johndoe/myfile.txt`,在`files` 和 `home` 之间有一个双斜杠(`//`)。
## Recap
-With **FastAPI**, by using short, intuitive and standard Python type declarations, you get:
+使用 **FastAPI**,通过简短、直观和标准的 Python 类型声明,你将获得:
-* Editor support: error checks, autocompletion, etc.
-* Data "parsing"
-* Data validation
-* API annotation and automatic documentation
+* 编辑器支持:错误检查,代码补全等
+* 数据 "解析"
+* 数据校验
+* API 标注和自动生成的文档
-And you only have to declare them once.
+而且你只需要声明一次即可。
-That's probably the main visible advantage of **FastAPI** compared to alternative frameworks (apart from the raw performance).
+这可能是 **FastAPI** 与其他框架相比主要的明显优势(除了原始性能以外)。
From d0ea2653a6a96b1331ca875e3fda5dcf01efc438 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:52 +0800
Subject: [PATCH 147/163] New translations query-params-str-validations.md
(Chinese Simplified)
---
.../tutorial/query-params-str-validations.md | 222 +++++++++---------
1 file changed, 115 insertions(+), 107 deletions(-)
diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md
index 6905626cc983f..15ef418f38a1c 100644
--- a/docs/zh/docs/tutorial/query-params-str-validations.md
+++ b/docs/zh/docs/tutorial/query-params-str-validations.md
@@ -1,8 +1,8 @@
-# Query Parameters and String Validations
+# 查询参数和字符串校验
-**FastAPI** allows you to declare additional information and validation for your parameters.
+**FastAPI** 允许你为参数声明额外的信息和校验。
-Let's take this application as example:
+让我们以下面的应用程序为例:
=== "Python 3.10+"
@@ -16,22 +16,23 @@ Let's take this application as example:
{!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
```
-The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
+!!! note
+ 请记住,在这种情况下 FastAPI 将不会检查列表的内容。
!!! note
FastAPI will know that the value of `q` is not required because of the default value `= None`.
The `Union` in `Union[str, None]` will allow your editor to give you better support and detect errors.
-## Additional validation
+## 额外的校验
-We are going to enforce that even though `q` is optional, whenever it is provided, **its length doesn't exceed 50 characters**.
+我们打算添加约束条件:即使 `q` 是可选的,但只要提供了该参数,则该参数值**不能超过50个字符的长度**。
-### Import `Query` and `Annotated`
+### 导入 `Query`
To achieve that, first import:
-* `Query` from `fastapi`
+* 为此,首先从 `fastapi` 导入 `Query`:
* `Annotated` from `typing` (or from `typing_extensions` in Python below 3.9)
=== "Python 3.10+"
@@ -39,7 +40,7 @@ To achieve that, first import:
In Python 3.9 or above, `Annotated` is part of the standard library, so you can import it from `typing`.
```Python hl_lines="1 3"
- {!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
=== "Python 3.6+"
@@ -59,7 +60,8 @@ To achieve that, first import:
Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} to at least 0.95.1 before using `Annotated`.
-## Use `Annotated` in the type for the `q` parameter
+## !!! tip
+ 要声明类型为 `list` 的查询参数,如上例所示,你需要显式地使用 `Query`,否则该参数将被解释为请求体。
Remember I told you before that `Annotated` can be used to add metadata to your parameters in the [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
@@ -84,7 +86,7 @@ What we will do is wrap that with `Annotated`, so it becomes:
=== "Python 3.10+"
```Python
- q: Annotated[str | None] = None
+ 总结
```
=== "Python 3.6+"
@@ -93,11 +95,11 @@ What we will do is wrap that with `Annotated`, so it becomes:
q: Annotated[Union[str, None]] = None
```
-Both of those versions mean the same thing, `q` is a parameter that can be a `str` or `None`, and by default, it is `None`.
+查询参数 `q` 的类型为 `str`,默认值为 `None`,因此它是可选的。
Now let's jump to the fun stuff. 🎉
-## Add `Query` to `Annotated` in the `q` parameter
+## 但是 `Query` 显式地将其声明为查询参数。
Now that we have this `Annotated` where we can put more metadata, add `Query` to it, and set the parameter `max_length` to 50:
@@ -110,10 +112,11 @@ Now that we have this `Annotated` where we can put more metadata, add `Query` to
=== "Python 3.6+"
```Python hl_lines="10"
- {!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial006d.py!}
```
-Notice that the default value is still `None`, so the parameter is still optional.
+!!! note
+ 具有默认值还会使该参数成为可选参数。
But now, having `Query(max_length=50)` inside of `Annotated`, we are telling FastAPI that we want it to extract this value from the query parameters (this would have been the default anyway 🤷) and that we want to have **additional validation** for this value (that's why we do this, to get the additional validation). 😎
@@ -123,14 +126,14 @@ FastAPI will now:
* Show a **clear error** for the client when the data is not valid
* **Document** the parameter in the OpenAPI schema *path operation* (so it will show up in the **automatic docs UI**)
-## Alternative (old) `Query` as the default value
+## 你可以向 `Query` 的第一个参数传入 `None` 用作查询参数的默认值,以同样的方式你也可以传递其他默认值。
Previous versions of FastAPI (before 0.95.0) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you.
!!! tip
For new code and whenever possible, use `Annotated` as explained above. There are multiple advantages (explained below) and no disadvantages. 🍰
-This is how you would use `Query()` as the default value of your function parameter, setting the parameter `max_length` to 50:
+现在,将 `Query` 用作查询参数的默认值,并将它的 `max_length` 参数设置为 50:
=== "Python 3.10+"
@@ -141,18 +144,18 @@ This is how you would use `Query()` as the default value of your function parame
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
-As in this case (without using `Annotated`) we have to replace the default value `None` in the function with `Query()`, we now need to set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value (at least for FastAPI).
+由于我们必须用 `Query(default=None)` 替换默认值 `None`,`Query` 的第一个参数同样也是用于定义默认值。
-So:
+所以:
```Python
q: Union[str, None] = Query(default=None)
```
-...makes the parameter optional, with a default value of `None`, the same as:
+...使得参数可选,等同于:
```Python
q: Union[str, None] = None
@@ -164,13 +167,13 @@ And in Python 3.10 and above:
q: str | None = Query(default=None)
```
-...makes the parameter optional, with a default value of `None`, the same as:
+有另一种方法可以显式的声明一个值是必需的,即将默认参数的默认值设为 `...` :
```Python
-q: str | None = None
+q: str = None
```
-But it declares it explicitly as being a query parameter.
+声明为必需参数
!!! info
Have in mind that the most important part to make a parameter optional is the part:
@@ -191,17 +194,18 @@ But it declares it explicitly as being a query parameter.
The `Union[str, None]` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
-Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
+然后,我们可以将更多的参数传递给 `Query`。 在本例中,适用于字符串的 `max_length` 参数:
```Python
q: Union[str, None] = Query(default=None, max_length=50)
```
-This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
+将会校验数据,在数据无效时展示清晰的错误信息,并在 OpenAPI 模式的*路径操作*中记录该参数。
-### `Query` as the default value or in `Annotated`
+### 使用 `Query` 作为默认值
-Have in mind that when using `Query` inside of `Annotated` you cannot use the `default` parameter for `Query`.
+!!! tip
+ 请记住,在大多数情况下,当你需要某些东西时,可以简单地省略 `default` 参数,因此你通常不必使用 `...` 或 `Required`
Instead use the actual default value of the function parameter. Otherwise, it would be inconsistent.
@@ -237,9 +241,9 @@ When you don't use `Annotated` and instead use the **(old) default value style**
Because `Annotated` can have more than one metadata annotation, you could now even use the same function with other tools, like Typer. 🚀
-## Add more validations
+## 添加更多校验
-You can also add a parameter `min_length`:
+你还可以添加 `min_length` 参数:
=== "Python 3.10+"
@@ -274,12 +278,12 @@ You can also add a parameter `min_length`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
- {!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial003.py!}
```
-## Add regular expressions
+## 添加正则表达式
-You can define a regular expression `pattern` that the parameter should match:
+你可以定义一个参数值必须匹配的正则表达式:
=== "Python 3.10+"
@@ -305,7 +309,7 @@ You can define a ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial013.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -314,18 +318,18 @@ You can define a ../../../docs_src/query_params_str_validations/tutorial004.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial004.py!}
```
-This specific regular expression pattern checks that the received parameter value:
+这个指定的正则表达式通过以下规则检查接收到的参数值:
-* `^`: starts with the following characters, doesn't have characters before.
-* `fixedquery`: has the exact value `fixedquery`.
-* `$`: ends there, doesn't have any more characters after `fixedquery`.
+* `^`:以该符号之后的字符开头,符号之前没有字符。
+* `fixedquery`: 值精确地等于 `fixedquery`。
+* `$`: 到此结束,在 `fixedquery` 之后没有更多字符。
-If you feel lost with all these **"regular expression"** ideas, don't worry. They are a hard topic for many people. You can still do a lot of stuff without needing regular expressions yet.
+如果你对所有的这些**「正则表达式」**概念感到迷茫,请不要担心。 对于许多人来说这都是一个困难的主题。 你仍然可以在无需正则表达式的情况下做很多事情。
-But whenever you need them and go and learn them, know that you can already use them directly in **FastAPI**.
+但是,一旦你需要用到并去学习它们时,请了解你已经可以在 **FastAPI** 中直接使用它们。
### Pydantic v1 `regex` instead of `pattern`
@@ -341,11 +345,12 @@ You could still see some code using it:
But know that this is deprecated and it should be updated to use the new parameter `pattern`. 🤓
-## Default values
+## 默认值
-You can, of course, use default values other than `None`.
+!!! note
+ 请记住,不同的工具对 OpenAPI 的支持程度可能不同。
-Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
+假设你想要声明查询参数 `q`,使其 `min_length` 为 `3`,并且默认值为 `fixedquery`:
=== "Python 3.9+"
@@ -356,7 +361,7 @@ Let's say that you want to declare the `q` query parameter to have a `min_length
=== "Python 3.6+"
```Python hl_lines="8"
- {!> ../../../docs_src/query_params_str_validations/tutorial005_an.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial005.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -365,7 +370,7 @@ Let's say that you want to declare the `q` query parameter to have a `min_length
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
- {!> ../../../docs_src/query_params_str_validations/tutorial005.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial008.py!}
```
!!! note
@@ -373,19 +378,19 @@ Let's say that you want to declare the `q` query parameter to have a `min_length
## Make it required
-When we don't need to declare more validations or metadata, we can make the `q` query parameter required just by not declaring a default value, like:
+当我们不需要声明额外的校验或元数据时,只需不声明默认值就可以使 `q` 参数成为必需参数,例如:
```Python
q: str
```
-instead of:
+代替:
```Python
q: Union[str, None] = None
```
-But we are now declaring it with `Query`, for example like:
+但是现在我们正在用 `Query` 声明它,例如:
=== "Annotated"
@@ -399,7 +404,7 @@ But we are now declaring it with `Query`, for example like:
q: Union[str, None] = Query(default=None, min_length=3)
```
-So, when you need to declare a value as required while using `Query`, you can simply not declare a default value:
+因此,当你在使用 `Query` 且需要声明一个值是必需的时,只需不声明默认参数:
=== "Python 3.9+"
@@ -410,7 +415,7 @@ So, when you need to declare a value as required while using `Query`, you can si
=== "Python 3.6+"
```Python hl_lines="8"
- {!> ../../../docs_src/query_params_str_validations/tutorial006_an.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial006c.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -419,7 +424,7 @@ So, when you need to declare a value as required while using `Query`, you can si
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
- {!> ../../../docs_src/query_params_str_validations/tutorial006.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial006.py!}
```
@@ -428,7 +433,7 @@ So, when you need to declare a value as required while using `Query`, you can si
Still, probably better to use the `Annotated` version. 😉
-### Required with Ellipsis (`...`)
+### 使用省略号(`...`)声明必需参数
There's an alternative way to explicitly declare that a value is required. You can set the default to the literal value `...`:
@@ -450,21 +455,21 @@ There's an alternative way to explicitly declare that a value is required. You c
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
- {!> ../../../docs_src/query_params_str_validations/tutorial006b.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial006b.py!}
```
-!!! info
- If you hadn't seen that `...` before: it is a special single value, it is part of Python and is called "Ellipsis".
+!!! !!! info
+ 如果你之前没见过 `...` 这种用法:它是一个特殊的单独值,它是 Python 的一部分并且被称为「省略号」。
- It is used by Pydantic and FastAPI to explicitly declare that a value is required.
+ Pydantic 和 FastAPI 使用它来显式的声明需要一个值。
-This will let **FastAPI** know that this parameter is required.
+这将使 **FastAPI** 知道此查询参数是必需的。
-### Required with `None`
+### 使用`None`声明必需参数
-You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`.
+你可以声明一个参数可以接收`None`值,但它仍然是必需的。 这将强制客户端发送一个值,即使该值是`None`。
-To do that, you can declare that `None` is a valid type but still use `...` as the default:
+为此,你可以声明`None`是一个有效的类型,并仍然使用`default=...`:
=== "Python 3.10+"
@@ -505,9 +510,9 @@ To do that, you can declare that `None` is a valid type but still use `...` as t
!!! tip
Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about Required Optional fields.
-### Use Pydantic's `Required` instead of Ellipsis (`...`)
+### 使用Pydantic中的`Required`代替省略号(`...`)
-If you feel uncomfortable using `...`, you can also import and use `Required` from Pydantic:
+如果你觉得使用 `...` 不舒服,你也可以从 Pydantic 导入并使用 `Required`:
=== "Python 3.9+"
@@ -533,11 +538,11 @@ If you feel uncomfortable using `...`, you can also import and use `Required` fr
!!! tip
Remember that in most of the cases, when something is required, you can simply omit the default, so you normally don't have to use `...` nor `Required`.
-## Query parameter list / multiple values
+## 查询参数列表 / 多个值
-When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values.
+当你使用 `Query` 显式地定义查询参数时,你还可以声明它去接收一组值,或换句话来说,接收多个值。
-For example, to declare a query parameter `q` that can appear multiple times in the URL, you can write:
+例如,要声明一个可在 URL 中出现多次的查询参数 `q`,你可以这样写:
=== "Python 3.10+"
@@ -554,8 +559,11 @@ For example, to declare a query parameter `q` that can appear multiple times in
=== "Python 3.6+"
```Python hl_lines="10"
- {!> ../../../docs_src/query_params_str_validations/tutorial011_an.py!}
+ !!! tip
+ Pydantic 是 FastAPI 中所有数据验证和序列化的核心,当你在没有设默认值的情况下使用 Optional 或 Union[Something, None] 时,它具有特殊行为,你可以在 Pydantic 文档中阅读有关必需可选字段的更多信息。
```
+ 或 Union[Something, None] 时,它具有特殊行为,你可以在 Pydantic 文档中阅读有关必需可选字段的更多信息。
+
=== "Python 3.10+ non-Annotated"
@@ -581,18 +589,18 @@ For example, to declare a query parameter `q` that can appear multiple times in
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial011.py!}
```
-Then, with a URL like:
+然后,输入如下网址:
```
http://localhost:8000/items/?q=foo&q=bar
```
-you would receive the multiple `q` *query parameters'* values (`foo` and `bar`) in a Python `list` inside your *path operation function*, in the *function parameter* `q`.
+你会在*路径操作函数*的*函数参数* `q` 中以一个 Python `list` 的形式接收到*查询参数* `q` 的多个值(`foo` 和 `bar`)。
-So, the response to that URL would be:
+因此,该 URL 的响应将会是:
```JSON
{
@@ -606,13 +614,13 @@ So, the response to that URL would be:
!!! tip
To declare a query parameter with a type of `list`, like in the example above, you need to explicitly use `Query`, otherwise it would be interpreted as a request body.
-The interactive API docs will update accordingly, to allow multiple values:
+交互式 API 文档将会相应地进行更新,以允许使用多个值:
-### Query parameter list / multiple values with defaults
+### 具有默认值的查询参数列表 / 多个值
-And you can also define a default `list` of values if none are provided:
+你还可以定义在没有任何给定值时的默认 `list` 值:
=== "Python 3.9+"
@@ -641,16 +649,16 @@ And you can also define a default `list` of values if none are provided:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial012.py!}
```
-If you go to:
+如果你访问:
```
http://localhost:8000/items/
```
-the default of `q` will be: `["foo", "bar"]` and your response will be:
+`q` 的默认值将为:`["foo", "bar"]`,你的响应会是:
```JSON
{
@@ -661,9 +669,9 @@ the default of `q` will be: `["foo", "bar"]` and your response will be:
}
```
-#### Using `list`
+#### 使用 `list`
-You can also use `list` directly instead of `List[str]` (or `list[str]` in Python 3.9+):
+你也可以直接使用 `list` 代替 `List [str]`:
=== "Python 3.9+"
@@ -689,20 +697,20 @@ You can also use `list` directly instead of `List[str]` (or `list[str]` in Pytho
!!! note
Have in mind that in this case, FastAPI won't check the contents of the list.
- For example, `List[int]` would check (and document) that the contents of the list are integers. But `list` alone wouldn't.
+ 例如,`List[int]` 将检查(并记录到文档)列表的内容必须是整数。 但是单独的 `list` 不会。
-## Declare more metadata
+## 声明更多元数据
-You can add more information about the parameter.
+你可以添加更多有关该参数的信息。
-That information will be included in the generated OpenAPI and used by the documentation user interfaces and external tools.
+这些信息将包含在生成的 OpenAPI 模式中,并由文档用户界面和外部工具所使用。
!!! note
Have in mind that different tools might have different levels of OpenAPI support.
- Some of them might not show all the extra information declared yet, although in most of the cases, the missing feature is already planned for development.
+ 其中一些可能不会展示所有已声明的额外信息,尽管在大多数情况下,缺少的这部分功能已经计划进行开发。
-You can add a `title`:
+你可以添加 `title`:
=== "Python 3.10+"
@@ -719,7 +727,7 @@ You can add a `title`:
=== "Python 3.6+"
```Python hl_lines="11"
- {!> ../../../docs_src/query_params_str_validations/tutorial007_an.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial007.py!}
```
=== "Python 3.10+ non-Annotated"
@@ -740,7 +748,7 @@ You can add a `title`:
{!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
```
-And a `description`:
+以及 `description`:
=== "Python 3.10+"
@@ -775,26 +783,26 @@ And a `description`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="13"
- {!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial001.py!}
```
-## Alias parameters
+## 别名参数
-Imagine that you want the parameter to be `item-query`.
+假设你想要查询参数为 `item-query`。
-Like in:
+像下面这样:
```
http://127.0.0.1:8000/items/?item-query=foobaritems
```
-But `item-query` is not a valid Python variable name.
+但是 `item-query` 不是一个有效的 Python 变量名称。
-The closest would be `item_query`.
+最接近的有效名称是 `item_query`。
-But you still need it to be exactly `item-query`...
+但是你仍然要求它在 URL 中必须是 `item-query`...
-Then you can declare an `alias`, and that alias is what will be used to find the parameter value:
+这时你可以用 `alias` 参数声明一个别名,该别名将用于在 URL 中查找查询参数值:
=== "Python 3.10+"
@@ -829,16 +837,16 @@ Then you can declare an `alias`, and that alias is what will be used to find the
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
- {!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial009.py!}
```
-## Deprecating parameters
+## 弃用参数
-Now let's say you don't like this parameter anymore.
+现在假设你不再喜欢此参数。
-You have to leave it there a while because there are clients using it, but you want the docs to clearly show it as deprecated.
+你不得不将其保留一段时间,因为有些客户端正在使用它,但你希望文档清楚地将其展示为已弃用。
-Then pass the parameter `deprecated=True` to `Query`:
+那么将参数 `deprecated=True` 传入 `Query`:
=== "Python 3.10+"
@@ -873,10 +881,10 @@ Then pass the parameter `deprecated=True` to `Query`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="18"
- {!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
+ {!../../../docs_src/query_params_str_validations/tutorial010.py!}
```
-The docs will show it like this:
+文档将会像下面这样展示它:
@@ -922,21 +930,21 @@ To exclude a query parameter from the generated OpenAPI schema (and thus, from t
## Recap
-You can declare additional validations and metadata for your parameters.
+你可以为查询参数声明额外的校验和元数据。
-Generic validations and metadata:
+通用的校验和元数据:
* `alias`
* `title`
* `description`
* `deprecated`
-Validations specific for strings:
+特定于字符串的校验:
* `min_length`
* `max_length`
* `regex`
-In these examples you saw how to declare validations for `str` values.
+在这些示例中,你了解了如何声明对 `str` 值的校验。
-See the next chapters to see how to declare validations for other types, like numbers.
+请参阅下一章节,以了解如何声明对其他类型例如数值的校验。
From 2e9036321e5104852a552967df87fc61df8e52f5 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:53 +0800
Subject: [PATCH 148/163] New translations query-params.md (Chinese Simplified)
---
docs/zh/docs/tutorial/query-params.md | 122 ++++++++++++++------------
1 file changed, 64 insertions(+), 58 deletions(-)
diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md
index 0b74b10f81c8c..dead131d45f8e 100644
--- a/docs/zh/docs/tutorial/query-params.md
+++ b/docs/zh/docs/tutorial/query-params.md
@@ -1,42 +1,42 @@
-# Query Parameters
+# 查询参数
-When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.
+声明不属于路径参数的其他函数参数时,它们将被自动解释为"查询字符串"参数
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
-The query is the set of key-value pairs that go after the `?` in a URL, separated by `&` characters.
+查询字符串是键值对的集合,这些键值对位于 URL 的 `? ` 之后,并以 `&` 符号分隔。
-For example, in the URL:
+例如,在以下 url 中:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
-...the query parameters are:
+...查询参数为:
-* `skip`: with a value of `0`
-* `limit`: with a value of `10`
+* `skip`:对应的值为 `0`
+* `limit`:对应的值为 `10`
-As they are part of the URL, they are "naturally" strings.
+由于它们是 URL 的一部分,因此它们的"原始值"是字符串。
-But when you declare them with Python types (in the example above, as `int`), they are converted to that type and validated against it.
+但是,当你为它们声明了 Python 类型(在上面的示例中为 `int`)时,它们将转换为该类型并针对该类型进行校验。
-All the same process that applied for path parameters also applies for query parameters:
+应用于路径参数的所有相同过程也适用于查询参数:
-* Editor support (obviously)
-* Data "parsing"
-* Data validation
-* Automatic documentation
+* (很明显的)编辑器支持
+* 数据"解析"
+* 数据校验
+* 自动生成文档
-## Defaults
+## 默认值
-As query parameters are not a fixed part of a path, they can be optional and can have default values.
+由于查询参数不是路径的固定部分,因此它们可以是可选的,并且可以有默认值。
-In the example above they have default values of `skip=0` and `limit=10`.
+在上面的示例中,它们具有 `skip=0` 和 `limit=10` 的默认值。
-So, going to the URL:
+因此,访问 URL:
```
http://127.0.0.1:8000/items/
@@ -48,94 +48,97 @@ would be the same as going to:
http://127.0.0.1:8000/items/?skip=0&limit=10
```
-But if you go to, for example:
+但是,如果你访问的是:
```
http://127.0.0.1:8000/items/?skip=20
```
-The parameter values in your function will be:
+函数中的参数值将会是:
-* `skip=20`: because you set it in the URL
-* `limit=10`: because that was the default value
+* `skip=20`:在 URL 中设定的值
+* `limit=10`:使用默认值
-## Optional parameters
+## 可选参数
-The same way, you can declare optional query parameters, by setting their default to `None`:
+通过同样的方式,你可以将它们的默认值设置为 `None` 来声明可选查询参数:
=== "Python 3.10+"
```Python hl_lines="7"
- {!> ../../../docs_src/query_params/tutorial002_py310.py!}
+ 将与访问以下地址相同:
```
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params/tutorial002.py!}
+ {!../../../docs_src/query_params/tutorial002.py!}
```
-In this case, the function parameter `q` will be optional, and will be `None` by default.
+在这个例子中,函数参数 `q` 将是可选的,并且默认值为 `None`。
!!! check
Also notice that **FastAPI** is smart enough to notice that the path parameter `item_id` is a path parameter and `q` is not, so, it's a query parameter.
-## Query parameter type conversion
+## 查询参数类型转换
-You can also declare `bool` types, and they will be converted:
+你还可以声明 `bool` 类型,它们将被自动转换:
=== "Python 3.10+"
```Python hl_lines="7"
- {!> ../../../docs_src/query_params/tutorial003_py310.py!}
+ {!../../../docs_src/query_params/tutorial003.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
- {!> ../../../docs_src/query_params/tutorial003.py!}
+ !!! check
+ 还要注意的是,FastAPI 足够聪明,能够分辨出参数 item_id 是路径参数而 q 不是,因此 q 是一个查询参数。
```
+ 是路径参数而 q 不是,因此 q 是一个查询参数。
+
-In this case, if you go to:
+这个例子中,如果你访问:
```
http://127.0.0.1:8000/items/foo?short=1
```
-or
+或
```
http://127.0.0.1:8000/items/foo?short=True
```
-or
+或
```
http://127.0.0.1:8000/items/foo?short=true
```
-or
+或
```
http://127.0.0.1:8000/items/foo?short=on
```
-or
+或
```
http://127.0.0.1:8000/items/foo?short=yes
```
-or any other case variation (uppercase, first letter in uppercase, etc), your function will see the parameter `short` with a `bool` value of `True`. Otherwise as `False`.
+或任何其他的变体形式(大写,首字母大写等等),你的函数接收的 `short` 参数都会是布尔值 `True`。 对于值为 `False` 的情况也是一样的。
-## Multiple path and query parameters
+## 多个路径和查询参数
-You can declare multiple path parameters and query parameters at the same time, **FastAPI** knows which is which.
+你可以同时声明多个路径参数和查询参数,**FastAPI** 能够识别它们。
-And you don't have to declare them in any specific order.
+而且你不需要以任何特定的顺序来声明。
-They will be detected by name:
+它们将通过名称被检测到:
=== "Python 3.10+"
@@ -146,30 +149,30 @@ They will be detected by name:
=== "Python 3.6+"
```Python hl_lines="8 10"
- {!> ../../../docs_src/query_params/tutorial004.py!}
+ {!../../../docs_src/query_params/tutorial004.py!}
```
-## Required query parameters
+## 必需查询参数
-When you declare a default value for non-path parameters (for now, we have only seen query parameters), then it is not required.
+当你为非路径参数声明了默认值时(目前而言,我们所知道的仅有查询参数),则该参数不是必需的。
-If you don't want to add a specific value but just make it optional, set the default as `None`.
+如果你不想添加一个特定的值,而只是想使该参数成为可选的,则将默认值设置为 `None`。
-But when you want to make a query parameter required, you can just not declare any default value:
+但当你想让一个查询参数成为必需的,不声明任何默认值就可以:
```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
-Here the query parameter `needy` is a required query parameter of type `str`.
+这里的查询参数 `needy` 是类型为 `str` 的必需查询参数。
-If you open in your browser a URL like:
+如果你在浏览器中打开一个像下面的 URL:
```
http://127.0.0.1:8000/items/foo-item
```
-...without adding the required parameter `needy`, you will see an error like:
+...因为没有添加必需的参数 `needy`,你将看到类似以下的错误:
```JSON
{
@@ -186,13 +189,13 @@ http://127.0.0.1:8000/items/foo-item
}
```
-As `needy` is a required parameter, you would need to set it in the URL:
+由于 `needy` 是必需参数,因此你需要在 URL 中设置它的值:
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
-...this would work:
+...这样就正常了:
```JSON
{
@@ -201,25 +204,28 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
}
```
-And of course, you can define some parameters as required, some as having a default value, and some entirely optional:
+当然,你也可以定义一些参数为必需的,一些具有默认值,而某些则完全是可选的:
=== "Python 3.10+"
```Python hl_lines="8"
- {!> ../../../docs_src/query_params/tutorial006_py310.py!}
+ {!../../../docs_src/query_params/tutorial006.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
- {!> ../../../docs_src/query_params/tutorial006.py!}
+ !!! tip
+ 你还可以像在 路径参数{.internal-link target=_blank} 中那样使用 Enum。
```
+。
+
-In this case, there are 3 query parameters:
+在这个例子中,有3个查询参数:
-* `needy`, a required `str`.
-* `skip`, an `int` with a default value of `0`.
-* `limit`, an optional `int`.
+* `needy`,一个必需的 `str` 类型参数。
+* `skip`,一个默认值为 `0` 的 `int` 类型参数。
+* `limit`,一个可选的 `int` 类型参数。
!!! tip
You could also use `Enum`s the same way as with [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
From aa73a0eb510060f2f9cfd0588654a442aba608b4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:55 +0800
Subject: [PATCH 149/163] New translations request-files.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/request-files.md | 156 ++++++++++++-------------
1 file changed, 78 insertions(+), 78 deletions(-)
diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md
index d2d649924f859..cf5d05139c827 100644
--- a/docs/zh/docs/tutorial/request-files.md
+++ b/docs/zh/docs/tutorial/request-files.md
@@ -1,28 +1,28 @@
-# Request Files
+# 请求文件
-You can define files to be uploaded by the client using `File`.
+`File` 用于定义客户端的上传文件。
!!! info
To receive uploaded files, first install `python-multipart`.
- E.g. `pip install python-multipart`.
+ E.g. 例如: `pip install python-multipart`。
- This is because uploaded files are sent as "form data".
+ 因为上传文件以「表单数据」形式发送。
-## Import `File`
+## 导入 `File`
-Import `File` and `UploadFile` from `fastapi`:
+从 `fastapi` 导入 `File` 和 `UploadFile`:
=== "Python 3.9+"
```Python hl_lines="3"
- {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ !!! info "说明"
```
=== "Python 3.6+"
```Python hl_lines="1"
- {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ FastAPI 支持同时上传多个文件。
```
=== "Python 3.6+ non-Annotated"
@@ -31,23 +31,23 @@ Import `File` and `UploadFile` from `fastapi`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
- {!> ../../../docs_src/request_files/tutorial001.py!}
+ {!../../../docs_src/request_files/tutorial001.py!}
```
-## Define `File` Parameters
+## 定义 `File` 参数
-Create file parameters the same way you would for `Body` or `Form`:
+创建文件(`File`)参数的方式与 `Body` 和 `Form` 一样:
=== "Python 3.9+"
```Python hl_lines="9"
- {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ !!! info "说明"
```
=== "Python 3.6+"
```Python hl_lines="8"
- {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ 使用 `async` 方法时,**FastAPI** 在线程池中执行文件方法,并 `await` 操作完成。
```
=== "Python 3.6+ non-Annotated"
@@ -56,39 +56,38 @@ Create file parameters the same way you would for `Body` or `Form`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
- {!> ../../../docs_src/request_files/tutorial001.py!}
+ {!../../../docs_src/request_files/tutorial001.py!}
```
-!!! info
- `File` is a class that inherits directly from `Form`.
+!!! `File` 是直接继承自 `Form` 的类。
- But remember that when you import `Query`, `Path`, `File` and others from `fastapi`, those are actually functions that return special classes.
+ 注意,从 `fastapi` 导入的 `Query`、`Path`、`File` 等项,实际上是返回特定类的函数。
!!! tip
To declare File bodies, you need to use `File`, because otherwise the parameters would be interpreted as query parameters or body (JSON) parameters.
-The files will be uploaded as "form data".
+文件作为「表单数据」上传。
-If you declare the type of your *path operation function* parameter as `bytes`, **FastAPI** will read the file for you and you will receive the contents as `bytes`.
+如果把*路径操作函数*参数的类型声明为 `bytes`,**FastAPI** 将以 `bytes` 形式读取和接收文件内容。
Have in mind that this means that the whole contents will be stored in memory. This will work well for small files.
-But there are several cases in which you might benefit from using `UploadFile`.
+不过,很多情况下,`UploadFile` 更好用。
-## File Parameters with `UploadFile`
+## 含 `UploadFile` 的文件参数
-Define a file parameter with a type of `UploadFile`:
+定义文件参数时使用 `UploadFile`:
=== "Python 3.9+"
```Python hl_lines="14"
- {!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
+ !!! note "技术细节"
```
=== "Python 3.6+"
```Python hl_lines="13"
- {!> ../../../docs_src/request_files/tutorial001_an.py!}
+ 声明文件体必须使用 `File`,否则,FastAPI 会把该参数当作查询参数或请求体(JSON)参数。
```
=== "Python 3.6+ non-Annotated"
@@ -97,45 +96,45 @@ Define a file parameter with a type of `UploadFile`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="12"
- {!> ../../../docs_src/request_files/tutorial001.py!}
+ {!../../../docs_src/request_files/tutorial001.py!}
```
-Using `UploadFile` has several advantages over `bytes`:
+`UploadFile` 与 `bytes` 相比有更多优势:
-* You don't have to use `File()` in the default value of the parameter.
-* It uses a "spooled" file:
- * A file stored in memory up to a maximum size limit, and after passing this limit it will be stored in disk.
-* This means that it will work well for large files like images, videos, large binaries, etc. without consuming all the memory.
-* You can get metadata from the uploaded file.
-* It has a file-like `async` interface.
-* It exposes an actual Python `SpooledTemporaryFile` object that you can pass directly to other libraries that expect a file-like object.
+* 本节介绍了如何用 `File` 把上传文件声明为(表单数据的)输入参数。
+* 使用 `spooled` 文件:
+ * 存储在内存的文件超出最大上限时,FastAPI 会把文件存入磁盘;
+* 这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;
+* 可获取上传文件的元数据;
+* 暴露的 Python `SpooledTemporaryFile` 对象,可直接传递给其他预期「file-like」对象的库。
+* 自带 file-like `async` 接口;
### `UploadFile`
-`UploadFile` has the following attributes:
+`UploadFile` 的属性如下:
-* `filename`: A `str` with the original file name that was uploaded (e.g. `myimage.jpg`).
-* `content_type`: A `str` with the content type (MIME type / media type) (e.g. `image/jpeg`).
-* `file`: A `SpooledTemporaryFile` (a file-like object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
+* `filename`:上传文件名字符串(`str`),例如, `myimage.jpg`;
+* `content_type`:内容类型(MIME 类型 / 媒体类型)字符串(`str`),例如,`image/jpeg`;
+* `file`: `SpooledTemporaryFile`( file-like 对象)。 其实就是 Python文件,可直接传递给其他预期 `file-like` 对象的函数或支持库。
`UploadFile` has the following `async` methods. They all call the corresponding file methods underneath (using the internal `SpooledTemporaryFile`).
-* `write(data)`: Writes `data` (`str` or `bytes`) to the file.
-* `read(size)`: Reads `size` (`int`) bytes/characters of the file.
-* `seek(offset)`: Goes to the byte position `offset` (`int`) in the file.
- * E.g., `await myfile.seek(0)` would go to the start of the file.
- * This is especially useful if you run `await myfile.read()` once and then need to read the contents again.
-* `close()`: Closes the file.
+* `write(data)`:把 `data` (`str` 或 `bytes`)写入文件;
+* `read(size)`:按指定数量的字节或字符(`size` (`int`))读取文件内容;
+* `seek(offset)`:移动至文件 `offset` (`int`)字节处的位置;
+ * 例如,`await myfile.seek(0)` 移动到文件开头;
+ * 执行 `await myfile.read()` 后,需再次读取已读取内容时,这种方法特别好用;
+* `close()`:关闭文件。
-As all these methods are `async` methods, you need to "await" them.
+因为上述方法都是 `async` 方法,要搭配「await」使用。
-For example, inside of an `async` *path operation function* you can get the contents with:
+例如,在 `async` *路径操作函数* 内,要用以下方式读取文件内容:
```Python
contents = await myfile.read()
```
-If you are inside of a normal `def` *path operation function*, you can access the `UploadFile.file` directly, for example:
+在普通 `def` *路径操作函数* 内,则可以直接访问 `UploadFile.file`,例如:
```Python
contents = myfile.file.read()
@@ -146,45 +145,45 @@ contents = myfile.file.read()
!!! note "Starlette Technical Details"
**FastAPI**'s `UploadFile` inherits directly from **Starlette**'s `UploadFile`, but adds some necessary parts to make it compatible with **Pydantic** and the other parts of FastAPI.
-## What is "Form Data"
+## 什么是 「表单数据」
-The way HTML forms (``) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON.
+与 JSON 不同,HTML 表单(``)向服务器发送数据通常使用「特殊」的编码。
-**FastAPI** will make sure to read that data from the right place instead of JSON.
+**FastAPI** 要确保从正确的位置读取数据,而不是读取 JSON。
-!!! note "Technical Details"
- Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded` when it doesn't include files.
+!!! 不包含文件时,表单数据一般用 `application/x-www-form-urlencoded`「媒体类型」编码。
- But when the form includes files, it is encoded as `multipart/form-data`. If you use `File`, **FastAPI** will know it has to get the files from the correct part of the body.
+ 但表单包含文件时,编码为 `multipart/form-data`。 使用了 `File`,**FastAPI** 就知道要从请求体的正确位置获取文件。
- If you want to read more about these encodings and form fields, head to the MDN web docs for POST.
+ 编码和表单字段详见 MDN Web 文档的 POST 小节。
-!!! warning
- You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
+!!! 可在一个*路径操作*中声明多个 `File` 和 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。 因为此时请求体的编码是 `multipart/form-data`,不是 `application/json`。
- This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
+ 这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
-## Optional File Upload
+## 可选文件上传
-You can make a file optional by using standard type annotations and setting a default value of `None`:
+您可以通过使用标准类型注解并将 None 作为默认值的方式将一个文件参数设为可选:
=== "Python 3.10+"
```Python hl_lines="9 17"
- {!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
+ 这种方式把文件的所有内容都存储在内存里,适用于小型文件。
```
=== "Python 3.9+"
```Python hl_lines="9 17"
- {!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
+ !!! warning "警告"
```
=== "Python 3.6+"
```Python hl_lines="10 18"
- {!> ../../../docs_src/request_files/tutorial001_02_an.py!}
+ !!! note "async 技术细节"
```
+ 技术细节"
+
=== "Python 3.10+ non-Annotated"
@@ -204,20 +203,20 @@ You can make a file optional by using standard type annotations and setting a de
{!> ../../../docs_src/request_files/tutorial001_02.py!}
```
-## `UploadFile` with Additional Metadata
+## 带有额外元数据的 `UploadFile`
-You can also use `File()` with `UploadFile`, for example, to set additional metadata:
+您也可以将 `File()` 与 `UploadFile` 一起使用,例如,设置额外的元数据:
=== "Python 3.9+"
```Python hl_lines="9 15"
- {!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
+ !!! tip "提示"
```
=== "Python 3.6+"
```Python hl_lines="8 14"
- {!> ../../../docs_src/request_files/tutorial001_03_an.py!}
+ **FastAPI** 的 `UploadFile` 直接继承自 **Starlette** 的 `UploadFile`,但添加了一些必要功能,使之与 **Pydantic** 及 FastAPI 的其它部件兼容。
```
=== "Python 3.6+ non-Annotated"
@@ -226,28 +225,30 @@ You can also use `File()` with `UploadFile`, for example, to set additional meta
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7 13"
- {!> ../../../docs_src/request_files/tutorial001_03.py!}
+ 可用同一个「表单字段」发送含多个文件的「表单数据」。
```
-## Multiple File Uploads
+## 多文件上传
It's possible to upload several files at the same time.
They would be associated to the same "form field" sent using "form data".
-To use that, declare a list of `bytes` or `UploadFile`:
+上传多个文件时,要声明含 `bytes` 或 `UploadFile` 的列表(`List`):
=== "Python 3.9+"
```Python hl_lines="10 15"
- {!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
+ !!! note "Starlette 技术细节"
```
=== "Python 3.6+"
```Python hl_lines="11 16"
- {!> ../../../docs_src/request_files/tutorial002_an.py!}
+ UploadFile 支持以下 async 方法,(使用内部 SpooledTemporaryFile)可调用相应的文件方法。
```
+ 支持以下 async 方法,(使用内部 SpooledTemporaryFile)可调用相应的文件方法。
+
=== "Python 3.9+ non-Annotated"
@@ -267,27 +268,26 @@ To use that, declare a list of `bytes` or `UploadFile`:
{!> ../../../docs_src/request_files/tutorial002.py!}
```
-You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
+接收的也是含 `bytes` 或 `UploadFile` 的列表(`list`)。
-!!! note "Technical Details"
- You could also use `from starlette.responses import HTMLResponse`.
+!!! 也可以使用 `from starlette.responses import HTMLResponse`。
- **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+ `fastapi.responses` 其实与 `starlette.responses` 相同,只是为了方便开发者调用。 实际上,大多数 **FastAPI** 的响应都直接从 Starlette 调用。 But most of the available responses come directly from Starlette.
-### Multiple File Uploads with Additional Metadata
+### 带有额外元数据的多文件上传
-And the same way as before, you can use `File()` to set additional parameters, even for `UploadFile`:
+和之前的方式一样, 您可以为 `File()` 设置额外参数, 即使是 `UploadFile`:
=== "Python 3.9+"
```Python hl_lines="11 18-20"
- {!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
+ !!! note "技术细节"
```
=== "Python 3.6+"
```Python hl_lines="12 19-21"
- {!> ../../../docs_src/request_files/tutorial003_an.py!}
+ {!../../../docs_src/request_files/tutorial001_03.py!}
```
=== "Python 3.9+ non-Annotated"
From 923cceb2be36162296331baebc60b888a0001e64 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:56 +0800
Subject: [PATCH 150/163] New translations request-forms-and-files.md (Chinese
Simplified)
---
.../docs/tutorial/request-forms-and-files.md | 36 +++++++++----------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/docs/zh/docs/tutorial/request-forms-and-files.md b/docs/zh/docs/tutorial/request-forms-and-files.md
index 1818946c4e087..6dc779760bfbf 100644
--- a/docs/zh/docs/tutorial/request-forms-and-files.md
+++ b/docs/zh/docs/tutorial/request-forms-and-files.md
@@ -1,18 +1,17 @@
-# Request Forms and Files
+# 请求表单与文件
-You can define files and form fields at the same time using `File` and `Form`.
+FastAPI 支持同时使用 `File` 和 `Form` 定义文件和表单字段。
-!!! info
- To receive uploaded files and/or form data, first install `python-multipart`.
+!!! 接收上传文件或表单数据,要预先安装 <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>。
- E.g. `pip install python-multipart`.
+ E.g. 例如,`pip install python-multipart`。
-## Import `File` and `Form`
+## 导入 `File` 与 `Form`
=== "Python 3.9+"
```Python hl_lines="3"
- {!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
+ !!! warning "警告"
```
=== "Python 3.6+"
@@ -27,23 +26,23 @@ You can define files and form fields at the same time using `File` and `Form`.
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
- {!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
+ {!../../../docs_src/request_forms_and_files/tutorial001.py!}
```
-## Define `File` and `Form` parameters
+## 定义 `File` 与 `Form` 参数
-Create file and form parameters the same way you would for `Body` or `Query`:
+创建文件和表单参数的方式与 `Body` 和 `Query` 一样:
=== "Python 3.9+"
```Python hl_lines="10-12"
- {!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
+ 小结
```
=== "Python 3.6+"
```Python hl_lines="9-11"
- {!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
+ !!! info "说明"
```
=== "Python 3.6+ non-Annotated"
@@ -52,18 +51,17 @@ Create file and form parameters the same way you would for `Body` or `Query`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
- {!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
+ {!../../../docs_src/request_forms_and_files/tutorial001.py!}
```
-The files and form fields will be uploaded as form data and you will receive the files and form fields.
+文件和表单字段作为表单数据上传与接收。
-And you can declare some of the files as `bytes` and some as `UploadFile`.
+声明文件可以使用 `bytes` 或 `UploadFile` 。
-!!! warning
- You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
+!!! 可在一个*路径操作*中声明多个 `File` 与 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。 因为此时请求体的编码为 `multipart/form-data`,不是 `application/json`。
- This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
+ 这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
## Recap
-Use `File` and `Form` together when you need to receive data and files in the same request.
+在同一个请求中接收数据和文件时,应同时使用 `File` 和 `Form`。
From 6b3d210d2212a6331824e1e0d83f51fa71be5919 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:57 +0800
Subject: [PATCH 151/163] New translations request-forms.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/request-forms.md | 55 ++++++++++++--------------
1 file changed, 26 insertions(+), 29 deletions(-)
diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md
index 1a608f33f5a3b..06300fee297d5 100644
--- a/docs/zh/docs/tutorial/request-forms.md
+++ b/docs/zh/docs/tutorial/request-forms.md
@@ -1,26 +1,25 @@
-# Form Data
+# 表单数据
-When you need to receive form fields instead of JSON, you can use `Form`.
+接收的不是 JSON,而是表单字段时,要使用 `Form`。
-!!! info
- To use forms, first install `python-multipart`.
+!!! 要使用表单,需预先安装 <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>。
- E.g. `pip install python-multipart`.
+ E.g. 例如,`pip install python-multipart`。
-## Import `Form`
+## 导入 `Form`
-Import `Form` from `fastapi`:
+从 `fastapi` 导入 `Form`:
=== "Python 3.9+"
```Python hl_lines="3"
- {!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
+ !!! tip "提示"
```
=== "Python 3.6+"
```Python hl_lines="1"
- {!> ../../../docs_src/request_forms/tutorial001_an.py!}
+ `Form` 是直接继承自 `Body` 的类。
```
=== "Python 3.6+ non-Annotated"
@@ -29,23 +28,23 @@ Import `Form` from `fastapi`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
- {!> ../../../docs_src/request_forms/tutorial001.py!}
+ {!../../../docs_src/request_forms/tutorial001.py!}
```
-## Define `Form` parameters
+## 定义 `Form` 参数
-Create form parameters the same way you would for `Body` or `Query`:
+创建表单(`Form`)参数的方式与 `Body` 和 `Query` 一样:
=== "Python 3.9+"
```Python hl_lines="9"
- {!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
+ !!! info "说明"
```
=== "Python 3.6+"
```Python hl_lines="8"
- {!> ../../../docs_src/request_forms/tutorial001_an.py!}
+ 声明表单体要显式使用 `Form` ,否则,FastAPI 会把该参数当作查询参数或请求体(JSON)参数。
```
=== "Python 3.6+ non-Annotated"
@@ -54,14 +53,14 @@ Create form parameters the same way you would for `Body` or `Query`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
- {!> ../../../docs_src/request_forms/tutorial001.py!}
+ {!../../../docs_src/request_forms/tutorial001.py!}
```
-For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields.
+例如,OAuth2 规范的 "密码流" 模式规定要通过表单字段发送 `username` 和 `password`。
-The spec requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON.
+该规范要求字段必须命名为 `username` 和 `password`,并通过表单字段发送,不能用 JSON。
-With `Form` you can declare the same configurations as with `Body` (and `Query`, `Path`, `Cookie`), including validation, examples, an alias (e.g. `user-name` instead of `username`), etc.
+使用 `Form` 可以声明与 `Body` (及 `Query`、`Path`、`Cookie`)相同的元数据和验证。
!!! info
`Form` is a class that inherits directly from `Body`.
@@ -69,24 +68,22 @@ With `Form` you can declare the same configurations as with `Body` (and `Query`,
!!! tip
To declare form bodies, you need to use `Form` explicitly, because without it the parameters would be interpreted as query parameters or body (JSON) parameters.
-## About "Form Fields"
+## 关于 "表单字段"
-The way HTML forms (``) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON.
+与 JSON 不同,HTML 表单(``)向服务器发送数据通常使用「特殊」的编码。
-**FastAPI** will make sure to read that data from the right place instead of JSON.
+**FastAPI** 要确保从正确的位置读取数据,而不是读取 JSON。
-!!! note "Technical Details"
- Data from forms is normally encoded using the "media type" `application/x-www-form-urlencoded`.
+!!! 表单数据的「媒体类型」编码一般为 `application/x-www-form-urlencoded`。
- But when the form includes files, it is encoded as `multipart/form-data`. You'll read about handling files in the next chapter.
+ 但包含文件的表单编码为 `multipart/form-data`。 You'll read about handling files in the next chapter.
- If you want to read more about these encodings and form fields, head to the MDN web docs for POST.
+ 编码和表单字段详见 MDN Web 文档的 POST小节。
-!!! warning
- You can declare multiple `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `application/x-www-form-urlencoded` instead of `application/json`.
+!!! 可在一个*路径操作*中声明多个 `Form` 参数,但不能同时声明要接收 JSON 的 `Body` 字段。 因为此时请求体的编码是 `application/x-www-form-urlencoded`,不是 `application/json`。
- This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
+ 这不是 **FastAPI** 的问题,而是 HTTP 协议的规定。
## Recap
-Use `Form` to declare form data input parameters.
+本节介绍了如何使用 `Form` 声明表单数据输入参数。
From a319c7bdd2bd8749bfb672d280027ab38b8635d4 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:58 +0800
Subject: [PATCH 152/163] New translations response-model.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/response-model.md | 157 +++++++++++++-----------
1 file changed, 82 insertions(+), 75 deletions(-)
diff --git a/docs/zh/docs/tutorial/response-model.md b/docs/zh/docs/tutorial/response-model.md
index 9c849bf3a0453..121d6543453e4 100644
--- a/docs/zh/docs/tutorial/response-model.md
+++ b/docs/zh/docs/tutorial/response-model.md
@@ -1,6 +1,6 @@
-# Response Model - Return Type
+# 响应模型
-You can declare the type used for the response by annotating the *path operation function* **return type**.
+你可以在任意的*路径操作*中使用 `response_model` 参数来声明用于响应的模型:
You can use **type annotations** the same way you would for input data in function **parameters**, you can use Pydantic models, lists, dictionaries, scalar values like integers, booleans, etc.
@@ -13,7 +13,7 @@ You can use **type annotations** the same way you would for input data in functi
=== "Python 3.9+"
```Python hl_lines="18 23"
- {!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
+ https://fastapi.tiangolo.com/img/tutorial/response-model/image02.png
```
=== "Python 3.6+"
@@ -22,20 +22,22 @@ You can use **type annotations** the same way you would for input data in functi
{!> ../../../docs_src/response_model/tutorial001_01.py!}
```
-FastAPI will use this return type to:
+!!! info
+ 你还可以使用:
* **Validate** the returned data.
* If the data is invalid (e.g. you are missing a field), it means that *your* app code is broken, not returning what it should, and it will return a server error instead of returning incorrect data. This way you and your clients can be certain that they will receive the data and the data shape expected.
-* Add a **JSON Schema** for the response, in the OpenAPI *path operation*.
+* 在 OpenAPI 的*路径操作*中为响应添加一个 JSON Schema。
* This will be used by the **automatic docs**.
* It will also be used by automatic client code generation tools.
-But most importantly:
+但最重要的是:
* It will **limit and filter** the output data to what is defined in the return type.
* This is particularly important for **security**, we'll see more of that below.
-## `response_model` Parameter
+## !!! tip
+ `{"name", "description"}` 语法创建一个具有这两个值的 `set`。
There are some cases where you need or want to return some data that is not exactly what the type declares.
@@ -43,15 +45,17 @@ For example, you could want to **return a dictionary** or a database object, but
If you added the return type annotation, tools and editors would complain with a (correct) error telling you that your function is returning a type (e.g. a dict) that is different from what you declared (e.g. a Pydantic model).
-In those cases, you can use the *path operation decorator* parameter `response_model` instead of the return type.
+!!! tip
+ 但是依然建议你使用上面提到的主意,使用多个类而不是这些参数。
-You can use the `response_model` parameter in any of the *path operations*:
+!!! note "技术细节"
+ 响应模型在参数中被声明,而不是作为函数返回类型的注解,这是因为路径函数可能不会真正返回该响应模型,而是返回一个 `dict`、数据库对象或其他模型,然后再使用 `response_model` 来执行字段约束和序列化。
* `@app.get()`
* `@app.post()`
* `@app.put()`
* `@app.delete()`
-* etc.
+* 等等。
=== "Python 3.10+"
@@ -68,32 +72,33 @@ You can use the `response_model` parameter in any of the *path operations*:
=== "Python 3.6+"
```Python hl_lines="17 22 24-27"
- {!> ../../../docs_src/response_model/tutorial001.py!}
+ 并在自动生成文档系统中使用。
```
-!!! note
- Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
+!!! !!! note
+ 注意,`response_model`是「装饰器」方法(`get`,`post` 等)的一个参数。 不像之前的所有参数和请求体,它不属于*路径操作函数*。
-`response_model` receives the same type you would declare for a Pydantic model field, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`.
+它接收的类型与你将为 Pydantic 模型属性所声明的类型相同,因此它可以是一个 Pydantic 模型,但也可以是一个由 Pydantic 模型组成的 `list`,例如 `List[Item]`。
-FastAPI will use this `response_model` to do all the data documentation, validation, etc. and also to **convert and filter the output data** to its type declaration.
+将输出数据转换为其声明的类型。
!!! tip
If you have strict type checks in your editor, mypy, etc, you can declare the function return type as `Any`.
That way you tell the editor that you are intentionally returning anything. But FastAPI will still do the data documentation, validation, filtering, etc. with the `response_model`.
-### `response_model` Priority
+### 使用 `response_model_exclude_unset` 参数
-If you declare both a return type and a `response_model`, the `response_model` will take priority and be used by FastAPI.
+FastAPI 将使用此 `response_model` 来:
This way you can add correct type annotations to your functions even when you are returning a type different than the response model, to be used by the editor and tools like mypy. And still you can have FastAPI do the data validation, documentation, etc. using the `response_model`.
-You can also use `response_model=None` to disable creating a response model for that *path operation*, you might need to do it if you are adding type annotations for things that are not valid Pydantic fields, you will see an example of that in one of the sections below.
+!!! danger
+ 永远不要存储用户的明文密码,也不要在响应中发送密码。
-## Return the same input data
+## 返回与输入相同的数据
-Here we are declaring a `UserIn` model, it will contain a plaintext password:
+现在我们声明一个 `UserIn` 模型,它将包含一个明文密码属性。
=== "Python 3.10+"
@@ -104,7 +109,7 @@ Here we are declaring a `UserIn` model, it will contain a plaintext password:
=== "Python 3.6+"
```Python hl_lines="9 11"
- {!> ../../../docs_src/response_model/tutorial002.py!}
+ {!../../../docs_src/response_model/tutorial001.py!}
```
!!! info
@@ -113,7 +118,7 @@ Here we are declaring a `UserIn` model, it will contain a plaintext password:
E.g. `pip install email-validator`
or `pip install pydantic[email]`.
-And we are using this model to declare our input and the same model to declare our output:
+我们正在使用此模型声明输入数据,并使用同一模型声明输出数据:
=== "Python 3.10+"
@@ -124,21 +129,21 @@ And we are using this model to declare our input and the same model to declare o
=== "Python 3.6+"
```Python hl_lines="18"
- {!> ../../../docs_src/response_model/tutorial002.py!}
+ {!../../../docs_src/response_model/tutorial002.py!}
```
-Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
+现在,每当浏览器使用一个密码创建用户时,API 都会在响应中返回相同的密码。
-In this case, it might not be a problem, because it's the same user sending the password.
+在这个案例中,这可能不算是问题,因为用户自己正在发送密码。
-But if we use the same model for another *path operation*, we could be sending our user's passwords to every client.
+但是,如果我们在其他的*路径操作*中使用相同的模型,则可能会将用户的密码发送给每个客户端。
!!! danger
Never store the plain password of a user or send it in a response like this, unless you know all the caveats and you know what you are doing.
-## Add an output model
+## 添加输出模型
-We can instead create an input model with the plaintext password and an output model without it:
+相反,我们可以创建一个有明文密码的输入模型和一个没有明文密码的输出模型:
=== "Python 3.10+"
@@ -149,10 +154,10 @@ We can instead create an input model with the plaintext password and an output m
=== "Python 3.6+"
```Python hl_lines="9 11 16"
- {!> ../../../docs_src/response_model/tutorial003.py!}
+ {!../../../docs_src/response_model/tutorial003.py!}
```
-Here, even though our *path operation function* is returning the same input user that contains the password:
+这样,即便我们的*路径操作函数*将会返回包含密码的相同输入用户:
=== "Python 3.10+"
@@ -163,10 +168,10 @@ Here, even though our *path operation function* is returning the same input user
=== "Python 3.6+"
```Python hl_lines="24"
- {!> ../../../docs_src/response_model/tutorial003.py!}
+ {!../../../docs_src/response_model/tutorial003.py!}
```
-...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
+...我们已经将 `response_model` 声明为了不包含密码的 `UserOut` 模型:
=== "Python 3.10+"
@@ -180,9 +185,9 @@ Here, even though our *path operation function* is returning the same input user
{!> ../../../docs_src/response_model/tutorial003.py!}
```
-So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
+因此,**FastAPI** 将会负责过滤掉未在输出模型中声明的所有数据(使用 Pydantic)。
-### `response_model` or Return Type
+### `response_model_include` 和 `response_model_exclude`
In this case, because the two models are different, if we annotated the function return type as `UserOut`, the editor and tools would complain that we are returning an invalid type, as those are different classes.
@@ -194,7 +199,7 @@ That's why in this example we have to declare it in the `response_model` paramet
Let's continue from the previous example. We wanted to **annotate the function with one type** but return something that includes **more data**.
-We want FastAPI to keep **filtering** the data using the response model.
+校验数据。
In the previous example, because the classes were different, we had to use the `response_model` parameter. But that also means that we don't get the support from the editor and tools checking the function return type.
@@ -236,13 +241,13 @@ FastAPI does several things internally with Pydantic to make sure that those sam
This way, you can get the best of both worlds: type annotations with **tooling support** and **data filtering**.
-## See it in the docs
+## 在文档中查看
-When you see the automatic docs, you can check that the input model and output model will both have their own JSON Schema:
+当你查看自动化文档时,你可以检查输入模型和输出模型是否都具有自己的 JSON Schema:
-And both models will be used for the interactive API documentation:
+并且两种模型都将在交互式 API 文档中使用:
@@ -255,7 +260,7 @@ There might be cases where you return something that is not a valid Pydantic fie
The most common case would be [returning a Response directly as explained later in the advanced docs](../advanced/response-directly.md){.internal-link target=_blank}.
```Python hl_lines="8 10-11"
-{!> ../../../docs_src/response_model/tutorial003_02.py!}
+{!../../../docs_src/response_model/tutorial002.py!}
```
This simple case is handled automatically by FastAPI because the return type annotation is the class (or a subclass) of `Response`.
@@ -267,7 +272,7 @@ And tools will also be happy because both `RedirectResponse` and `JSONResponse`
You can also use a subclass of `Response` in the type annotation:
```Python hl_lines="8-9"
-{!> ../../../docs_src/response_model/tutorial003_03.py!}
+{!../../../docs_src/response_model/tutorial003.py!}
```
This will also work because `RedirectResponse` is a subclass of `Response`, and FastAPI will automatically handle this simple case.
@@ -298,7 +303,8 @@ Continuing from the example above, you might not want to have the default data v
But you might want to still keep the return type annotation in the function to get the support from tools like editors and type checkers (e.g. mypy).
-In this case, you can disable the response model generation by setting `response_model=None`:
+!!! tip
+ 请注意默认值可以是任何值,而不仅是`None`。
=== "Python 3.10+"
@@ -314,9 +320,9 @@ In this case, you can disable the response model generation by setting `response
This will make FastAPI skip the response model generation and that way you can have any return type annotations you need without it affecting your FastAPI application. 🤓
-## Response Model encoding parameters
+## 响应模型编码参数
-Your response model could have default values, like:
+你的响应模型可以具有默认值,例如:
=== "Python 3.10+"
@@ -333,20 +339,21 @@ Your response model could have default values, like:
=== "Python 3.6+"
```Python hl_lines="11 13-14"
- {!> ../../../docs_src/response_model/tutorial004.py!}
+ {!../../../docs_src/response_model/tutorial004.py!}
```
-* `description: Union[str, None] = None` (or `str | None = None` in Python 3.10) has a default of `None`.
-* `tax: float = 10.5` has a default of `10.5`.
-* `tags: List[str] = []` as a default of an empty list: `[]`.
+* `description: Union[str, None] = None` 具有默认值 `None`。
+* `tax: float = 10.5` 具有默认值 `10.5`.
+* `tags: List[str] = []` 具有一个空列表作为默认值: `[]`.
-but you might want to omit them from the result if they were not actually stored.
+但如果它们并没有存储实际的值,你可能想从结果中忽略它们的默认值。
-For example, if you have models with many optional attributes in a NoSQL database, but you don't want to send very long JSON responses full of default values.
+举个例子,当你在 NoSQL 数据库中保存了具有许多可选属性的模型,但你又不想发送充满默认值的很长的 JSON 响应。
-### Use the `response_model_exclude_unset` parameter
+### !!! info
+ FastAPI 通过 Pydantic 模型的 `.dict()` 配合 该方法的 `exclude_unset` 参数 来实现此功能。
-You can set the *path operation decorator* parameter `response_model_exclude_unset=True`:
+你可以设置*路径操作装饰器*的 `response_model_exclude_unset=True` 参数:
=== "Python 3.10+"
@@ -363,12 +370,12 @@ You can set the *path operation decorator* parameter `response_model_exclude_uns
=== "Python 3.6+"
```Python hl_lines="24"
- {!> ../../../docs_src/response_model/tutorial004.py!}
+ {!../../../docs_src/response_model/tutorial004.py!}
```
-and those default values won't be included in the response, only the values actually set.
+然后响应中将不会包含那些默认值,而是仅有实际设置的值。
-So, if you send a request to that *path operation* for the item with ID `foo`, the response (not including default values) will be:
+因此,如果你向*路径操作*发送 ID 为 `foo` 的商品的请求,则响应(不包括默认值)将为:
```JSON
{
@@ -386,11 +393,11 @@ So, if you send a request to that *path operation* for the item with ID `foo`, t
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
- as described in the Pydantic docs for `exclude_defaults` and `exclude_none`.
+ 参考 Pydantic 文档 中对 `exclude_defaults` 和 `exclude_none` 的描述。
-#### Data with values for fields with defaults
+#### 默认值字段有实际值的数据
-But if your data has values for the model's fields with default values, like the item with ID `bar`:
+但是,如果你的数据在具有默认值的模型字段中有实际的值,例如 ID 为 `bar` 的项:
```Python hl_lines="3 5"
{
@@ -401,11 +408,11 @@ But if your data has values for the model's fields with default values, like the
}
```
-they will be included in the response.
+这些值将包含在响应中。
-#### Data with the same values as the defaults
+#### 具有与默认值相同值的数据
-If the data has the same values as the default ones, like the item with ID `baz`:
+如果数据具有与默认值相同的值,例如 ID 为 `baz` 的项:
```Python hl_lines="3 5-6"
{
@@ -417,29 +424,29 @@ If the data has the same values as the default ones, like the item with ID `baz`
}
```
-FastAPI is smart enough (actually, Pydantic is smart enough) to realize that, even though `description`, `tax`, and `tags` have the same values as the defaults, they were set explicitly (instead of taken from the defaults).
+即使 `description`、`tax` 和 `tags` 具有与默认值相同的值,FastAPI 足够聪明 (实际上是 Pydantic 足够聪明) 去认识到这一点,它们的值被显式地所设定(而不是取自默认值)。
-So, they will be included in the JSON response.
+因此,它们将包含在 JSON 响应中。
!!! tip
Notice that the default values can be anything, not only `None`.
- They can be a list (`[]`), a `float` of `10.5`, etc.
+ 它们可以是一个列表(`[]`),一个值为 `10.5`的 `float`,等等。
### `response_model_include` and `response_model_exclude`
-You can also use the *path operation decorator* parameters `response_model_include` and `response_model_exclude`.
+你还可以使用*路径操作装饰器*的 `response_model_include` 和 `response_model_exclude` 参数。
-They take a `set` of `str` with the name of the attributes to include (omitting the rest) or to exclude (including the rest).
+它们接收一个由属性名称 `str` 组成的 `set` 来包含(忽略其他的)或者排除(包含其他的)这些属性。
-This can be used as a quick shortcut if you have only one Pydantic model and want to remove some data from the output.
+如果你只有一个 Pydantic 模型,并且想要从输出中移除一些数据,则可以使用这种快捷方法。
!!! tip
But it is still recommended to use the ideas above, using multiple classes, instead of these parameters.
- This is because the JSON Schema generated in your app's OpenAPI (and the docs) will still be the one for the complete model, even if you use `response_model_include` or `response_model_exclude` to omit some attributes.
+ 这是因为即使使用 `response_model_include` 或 `response_model_exclude` 来省略某些属性,在应用程序的 OpenAPI 定义(和文档)中生成的 JSON Schema 仍将是完整的模型。
- This also applies to `response_model_by_alias` that works similarly.
+ 这也适用于作用类似的 `response_model_by_alias`。
=== "Python 3.10+"
@@ -450,17 +457,17 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
=== "Python 3.6+"
```Python hl_lines="31 37"
- {!> ../../../docs_src/response_model/tutorial005.py!}
+ {!../../../docs_src/response_model/tutorial005.py!}
```
!!! tip
The syntax `{"name", "description"}` creates a `set` with those two values.
- It is equivalent to `set(["name", "description"])`.
+ 等同于 `set(["name", "description"])`。
-#### Using `list`s instead of `set`s
+#### 使用 `list` 而不是 `set`
-If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will still convert it to a `set` and it will work correctly:
+如果你忘记使用 `set` 而是使用 `list` 或 `tuple`,FastAPI 仍会将其转换为 `set` 并且正常工作:
=== "Python 3.10+"
@@ -471,11 +478,11 @@ If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will s
=== "Python 3.6+"
```Python hl_lines="31 37"
- {!> ../../../docs_src/response_model/tutorial006.py!}
+ {!../../../docs_src/response_model/tutorial006.py!}
```
## Recap
-Use the *path operation decorator's* parameter `response_model` to define response models and especially to ensure private data is filtered out.
+使用*路径操作装饰器*的 `response_model` 参数来定义响应模型,特别是确保私有数据被过滤掉。
-Use `response_model_exclude_unset` to return only the values explicitly set.
+使用 `response_model_exclude_unset` 来仅返回显式设定的值。
From fde986fc3553db2f42902c93029dbba8acda9533 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:54:59 +0800
Subject: [PATCH 153/163] New translations response-status-code.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/response-status-code.md | 86 +++++++++----------
1 file changed, 43 insertions(+), 43 deletions(-)
diff --git a/docs/zh/docs/tutorial/response-status-code.md b/docs/zh/docs/tutorial/response-status-code.md
index 8e26706e53d62..5a265909abcff 100644
--- a/docs/zh/docs/tutorial/response-status-code.md
+++ b/docs/zh/docs/tutorial/response-status-code.md
@@ -1,89 +1,89 @@
-# Response Status Code
+# 响应状态码
-The same way you can specify a response model, you can also declare the HTTP status code used for the response with the parameter `status_code` in any of the *path operations*:
+与指定响应模型的方式相同,你也可以在以下任意的*路径操作*中使用 `status_code` 参数来声明用于响应的 HTTP 状态码:
* `@app.get()`
* `@app.post()`
* `@app.put()`
* `@app.delete()`
-* etc.
+* 等等。
```Python hl_lines="6"
{!../../../docs_src/response_status_code/tutorial001.py!}
```
-!!! note
- Notice that `status_code` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
+!!! !!! note
+ 注意,`status_code` 是「装饰器」方法(`get`,`post` 等)的一个参数。 不像之前的所有参数和请求体,它不属于*路径操作函数*。
-The `status_code` parameter receives a number with the HTTP status code.
+`status_code` 参数接收一个表示 HTTP 状态码的数字。
-!!! info
- `status_code` can alternatively also receive an `IntEnum`, such as Python's `http.HTTPStatus`.
+!!! !!! info
+ `status_code` 也能够接收一个 `IntEnum` 类型,比如 Python 的 `http.HTTPStatus`。
-It will:
+它将会:
-* Return that status code in the response.
-* Document it as such in the OpenAPI schema (and so, in the user interfaces):
+* 在响应中返回该状态码。
+* 在 OpenAPI 模式中(以及在用户界面中)将其记录为:
-!!! note
- Some response codes (see the next section) indicate that the response does not have a body.
+!!! !!! note
+ 一些响应状态码(请参阅下一部分)表示响应没有响应体。
- FastAPI knows this, and will produce OpenAPI docs that state there is no response body.
+ FastAPI 知道这一点,并将生成表明没有响应体的 OpenAPI 文档。
-## About HTTP status codes
+## 关于 HTTP 状态码
-!!! note
- If you already know what HTTP status codes are, skip to the next section.
+!!! !!! note
+ 如果你已经了解什么是 HTTP 状态码,请跳到下一部分。
-In HTTP, you send a numeric status code of 3 digits as part of the response.
+在 HTTP 协议中,你将发送 3 位数的数字状态码作为响应的一部分。
-These status codes have a name associated to recognize them, but the important part is the number.
+这些状态码有一个识别它们的关联名称,但是重要的还是数字。
-In short:
+简而言之:
-* `100` and above are for "Information". You rarely use them directly. Responses with these status codes cannot have a body.
-* **`200`** and above are for "Successful" responses. These are the ones you would use the most.
- * `200` is the default status code, which means everything was "OK".
- * Another example would be `201`, "Created". It is commonly used after creating a new record in the database.
- * A special case is `204`, "No Content". This response is used when there is no content to return to the client, and so the response must not have a body.
-* **`300`** and above are for "Redirection". Responses with these status codes may or may not have a body, except for `304`, "Not Modified", which must not have one.
-* **`400`** and above are for "Client error" responses. These are the second type you would probably use the most.
- * An example is `404`, for a "Not Found" response.
- * For generic errors from the client, you can just use `400`.
-* `500` and above are for server errors. You almost never use them directly. When something goes wrong at some part in your application code, or server, it will automatically return one of these status codes.
+* `100` 及以上状态码用于「消息」响应。 你很少直接使用它们。 具有这些状态代码的响应不能带有响应体。
+* **`200`** 及以上状态码用于「成功」响应。 这些是你最常使用的。
+ * `200` 是默认状态代码,它表示一切「正常」。
+ * 另一个例子会是 `201`,「已创建」。 它通常在数据库中创建了一条新记录后使用。
+ * 一个特殊的例子是 `204`,「无内容」。 此响应在没有内容返回给客户端时使用,因此该响应不能包含响应体。
+* **`300`** 及以上状态码用于「重定向」。 具有这些状态码的响应可能有或者可能没有响应体,但 `304`「未修改」是个例外,该响应不得含有响应体。
+* **`400`** 及以上状态码用于「客户端错误」响应。 这些可能是你第二常使用的类型。
+ * 一个例子是 `404`,用于「未找到」响应。
+ * 对于来自客户端的一般错误,你可以只使用 `400`。
+* `500` 及以上状态码用于服务器端错误。 你几乎永远不会直接使用它们。 当你的应用程序代码或服务器中的某些部分出现问题时,它将自动返回这些状态代码之一。
-!!! tip
- To know more about each status code and which code is for what, check the MDN documentation about HTTP status codes.
+!!! !!! tip
+ 要了解有关每个状态代码以及适用场景的更多信息,请查看 MDN 关于 HTTP 状态码的文档。
-## Shortcut to remember the names
+## 记住名称的捷径
-Let's see the previous example again:
+让我们再次看看之前的例子:
```Python hl_lines="6"
{!../../../docs_src/response_status_code/tutorial001.py!}
```
-`201` is the status code for "Created".
+`201` 是表示「已创建」的状态码。
-But you don't have to memorize what each of these codes mean.
+但是你不必去记住每个代码的含义。
-You can use the convenience variables from `fastapi.status`.
+你可以使用来自 `fastapi.status` 的便捷变量。
```Python hl_lines="1 6"
{!../../../docs_src/response_status_code/tutorial002.py!}
```
-They are just a convenience, they hold the same number, but that way you can use the editor's autocomplete to find them:
+它们只是一种便捷方式,它们具有同样的数字代码,但是这样使用你就可以使用编辑器的自动补全功能来查找它们:
-!!! note "Technical Details"
- You could also use `from starlette import status`.
+!!! !!! note "技术细节"
+ 你也可以使用 `from starlette import status`。
- **FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
+ 为了给你(即开发者)提供方便,**FastAPI** 提供了与 `starlette.status` 完全相同的 `fastapi.status`。 但它直接来自于 Starlette。
-## Changing the default
+## 更改默认状态码
-Later, in the [Advanced User Guide](../advanced/response-change-status-code.md){.internal-link target=_blank}, you will see how to return a different status code than the default you are declaring here.
+稍后,在[高级用户指南](../advanced/response-change-status-code.md){.internal-link target=_blank}中你将了解如何返回与在此声明的默认状态码不同的状态码。
From 78743df4e56761da0401c9a6c73fb03a167236fe Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:00 +0800
Subject: [PATCH 154/163] New translations schema-extra-example.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/schema-extra-example.md | 55 ++++++++++---------
1 file changed, 30 insertions(+), 25 deletions(-)
diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md
index 9b24aa3702e80..14abdac8624b7 100644
--- a/docs/zh/docs/tutorial/schema-extra-example.md
+++ b/docs/zh/docs/tutorial/schema-extra-example.md
@@ -23,7 +23,7 @@ You can declare `examples` for a Pydantic model that will be added to the genera
=== "Python 3.6+ Pydantic v2"
```Python hl_lines="15-26"
- {!> ../../../docs_src/schema_extra_example/tutorial001.py!}
+ {!../../../docs_src/schema_extra_example/tutorial001.py!}
```
=== "Python 3.6+ Pydantic v1"
@@ -58,7 +58,7 @@ That extra info will be added as-is to the output **JSON Schema** for that model
You can read more at the end of this page.
-## `Field` additional arguments
+## `Field` 的附加参数
When using `Field()` with Pydantic models, you can also declare additional `examples`:
@@ -71,10 +71,10 @@ When using `Field()` with Pydantic models, you can also declare additional `exam
=== "Python 3.6+"
```Python hl_lines="4 10-13"
- {!> ../../../docs_src/schema_extra_example/tutorial002.py!}
+ {!../../../docs_src/schema_extra_example/tutorial002.py!}
```
-## `examples` in OpenAPI
+## 所以,虽然 `example` 不是JSON Schema的一部分,但它是OpenAPI的一部分,这将被文档UI使用。
When using any of:
@@ -88,9 +88,9 @@ When using any of:
you can also declare a group of `examples` with additional information that will be added to **OpenAPI**.
-### `Body` with `examples`
+### 关于 `example` 和 `examples`...
-Here we pass `examples` containing one example of the data expected in `Body()`:
+比如,你可以将请求体的一个 `example` 传递给 `Body`:
=== "Python 3.10+"
@@ -101,15 +101,18 @@ Here we pass `examples` containing one example of the data expected in `Body()`:
=== "Python 3.9+"
```Python hl_lines="22-29"
- {!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
+ !!! warning
+ 请记住,传递的那些额外参数不会添加任何验证,只会添加注释,用于文档的目的。
```
=== "Python 3.6+"
```Python hl_lines="23-30"
- {!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
+ Pydantic schema_extra
```
+
+
=== "Python 3.10+ non-Annotated"
!!! tip
@@ -125,16 +128,18 @@ Here we pass `examples` containing one example of the data expected in `Body()`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="20-27"
- {!> ../../../docs_src/schema_extra_example/tutorial003.py!}
+ 您可以使用 Config 和 schema_extra 为Pydantic模型声明一个示例,如Pydantic 文档:定制 Schema 中所述:
```
+ 和 schema_extra 为Pydantic模型声明一个示例,如Pydantic 文档:定制 Schema 中所述:
+
-### Example in the docs UI
+### 模式的额外信息 - 例子
-With any of the methods above it would look like this in the `/docs`:
+使用上面的任何方法,它在 `/docs` 中看起来都是这样的:
-### `Body` with multiple `examples`
+### `Body` 额外参数
You can of course also pass multiple `examples`:
@@ -153,7 +158,7 @@ You can of course also pass multiple `examples`:
=== "Python 3.6+"
```Python hl_lines="24-39"
- {!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
+ 同样的方法,你可以添加你自己的额外信息,这些信息将被添加到每个模型的JSON模式中,例如定制前端用户界面,等等。
```
=== "Python 3.10+ non-Annotated"
@@ -162,7 +167,7 @@ You can of course also pass multiple `examples`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="19-34"
- {!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
+ 其他信息
```
=== "Python 3.6+ non-Annotated"
@@ -171,16 +176,16 @@ You can of course also pass multiple `examples`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="21-36"
- {!> ../../../docs_src/schema_extra_example/tutorial004.py!}
+ {!../../../docs_src/schema_extra_example/tutorial003.py!}
```
-### Examples in the docs UI
+### 文档 UI 中的例子
-With `examples` added to `Body()` the `/docs` would look like:
+你可以通过传递额外信息给 `Field` 同样的方式操作`Path`, `Query`, `Body`等。
-## Technical Details
+## 技术细节
!!! tip
If you are already using **FastAPI** version **0.99.0 or above**, you can probably **skip** these details.
@@ -196,16 +201,16 @@ With `examples` added to `Body()` the `/docs` would look like:
Before OpenAPI 3.1.0, OpenAPI used an older and modified version of **JSON Schema**.
-JSON Schema didn't have `examples`, so OpenAPI added it's own `example` field to its own modified version.
+在 `Field`, `Path`, `Query`, `Body` 和其他你之后将会看到的工厂函数,你可以为JSON 模式声明额外信息,你也可以通过给工厂函数传递其他的任意参数来给JSON 模式声明额外信息,比如增加 `example`:
OpenAPI also added `example` and `examples` fields to other parts of the specification:
-* `Parameter Object` (in the specification) that was used by FastAPI's:
+* 所以 OpenAPI为了相似的目的定义了自己的 `example` (使用 `example`, 而不是 `examples`), 这也是文档 UI 所使用的 (使用 Swagger UI).
* `Path()`
* `Query()`
* `Header()`
* `Cookie()`
-* `Request Body Object`, in the field `content`, on the `Media Type Object` (in the specification) that was used by FastAPI's:
+* 您可以在JSON模式中定义额外的信息。
* `Body()`
* `File()`
* `Form()`
@@ -216,18 +221,18 @@ The shape of this field `examples` from OpenAPI is a `dict` with **multiple exam
The keys of the `dict` identify each example, and each value is another `dict`.
-Each specific example `dict` in the `examples` can contain:
+一个常见的用例是添加一个将在文档中显示的`example`。
* `summary`: Short description for the example.
* `description`: A long description that can contain Markdown text.
* `value`: This is the actual example shown, e.g. a `dict`.
* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`.
-This applies to those other parts of the OpenAPI specification apart from JSON Schema.
+这些额外的信息将按原样添加到输出的JSON模式中。
-### JSON Schema's `examples` field
+### 有几种方法可以声明额外的 JSON 模式信息。
-But then JSON Schema added an `examples` field to a new version of the specification.
+JSON Schema在最新的一个版本中定义了一个字段 `examples` ,但是 OpenAPI 基于之前的一个旧版JSON Schema,并没有 `examples`.
And then the new OpenAPI 3.1.0 was based on the latest version (JSON Schema 2020-12) that included this new field `examples`.
From 7d821a7a8d244016e09459f296cd9613152886dd Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:01 +0800
Subject: [PATCH 155/163] New translations first-steps.md (Chinese Simplified)
---
docs/zh/docs/tutorial/security/first-steps.md | 466 +++++++++++-------
1 file changed, 298 insertions(+), 168 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md
index 25c20b8df21d6..32827f42aac1b 100644
--- a/docs/zh/docs/tutorial/security/first-steps.md
+++ b/docs/zh/docs/tutorial/security/first-steps.md
@@ -1,35 +1,35 @@
-# Security - First Steps
+# 安全 - 第一步
-Let's imagine that you have your **backend** API in some domain.
+假设**后端** API 在某个域。
-And you have a **frontend** in another domain or in a different path of the same domain (or in a mobile application).
+**前端**在另一个域,或(移动应用中)在同一个域的不同路径下。
-And you want to have a way for the frontend to authenticate with the backend, using a **username** and **password**.
+并且,前端要使用后端的 **username** 与 **password** 验证用户身份。
-We can use **OAuth2** to build that with **FastAPI**.
+固然,**FastAPI** 支持 **OAuth2** 身份验证。
But let's save you the time of reading the full long specification just to find those little pieces of information you need.
-Let's use the tools provided by **FastAPI** to handle security.
+我们建议使用 **FastAPI** 的安全工具。
## How it looks
-Let's first just use the code and see how it works, and then we'll come back to understand what's happening.
+首先,看看下面的代码是怎么运行的,然后再回过头来了解其背后的原理。
-## Create `main.py`
+## 创建 `main.py`
-Copy the example in a file `main.py`:
+把下面的示例代码复制到 `main.py`:
=== "Python 3.9+"
```Python
- {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ !!! tip "提示"
```
=== "Python 3.6+"
```Python
- {!> ../../../docs_src/security/tutorial001_an.py!}
+ 令牌只是用于验证用户的字符串
```
=== "Python 3.6+ non-Annotated"
@@ -38,20 +38,22 @@ Copy the example in a file `main.py`:
Prefer to use the `Annotated` version if possible.
```Python
- {!> ../../../docs_src/security/tutorial001.py!}
+ {!../../../docs_src/security/tutorial001.py!}
```
-## Run it
+## 运行
-!!! info
- First install `python-multipart`.
+!!! 打开 API 文档: http://127.0.0.1:8000/docs。
- E.g. `pip install python-multipart`.
-
- This is because **OAuth2** uses "form data" for sending the `username` and `password`.
+先安装 <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>。 安装命令: `pip install python-multipart`。
-Run the example with:
+这是因为 **OAuth2** 使用**表单数据**发送 `username` 与 `password`。
+
+
++ 用下面的命令运行该示例: +
+ Go to the interactive docs at: http://127.0.0.1:8000/docs. +
-You will see something like this: ++ You will see something like this: +
-
+
+
+
+ !!! check "Authorize button!" You already have a shiny new "Authorize" button. +
- And your *path operation* has a little lock in the top-right corner that you can click. +And your *path operation* has a little lock in the top-right corner that you can click.
+
-And if you click it, you have a little authorization form to type a `username` and `password` (and other optional fields):
+
+ 点击 Authorize 按钮,弹出授权表单,输入 username 与 password 及其它可选字段:
+
+
+
+
+ !!! note It doesn't matter what you type in the form, it won't work yet. But we'll get there. +
+ ++ 虽然此文档不是给前端最终用户使用的,但这个自动工具非常实用,可在文档中与所有 API 交互。 +
+ ++ 前端团队(可能就是开发者本人)可以使用本工具。 +
+ ++ 第三方应用与系统也可以调用本工具。 +
+ ++ 开发者也可以用它来调试、检查、测试应用。 +
+ ++ Now let's go back a bit and understand what is all that. +
+ +
+ Password 流是 OAuth2 定义的,用于处理安全与身份验证的方式(流)。
+
+ OAuth2 的设计目标是为了让后端或 API 独立于服务器验证用户身份。 +
+ ++ 但在本例中,FastAPI 应用会处理 API 与身份验证。 +
+ ++ So, let's review it from that simplified point of view: +
+ +username 与password,并点击回车
+ username 与password 发送至 API 中指定的 URL(使用 tokenUrl="token" 声明)
+ username 与password,并用令牌(Token) 响应(暂未实现此功能): Bearer + 令牌的请求头 Authorization
+ foobar,Authorization 请求头就是: Bearer foobar
+ OAuth2PasswordBearer
++ FastAPI 提供了不同抽象级别的安全工具。 +
+ +
+ 本例使用 OAuth2 的 Password 流以及 Bearer 令牌(Token)。 为此要使用 OAuth2PasswordBearer 类。
+
+ !!! `Bearer` 令牌不是唯一的选择。 +
+ +但它是最适合这个用例的方案。
+
+甚至可以说,它是适用于绝大多数用例的最佳方案,除非您是 OAuth2 的专家,知道为什么其它方案更合适。
+
+本例中,**FastAPI** 还提供了构建工具。
+
+
+
+ 创建 OAuth2PasswordBearer 的类实例时,要传递 tokenUrl 参数。 该参数包含客户端(用户浏览器中运行的前端) 的 URL,用于发送 username 与 password,并获取令牌。
+
+ === "Python 3.9+" + +
!!! check "Authorize 按钮!"
+
+
+
++ === "Python 3.6+" + +
!!! info "说明"
+
+
+
++ === "Python 3.6+ non-Annotated" +
+ +!!! tip
+ Prefer to use the `Annotated` version if possible.
+
+
+ {!../../../docs_src/security/tutorial001.py!}
+
+
++ !!! 在此,`tokenUrl="token"` 指向的是暂未创建的相对 URL `token`。 这个相对 URL 相当于 `./token`。 +
+ +因为使用的是相对 URL,如果 API 位于 `https://example.com/`,则指向 `https://example.com/token`。 但如果 API 位于 `https://example.com/api/v1/`,它指向的就是`https://example.com/api/v1/token`。
+
+使用相对 URL 非常重要,可以确保应用在遇到[使用代理](../../advanced/behind-a-proxy.md){.internal-link target=_blank}这样的高级用例时,也能正常运行。
+
+
+
+ 该参数不会创建端点或路径操作,但会声明客户端用来获取令牌的 URL /token 。 此信息用于 OpenAPI 及 API 文档。
+
+ 接下来,学习如何创建实际的路径操作。 +
+ ++ !!! 严苛的 **Pythonista** 可能不喜欢用 `tokenUrl` 这种命名风格代替 `token_url`。 +
+ +这种命名方式是因为要使用与 OpenAPI 规范中相同的名字。 以便在深入校验安全方案时,能通过复制粘贴查找更多相关信息。
+
+
+
+ oauth2_scheme 变量是 OAuth2PasswordBearer 的实例,也是可调用项。
+
+ It could be called as: +
+ +oauth2_scheme(some, parameters)
+
+
+
+ 因此,Depends 可以调用 oauth2_scheme 变量。
+
+ 接下来,使用 Depends 把 oauth2_scheme 传入依赖项。
+
+ === "Python 3.9+" + +
!!! info "说明"
+
+
-## What it does
++ === "Python 3.6+" + +
!!! info "说明"
+
+
-It will go and look in the request for that `Authorization` header, check if the value is `Bearer` plus some token, and will return the token as a `str`.
++ === "Python 3.6+ non-Annotated" +
-If it doesn't see an `Authorization` header, or the value doesn't have a `Bearer` token, it will respond with a 401 status code error (`UNAUTHORIZED`) directly. +!!! tip
+ Prefer to use the `Annotated` version if possible.
+
+
+ {!../../../docs_src/security/tutorial001.py!}
+
+
+
+ 该依赖项使用字符串(str)接收路径操作函数的参数 token 。
+
+ FastAPI 使用依赖项在 OpenAPI 概图(及 API 文档)中定义安全方案。 +
+ +
+ !!! info "Technical Details"
+ FastAPI will know that it can use the class OAuth2PasswordBearer (declared in a dependency) to define the security scheme in OpenAPI because it inherits from fastapi.security.oauth2.OAuth2, which in turn inherits from fastapi.security.base.SecurityBase.
+
所有与 OpenAPI(及 API 文档)集成的安全工具都继承自 `SecurityBase`, 这就是为什么 **FastAPI** 能把它们集成至 OpenAPI 的原因。
+
-You can try it already in the interactive docs:
+
+
+ FastAPI 校验请求中的 Authorization 请求头,核对请求头的值是不是由 Bearer + 令牌组成, 并返回令牌字符串(str)。
+
+ 如果没有找到 Authorization 请求头,或请求头的值不是 Bearer + 令牌。 FastAPI 直接返回 401 错误状态码(UNAUTHORIZED)。
+
+ You don't even have to check if the token exists to return an error. You can be sure that if your function is executed, it will have a str in that token.
+
+ You can try it already in the interactive docs: +
+ +
+
+
+ We are not verifying the validity of the token yet, but that's a start already. +
+ ++ 看到了吧,只要多写三四行代码,就可以添加基础的安全表单。 +
From aaa854a694ed073357b39622c5b2a2460b326e41 Mon Sep 17 00:00:00 2001 From: Sefank <12670778+Sefank@users.noreply.github.com> Date: Wed, 26 Jul 2023 16:55:02 +0800 Subject: [PATCH 156/163] New translations get-current-user.md (Chinese Simplified) --- .../tutorial/security/get-current-user.md | 102 +++++++++--------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/docs/zh/docs/tutorial/security/get-current-user.md b/docs/zh/docs/tutorial/security/get-current-user.md index 1a8c5d9a8d8fd..c503a34059ba5 100644 --- a/docs/zh/docs/tutorial/security/get-current-user.md +++ b/docs/zh/docs/tutorial/security/get-current-user.md @@ -1,17 +1,18 @@ -# Get Current User +# 获取当前用户 -In the previous chapter the security system (which is based on the dependency injection system) was giving the *path operation function* a `token` as a `str`: +在上一章节中,(基于依赖项注入系统的)安全系统向*路径操作函数*提供了一个 `str` 类型的 `token`: === "Python 3.9+" ```Python hl_lines="12" - {!> ../../../docs_src/security/tutorial001_an_py39.py!} + 这些内容在下一章节。 ``` === "Python 3.6+" ```Python hl_lines="11" - {!> ../../../docs_src/security/tutorial001_an.py!} + !!! tip + 你可能还记得请求体也是使用 Pydantic 模型来声明的。 ``` === "Python 3.6+ non-Annotated" @@ -20,18 +21,18 @@ In the previous chapter the security system (which is based on the dependency in Prefer to use the `Annotated` version if possible. ```Python hl_lines="10" - {!> ../../../docs_src/security/tutorial001.py!} + {!../../../docs_src/security/tutorial002.py!} ``` -But that is still not that useful. +但这还不是很实用。 -Let's make it give us the current user. +让我们来使它返回当前用户给我们。 -## Create a user model +## 创建一个用户模型 -First, let's create a Pydantic user model. +首先,让我们来创建一个用户 Pydantic 模型。 -The same way we use Pydantic to declare bodies, we can use it anywhere else: +与使用 Pydantic 声明请求体的方式相同,我们可以在其他任何地方使用它: === "Python 3.10+" @@ -57,7 +58,7 @@ The same way we use Pydantic to declare bodies, we can use it anywhere else: Prefer to use the `Annotated` version if possible. ```Python hl_lines="3 10-14" - {!> ../../../docs_src/security/tutorial002_py310.py!} + {!../../../docs_src/security/tutorial002.py!} ``` === "Python 3.6+ non-Annotated" @@ -66,18 +67,18 @@ The same way we use Pydantic to declare bodies, we can use it anywhere else: Prefer to use the `Annotated` version if possible. ```Python hl_lines="5 12-16" - {!> ../../../docs_src/security/tutorial002.py!} + {!../../../docs_src/security/tutorial001.py!} ``` -## Create a `get_current_user` dependency +## 创建一个 `get_current_user` 依赖项 -Let's create a dependency `get_current_user`. +让我们来创建一个 `get_current_user` 依赖项。 -Remember that dependencies can have sub-dependencies? +还记得依赖项可以有子依赖项吗? -`get_current_user` will have a dependency with the same `oauth2_scheme` we created before. +`get_current_user` 将具有一个我们之前所创建的同一个 `oauth2_scheme` 作为依赖项。 -The same as we were doing before in the *path operation* directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`: +与我们之前直接在路径操作中所做的相同,我们新的依赖项 `get_current_user` 将从子依赖项 `oauth2_scheme` 中接收一个 `str` 类型的 `token`: === "Python 3.10+" @@ -103,7 +104,7 @@ The same as we were doing before in the *path operation* directly, our new depen Prefer to use the `Annotated` version if possible. ```Python hl_lines="23" - {!> ../../../docs_src/security/tutorial002_py310.py!} + {!../../../docs_src/security/tutorial002.py!} ``` === "Python 3.6+ non-Annotated" @@ -112,12 +113,12 @@ The same as we were doing before in the *path operation* directly, our new depen Prefer to use the `Annotated` version if possible. ```Python hl_lines="25" - {!> ../../../docs_src/security/tutorial002.py!} + {!../../../docs_src/security/tutorial002.py!} ``` -## Get the user +## 获取用户 -`get_current_user` will use a (fake) utility function we created, that takes a token as a `str` and returns our Pydantic `User` model: +`get_current_user` 将使用我们创建的(伪)工具函数,该函数接收 `str` 类型的令牌并返回我们的 Pydantic `User` 模型: === "Python 3.10+" @@ -155,9 +156,9 @@ The same as we were doing before in the *path operation* directly, our new depen {!> ../../../docs_src/security/tutorial002.py!} ``` -## Inject the current user +## 注入当前用户 -So now we can use the same `Depends` with our `get_current_user` in the *path operation*: +因此现在我们可以在*路径操作*中使用 `get_current_user` 作为 `Depends` 了: === "Python 3.10+" @@ -174,8 +175,11 @@ So now we can use the same `Depends` with our `get_current_user` in the *path op === "Python 3.6+" ```Python hl_lines="32" - {!> ../../../docs_src/security/tutorial002_an.py!} + !!! check + 这种依赖系统的设计方式使我们可以拥有不同的依赖项(不同的「可依赖类型」),并且它们都返回一个User 模型。
```
+ 模型。
+
=== "Python 3.10+ non-Annotated"
@@ -195,56 +199,56 @@ So now we can use the same `Depends` with our `get_current_user` in the *path op
{!> ../../../docs_src/security/tutorial002.py!}
```
-Notice that we declare the type of `current_user` as the Pydantic model `User`.
+注意我们将 `current_user` 的类型声明为 Pydantic 模型 `User`。
-This will help us inside of the function with all the completion and type checks.
+这将帮助我们在函数内部使用所有的代码补全和类型检查。
!!! tip
You might remember that request bodies are also declared with Pydantic models.
- Here **FastAPI** won't get confused because you are using `Depends`.
+ 在这里 **FastAPI** 不会搞混,因为你正在使用的是 `Depends`。
!!! check
The way this dependency system is designed allows us to have different dependencies (different "dependables") that all return a `User` model.
- We are not restricted to having only one dependency that can return that type of data.
+ 我们并未被局限于只能有一个返回该类型数据的依赖项。
-## Other models
+## 其他模型
-You can now get the current user directly in the *path operation functions* and deal with the security mechanisms at the **Dependency Injection** level, using `Depends`.
+现在你可以直接在*路径操作函数*中获取当前用户,并使用 `Depends` 在**依赖注入**级别处理安全性机制。
-And you can use any model or data for the security requirements (in this case, a Pydantic model `User`).
+你可以使用任何模型或数据来满足安全性要求(在这个示例中,使用的是 Pydantic 模型 `User`)。
-But you are not restricted to using some specific data model, class or type.
+但是你并未被限制只能使用某些特定的数据模型,类或类型。
-Do you want to have an `id` and `email` and not have any `username` in your model? Sure. You can use these same tools.
+你想要在模型中使用 `id` 和 `email` 而不使用任何的 `username`? 当然可以。 你可以同样地使用这些工具。
-Do you want to just have a `str`? Or just a `dict`? Or a database class model instance directly? It all works the same way.
+你只想要一个 `str`? 或者仅仅一个 `dict`? 还是直接一个数据库模型类的实例? 它们的工作方式都是一样的。
-You actually don't have users that log in to your application but robots, bots, or other systems, that have just an access token? Again, it all works the same.
+实际上你没有用户登录到你的应用程序,而是只拥有访问令牌的机器人,程序或其他系统? 再一次,它们的工作方式也是一样的。
-Just use any kind of model, any kind of class, any kind of database that you need for your application. **FastAPI** has you covered with the dependency injection system.
+尽管去使用你的应用程序所需要的任何模型,任何类,任何数据库。 **FastAPI** 通过依赖项注入系统都帮你搞定。
-## Code size
+## 代码体积
-This example might seem verbose. Have in mind that we are mixing security, data models, utility functions and *path operations* in the same file.
+这个示例似乎看起来很冗长。 考虑到我们在同一文件中混合了安全性,数据模型工具函数和路径操作等代码。
-But here's the key point.
+但关键的是。
-The security and dependency injection stuff is written once.
+安全性和依赖项注入内容只需要编写一次。
-And you can make it as complex as you want. And still, have it written only once, in a single place. With all the flexibility.
+你可以根据需要使其变得很复杂。 而且只需要在一个地方写一次。 但仍然具备所有的灵活性。
-But you can have thousands of endpoints (*path operations*) using the same security system.
+但是,你可以有无数个使用同一安全系统的端点(*路径操作*)。
-And all of them (or any portion of them that you want) can take the advantage of re-using these dependencies or any other dependencies you create.
+所有(或所需的任何部分)的端点,都可以利用对这些或你创建的其他依赖项进行复用所带来的优势。
-And all these thousands of *path operations* can be as small as 3 lines:
+所有的这无数个*路径操作*甚至可以小到只需 3 行代码:
=== "Python 3.10+"
```Python hl_lines="30-32"
- {!> ../../../docs_src/security/tutorial002_an_py310.py!}
+ 总结
```
=== "Python 3.9+"
@@ -274,15 +278,15 @@ And all these thousands of *path operations* can be as small as 3 lines:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="30-32"
- {!> ../../../docs_src/security/tutorial002.py!}
+ {!../../../docs_src/security/tutorial002.py!}
```
## Recap
-You can now get the current user directly in your *path operation function*.
+现在你可以直接在*路径操作函数*中获取当前用户。
-We are already halfway there.
+我们已经进行到一半了。
-We just need to add a *path operation* for the user/client to actually send the `username` and `password`.
+我们只需要再为用户/客户端添加一个真正发送 `username` 和 `password` 的*路径操作*。
That comes next.
From fbb2a997f479a6b0565f3ed58ec11c264ea17d97 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:04 +0800
Subject: [PATCH 157/163] New translations index.md (Chinese Simplified)
---
docs/zh/docs/tutorial/security/index.md | 100 ++++++++++++------------
1 file changed, 50 insertions(+), 50 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/index.md b/docs/zh/docs/tutorial/security/index.md
index 9679cda427d6a..b4b26eb0e49a9 100644
--- a/docs/zh/docs/tutorial/security/index.md
+++ b/docs/zh/docs/tutorial/security/index.md
@@ -1,101 +1,101 @@
-# Security
+# 安全性
-There are many ways to handle security, authentication and authorization.
+有许多方法可以处理安全性、身份认证和授权等问题。
-And it normally is a complex and "difficult" topic.
+而且这通常是一个复杂而「困难」的话题。
-In many frameworks and systems just handling security and authentication takes a big amount of effort and code (in many cases it can be 50% or more of all the code written).
+在许多框架和系统中,仅处理安全性和身份认证就会花费大量的精力和代码(在许多情况下,可能占编写的所有代码的 50% 或更多)。
-**FastAPI** provides several tools to help you deal with **Security** easily, rapidly, in a standard way, without having to study and learn all the security specifications.
+**FastAPI** 提供了多种工具,可帮助你以标准的方式轻松、快速地处理**安全性**,而无需研究和学习所有的安全规范。
-But first, let's check some small concepts.
+但首先,让我们来看一些小的概念。
## In a hurry?
-If you don't care about any of these terms and you just need to add security with authentication based on username and password *right now*, skip to the next chapters.
+如果你不关心这些术语,而只需要*立即*通过基于用户名和密码的身份认证来增加安全性,请跳转到下一章。
## OAuth2
-OAuth2 is a specification that defines several ways to handle authentication and authorization.
+OAuth2是一个规范,它定义了几种处理身份认证和授权的方法。
-It is quite an extensive specification and covers several complex use cases.
+它是一个相当广泛的规范,涵盖了一些复杂的使用场景。
-It includes ways to authenticate using a "third party".
+它包括了使用「第三方」进行身份认证的方法。
-That's what all the systems with "login with Facebook, Google, Twitter, GitHub" use underneath.
+这就是所有带有「使用 Facebook,Google,Twitter,GitHub 登录」的系统背后所使用的机制。
### OAuth 1
-There was an OAuth 1, which is very different from OAuth2, and more complex, as it included direct specifications on how to encrypt the communication.
+有一个 OAuth 1,它与 OAuth2 完全不同,并且更为复杂,因为它直接包含了有关如何加密通信的规范。
-It is not very popular or used nowadays.
+如今它已经不是很流行,没有被广泛使用了。
-OAuth2 doesn't specify how to encrypt the communication, it expects you to have your application served with HTTPS.
+OAuth2 没有指定如何加密通信,它期望你为应用程序使用 HTTPS 进行通信。
-!!! tip
- In the section about **deployment** you will see how to set up HTTPS for free, using Traefik and Let's Encrypt.
+!!! !!! tip
+ 在有关**部署**的章节中,你将了解如何使用 Traefik 和 Let's Encrypt 免费设置 HTTPS。
## OpenID Connect
-OpenID Connect is another specification, based on **OAuth2**.
+OpenID Connect 是另一个基于 **OAuth2** 的规范。
-It just extends OAuth2 specifying some things that are relatively ambiguous in OAuth2, to try to make it more interoperable.
+它只是扩展了 OAuth2,并明确了一些在 OAuth2 中相对模糊的内容,以尝试使其更具互操作性。
-For example, Google login uses OpenID Connect (which underneath uses OAuth2).
+例如,Google 登录使用 OpenID Connect(底层使用OAuth2)。
-But Facebook login doesn't support OpenID Connect. It has its own flavor of OAuth2.
+但是 Facebook 登录不支持 OpenID Connect。 它具有自己的 OAuth2 风格。
-### OpenID (not "OpenID Connect")
+### OpenID(非「OpenID Connect」)
-There was also an "OpenID" specification. That tried to solve the same thing as **OpenID Connect**, but was not based on OAuth2.
+还有一个「OpenID」规范。 它试图解决与 **OpenID Connect** 相同的问题,但它不是基于 OAuth2。
-So, it was a complete additional system.
+因此,它是一个完整的附加系统。
-It is not very popular or used nowadays.
+如今它已经不是很流行,没有被广泛使用了。
## OpenAPI
-OpenAPI (previously known as Swagger) is the open specification for building APIs (now part of the Linux Foundation).
+OpenAPI(以前称为 Swagger)是用于构建 API 的开放规范(现已成为 Linux Foundation 的一部分)。
-**FastAPI** is based on **OpenAPI**.
+**FastAPI** 基于 **OpenAPI**。
-That's what makes it possible to have multiple automatic interactive documentation interfaces, code generation, etc.
+这就是使多个自动交互式文档界面,代码生成等成为可能的原因。
-OpenAPI has a way to define multiple security "schemes".
+OpenAPI 有一种定义多个安全「方案」的方法。
-By using them, you can take advantage of all these standard-based tools, including these interactive documentation systems.
+通过使用它们,你可以利用所有这些基于标准的工具,包括这些交互式文档系统。
-OpenAPI defines the following security schemes:
+OpenAPI 定义了以下安全方案:
-* `apiKey`: an application specific key that can come from:
- * A query parameter.
+* `apiKey`:一个特定于应用程序的密钥,可以来自:
+ * 查询参数。
* A header.
- * A cookie.
-* `http`: standard HTTP authentication systems, including:
- * `bearer`: a header `Authorization` with a value of `Bearer` plus a token. This is inherited from OAuth2.
- * HTTP Basic authentication.
- * HTTP Digest, etc.
-* `oauth2`: all the OAuth2 ways to handle security (called "flows").
- * Several of these flows are appropriate for building an OAuth 2.0 authentication provider (like Google, Facebook, Twitter, GitHub, etc):
+ * cookie。
+* `http`:标准的 HTTP 身份认证系统,包括:
+ * `bearer`: 一个值为 `Bearer` 加令牌字符串的 `Authorization` 请求头。 这是从 OAuth2 继承的。
+ * HTTP Basic 认证方式。
+ * HTTP Digest,等等。
+* `oauth2`:所有的 OAuth2 处理安全性的方式(称为「流程」)。
+ * *以下几种流程适合构建 OAuth 2.0 身份认证的提供者(例如 Google,Facebook,Twitter,GitHub 等): * `implicit` * `clientCredentials` * `authorizationCode`
* `implicit`
* `clientCredentials`
* `authorizationCode`
- * But there is one specific "flow" that can be perfectly used for handling authentication in the same application directly:
- * `password`: some next chapters will cover examples of this.
-* `openIdConnect`: has a way to define how to discover OAuth2 authentication data automatically.
- * This automatic discovery is what is defined in the OpenID Connect specification.
+ * 但是有一个特定的「流程」可以完美地用于直接在同一应用程序中处理身份认证:
+ * `password`:接下来的几章将介绍它的示例。
+* `openIdConnect`:提供了一种定义如何自动发现 OAuth2 身份认证数据的方法。
+ * 此自动发现机制是 OpenID Connect 规范中定义的内容。
-!!! tip
- Integrating other authentication/authorization providers like Google, Facebook, Twitter, GitHub, etc. is also possible and relatively easy.
+!!! !!! tip
+ 集成其他身份认证/授权提供者(例如Google,Facebook,Twitter,GitHub等)也是可能的,而且较为容易。
- The most complex problem is building an authentication/authorization provider like those, but **FastAPI** gives you the tools to do it easily, while doing the heavy lifting for you.
+ 最复杂的问题是创建一个像这样的身份认证/授权提供程序,但是 **FastAPI** 为你提供了轻松完成任务的工具,同时为你解决了重活。
-## **FastAPI** utilities
+## **FastAPI** 实用工具
-FastAPI provides several tools for each of these security schemes in the `fastapi.security` module that simplify using these security mechanisms.
+FastAPI 在 `fastapi.security` 模块中为每个安全方案提供了几种工具,这些工具简化了这些安全机制的使用方法。
-In the next chapters you will see how to add security to your API using those tools provided by **FastAPI**.
+在下一章中,你将看到如何使用 **FastAPI** 所提供的这些工具为你的 API 增加安全性。
-And you will also see how it gets automatically integrated into the interactive documentation system.
+而且你还将看到它如何自动地被集成到交互式文档系统中。
From 52e84d4274174d24125bf94d3d151c186024a7d3 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:05 +0800
Subject: [PATCH 158/163] New translations oauth2-jwt.md (Chinese Simplified)
---
docs/zh/docs/tutorial/security/oauth2-jwt.md | 201 +++++++++----------
1 file changed, 100 insertions(+), 101 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md
index b663abcb7b696..7e126a75d93d3 100644
--- a/docs/zh/docs/tutorial/security/oauth2-jwt.md
+++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md
@@ -1,16 +1,16 @@
-# OAuth2 with Password (and hashing), Bearer with JWT tokens
+# OAuth2 实现密码哈希与 Bearer JWT 令牌验证
-Now that we have all the security flow, let's make the application actually secure, using JWT tokens and secure password hashing.
+至此,我们已经编写了所有安全流,本章学习如何使用 JWT 令牌(Token)和安全密码哈希(Hash)实现真正的安全机制。
-This code is something you can actually use in your application, save the password hashes in your database, etc.
+本章的示例代码真正实现了在应用的数据库中保存哈希密码等功能。
We are going to start from where we left in the previous chapter and increment it.
-## About JWT
+## JWT 简介
-JWT means "JSON Web Tokens".
+JWT 即**JSON 网络令牌**(JSON Web Tokens)。
-It's a standard to codify a JSON object in a long dense string without spaces. It looks like this:
+JWT 是一种将 JSON 对象编码为没有空格,且难以理解的长字符串的标准。 It looks like this:
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
@@ -20,111 +20,108 @@ It is not encrypted, so, anyone could recover the information from the contents.
But it's signed. So, when you receive a token that you emitted, you can verify that you actually emitted it.
-That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know that user is still logged in to your system.
+使用 JWT 创建有效期为一周的令牌。 第二天,用户持令牌再次访问时,仍为登录状态。
-After a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
+After a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. 如果用户(或第三方)篡改令牌的过期时间,因为签名不匹配会导致身份验证失败。
-If you want to play with JWT tokens and see how they work, check https://jwt.io.
+如需深入了解 JWT 令牌,了解它的工作方式,请参阅 https://jwt.io。
-## Install `python-jose`
+## 安装 `python-jose`
-We need to install `python-jose` to generate and verify the JWT tokens in Python:
+安装 `python-jose`,在 Python 中生成和校验 JWT 令牌:
scopes(作用域)。
```
+(作用域)。
+
=== "Python 3.10+ non-Annotated"
@@ -286,7 +285,7 @@ Create a real JWT access token and return it
Prefer to use the `Annotated` version if possible.
```Python hl_lines="114-127"
- {!> ../../../docs_src/security/tutorial004_py310.py!}
+ 查看新的(伪)数据库 `fake_users_db`,就能看到哈希后的密码:`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`。
```
=== "Python 3.6+ non-Annotated"
@@ -295,51 +294,51 @@ Create a real JWT access token and return it
Prefer to use the `Annotated` version if possible.
```Python hl_lines="115-128"
- {!> ../../../docs_src/security/tutorial004.py!}
+ {!../../../docs_src/security/tutorial004.py!}
```
-### Technical details about the JWT "subject" `sub`
+### JWT `sub` 的技术细节
-The JWT specification says that there's a key `sub`, with the subject of the token.
+JWT 规范还包括 `sub` 键,值是令牌的主题。
-It's optional to use it, but that's where you would put the user's identification, so we are using it here.
+该键是可选的,但要把用户标识放在这个键里,所以本例使用了该键。
-JWT might be used for other things apart from identifying a user and allowing them to perform operations directly on your API.
+除了识别用户与许可用户在 API 上直接执行操作之外,JWT 还可能用于其它事情。
For example, you could identify a "car" or a "blog post".
Then you could add permissions about that entity, like "drive" (for the car) or "edit" (for the blog).
-And then, you could give that JWT token to a user (or bot), and they could use it to perform those actions (drive the car, or edit the blog post) without even needing to have an account, just with the JWT token your API generated for that.
+JWT 字符串没有加密,任何人都能用它恢复原始信息。
-Using these ideas, JWT can be used for way more sophisticated scenarios.
+同理,JWT 可以用于更复杂的场景。
-In those cases, several of those entities could have the same ID, let's say `foo` (a user `foo`, a car `foo`, and a blog post `foo`).
+在这些情况下,多个实体的 ID 可能是相同的,以 ID `foo` 为例,用户的 ID 是 `foo`,车的 ID 是 `foo`,博客的 ID 也是 `foo`。
-So, to avoid ID collisions, when creating the JWT token for the user, you could prefix the value of the `sub` key, e.g. with `username:`. So, in this example, the value of `sub` could have been: `username:johndoe`.
+为了避免 ID 冲突,在给用户创建 JWT 令牌时,可以为 `sub` 键的值加上前缀,例如 `username:`。 因此,在本例中,`sub` 的值可以是:`username:johndoe`。
-The important thing to have in mind is that the `sub` key should have a unique identifier across the entire application, and it should be a string.
+注意,划重点,`sub` 键在整个应用中应该只有一个唯一的标识符,而且应该是字符串。
-## Check it
+## 检查
-Run the server and go to the docs: http://127.0.0.1:8000/docs.
+运行服务器并访问文档: http://127.0.0.1:8000/docs。
-You'll see the user interface like:
+可以看到如下用户界面:
-Authorize the application the same way as before.
+用与上一章同样的方式实现应用授权。
-Using the credentials:
+使用如下凭证:
-Username: `johndoe` Password: `secret`
+用户名: `johndoe` 密码: `secret`
!!! check
Notice that nowhere in the code is the plaintext password "`secret`", we only have the hashed version.
-Call the endpoint `/users/me/`, you will get the response as:
+调用 `/users/me/` 端点,收到下面的响应:
```JSON
{
@@ -352,41 +351,41 @@ Call the endpoint `/users/me/`, you will get the response as:
-If you open the developer tools, you could see how the data sent only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
+打开浏览器的开发者工具,查看数据是怎么发送的,而且数据里只包含了令牌,只有验证用户的第一个请求才发送密码,并获取访问令牌,但之后不会再发送密码:
!!! note
Notice the header `Authorization`, with a value that starts with `Bearer`.
-## Advanced usage with `scopes`
+## `scopes` 高级用法
OAuth2 has the notion of "scopes".
You can use them to add a specific set of permissions to a JWT token.
-Then you can give this token to a user directly or a third party, to interact with your API with a set of restrictions.
+让持有令牌的用户或第三方在指定限制条件下与 API 交互。
-You can learn how to use them and how they are integrated into **FastAPI** later in the **Advanced User Guide**.
+**高级用户指南**中将介绍如何使用 `scopes`,及如何把 `scopes` 集成至 **FastAPI**。
## Recap
-With what you have seen up to now, you can set up a secure **FastAPI** application using standards like OAuth2 and JWT.
+至此,您可以使用 OAuth2 和 JWT 等标准配置安全的 **FastAPI** 应用。
-In almost any framework handling the security becomes a rather complex subject quite quickly.
+几乎在所有框架中,处理安全问题很快都会变得非常复杂。
-Many packages that simplify it a lot have to make many compromises with the data model, database, and available features. And some of these packages that simplify things too much actually have security flaws underneath.
+有些包为了简化安全流,不得不在数据模型、数据库和功能上做出妥协。 而有些过于简化的软件包其实存在了安全隐患。
---
-**FastAPI** doesn't make any compromise with any database, data model or tool.
+**FastAPI** 不向任何数据库、数据模型或工具做妥协。
It gives you all the flexibility to choose the ones that fit your project the best.
-And you can use directly many well maintained and widely used packages like `passlib` and `python-jose`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
+还可以直接使用 `passlib` 和 `python-jose` 等维护良好、使用广泛的包,这是因为 **FastAPI** 不需要任何复杂机制,就能集成外部的包。
But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security.
And you can use and implement secure, standard protocols, like OAuth2 in a relatively simple way.
-You can learn more in the **Advanced User Guide** about how to use OAuth2 "scopes", for a more fine-grained permission system, following these same standards. OAuth2 with scopes is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, Twitter, etc. to authorize third party applications to interact with their APIs on behalf of their users.
+**高级用户指南**中详细介绍了 OAuth2**`scopes`**的内容,遵循同样的标准,实现更精密的权限系统。 OAuth2 的作用域是脸书、谷歌、GitHub、微软、推特等第三方身份验证应用使用的机制,让用户授权第三方应用与 API 交互。
From 3795b9893a8bead6121c15fc9b0428d72e918b75 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:06 +0800
Subject: [PATCH 159/163] New translations simple-oauth2.md (Chinese
Simplified)
---
.../docs/tutorial/security/simple-oauth2.md | 242 ++++++++++--------
1 file changed, 131 insertions(+), 111 deletions(-)
diff --git a/docs/zh/docs/tutorial/security/simple-oauth2.md b/docs/zh/docs/tutorial/security/simple-oauth2.md
index f55ee6fb8f029..7b782c9e1bd33 100644
--- a/docs/zh/docs/tutorial/security/simple-oauth2.md
+++ b/docs/zh/docs/tutorial/security/simple-oauth2.md
@@ -1,53 +1,53 @@
-# Simple OAuth2 with Password and Bearer
+# 使用密码和 Bearer 的简单 OAuth2
-Now let's build from the previous chapter and add the missing parts to have a complete security flow.
+现在让我们接着上一章继续开发,并添加缺少的部分以实现一个完整的安全性流程。
-## Get the `username` and `password`
+## 获取 `username` 和 `password`
-We are going to use **FastAPI** security utilities to get the `username` and `password`.
+我们将使用 **FastAPI** 的安全性实用工具来获取 `username` 和 `password`。
-OAuth2 specifies that when using the "password flow" (that we are using) the client/user must send a `username` and `password` fields as form data.
+OAuth2 规定在使用(我们打算用的)「password 流程」时,客户端/用户必须将 `username` 和 `password` 字段作为表单数据发送。
-And the spec says that the fields have to be named like that. So `user-name` or `email` wouldn't work.
+而且规范明确了字段必须这样命名。 因此 `user-name` 或 `email` 是行不通的。
-But don't worry, you can show it as you wish to your final users in the frontend.
+不过不用担心,你可以在前端按照你的想法将它展示给最终用户。
-And your database models can use any other names you want.
+而且你的数据库模型也可以使用你想用的任何其他名称。
-But for the login *path operation*, we need to use these names to be compatible with the spec (and be able to, for example, use the integrated API documentation system).
+但是对于登录*路径操作*,我们需要使用这些名称来与规范兼容(以具备例如使用集成的 API 文档系统的能力)。
-The spec also states that the `username` and `password` must be sent as form data (so, no JSON here).
+规范还写明了 `username` 和 `password` 必须作为表单数据发送(因此,此处不能使用 JSON)。
### `scope`
-The spec also says that the client can send another form field "`scope`".
+规范还提到客户端可以发送另一个表单字段「`scope`」。
-The form field name is `scope` (in singular), but it is actually a long string with "scopes" separated by spaces.
+这个表单字段的名称为 `scope`(单数形式),但实际上它是一个由空格分隔的「作用域」组成的长字符串。
Each "scope" is just a string (without spaces).
-They are normally used to declare specific security permissions, for example:
+它们通常用于声明特定的安全权限,例如:
-* `users:read` or `users:write` are common examples.
-* `instagram_basic` is used by Facebook / Instagram.
-* `https://www.googleapis.com/auth/drive` is used by Google.
+* `users:read` 或者 `users:write` 是常见的例子。
+* Facebook / Instagram 使用 `instagram_basic`。
+* Google 使用了 `https://www.googleapis.com/auth/drive` 。
!!! info
In OAuth2 a "scope" is just a string that declares a specific permission required.
- It doesn't matter if it has other characters like `:` or if it is a URL.
+ 它有没有 `:` 这样的其他字符或者是不是 URL 都没有关系。
- Those details are implementation specific.
+ 这些细节是具体的实现。
- For OAuth2 they are just strings.
+ 对 OAuth2 来说它们就只是字符串而已。
-## Code to get the `username` and `password`
+## 获取 `username` 和 `password` 的代码
-Now let's use the utilities provided by **FastAPI** to handle this.
+现在,让我们使用 **FastAPI** 提供的实用工具来处理此问题。
### `OAuth2PasswordRequestForm`
-First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` in the *path operation* for `/token`:
+首先,导入 `OAuth2PasswordRequestForm`,然后在 `token` 的*路径操作*中通过 `Depends` 将其作为依赖项使用。
=== "Python 3.10+"
@@ -58,14 +58,18 @@ First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depe
=== "Python 3.9+"
```Python hl_lines="4 78"
- {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ !!! tip
+ 在下一章中,你将看到一个真实的安全实现,使用了哈希密码和 JWT 令牌。
```
=== "Python 3.6+"
```Python hl_lines="4 79"
- {!> ../../../docs_src/security/tutorial003_an.py!}
+ !!! info
+ OAuth2PasswordRequestForm 并不像 OAuth2PasswordBearer 一样是 FastAPI 的一个特殊的类。
```
+ 并不像 OAuth2PasswordBearer 一样是 FastAPI 的一个特殊的类。
+
=== "Python 3.10+ non-Annotated"
@@ -73,7 +77,7 @@ First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depe
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 74"
- {!> ../../../docs_src/security/tutorial003_py310.py!}
+ 如果没有这个用户,我们将返回一个错误消息,提示「用户名或密码错误」。
```
=== "Python 3.6+ non-Annotated"
@@ -82,62 +86,66 @@ First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depe
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4 76"
- {!> ../../../docs_src/security/tutorial003.py!}
+ {!../../../docs_src/security/tutorial003.py!}
```
-`OAuth2PasswordRequestForm` is a class dependency that declares a form body with:
+`OAuth2PasswordRequestForm` 是一个类依赖项,声明了如下的请求表单:
-* The `username`.
-* The `password`.
-* An optional `scope` field as a big string, composed of strings separated by spaces.
-* An optional `grant_type`.
+* `username`。
+* `password`。
+* 一个可选的 `scope` 字段,是一个由空格分隔的字符串组成的大字符串。
+* 一个可选的 `grant_type`.
!!! tip
The OAuth2 spec actually *requires* a field `grant_type` with a fixed value of `password`, but `OAuth2PasswordRequestForm` doesn't enforce it.
- If you need to enforce it, use `OAuth2PasswordRequestFormStrict` instead of `OAuth2PasswordRequestForm`.
+ 如果你需要强制要求这一点,请使用 `OAuth2PasswordRequestFormStrict` 而不是 `OAuth2PasswordRequestForm`。
-* An optional `client_id` (we don't need it for our example).
-* An optional `client_secret` (we don't need it for our example).
+* 一个可选的 `client_id`(我们的示例不需要它)。
+* 一个可选的 `client_secret`(我们的示例不需要它)。
!!! info
The `OAuth2PasswordRequestForm` is not a special class for **FastAPI** as is `OAuth2PasswordBearer`.
- `OAuth2PasswordBearer` makes **FastAPI** know that it is a security scheme. So it is added that way to OpenAPI.
+ `OAuth2PasswordBearer` 使得 **FastAPI** 明白它是一个安全方案。 所以它得以通过这种方式添加到 OpenAPI 中。
- But `OAuth2PasswordRequestForm` is just a class dependency that you could have written yourself, or you could have declared `Form` parameters directly.
+ 但 `OAuth2PasswordRequestForm` 只是一个你可以自己编写的类依赖项,或者你也可以直接声明 `Form` 参数。
- But as it's a common use case, it is provided by **FastAPI** directly, just to make it easier.
+ 但是由于这是一种常见的使用场景,因此 FastAPI 出于简便直接提供了它。
-### Use the form data
+### 使用表单数据
!!! tip
The instance of the dependency class `OAuth2PasswordRequestForm` won't have an attribute `scope` with the long string separated by spaces, instead, it will have a `scopes` attribute with the actual list of strings for each scope sent.
- We are not using `scopes` in this example, but the functionality is there if you need it.
+ 在此示例中我们没有使用 `scopes`,但如果你需要的话可以使用该功能。
-Now, get the user data from the (fake) database, using the `username` from the form field.
+现在,使用表单字段中的 `username` 从(伪)数据库中获取用户数据。
-If there is no such user, we return an error saying "incorrect username or password".
+如果密码不匹配,我们将返回同一个错误。
-For the error, we use the exception `HTTPException`:
+对于这个错误,我们使用 `HTTPException` 异常:
=== "Python 3.10+"
```Python hl_lines="3 79-81"
- {!> ../../../docs_src/security/tutorial003_an_py310.py!}
+ !!! info
+ 我们在此处返回的值为 Bearer 的额外响应头 WWW-Authenticate 也是规范的一部分。
```
+ 的额外响应头 WWW-Authenticate 也是规范的一部分。
+
=== "Python 3.9+"
```Python hl_lines="3 79-81"
- {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ https://fastapi.tiangolo.com/img/tutorial/security/image05.png
```
=== "Python 3.6+"
```Python hl_lines="3 80-82"
- {!> ../../../docs_src/security/tutorial003_an.py!}
+ !!! info
+ 在 OAuth2 中「作用域」只是一个声明所需特定权限的字符串。
```
=== "Python 3.10+ non-Annotated"
@@ -146,7 +154,7 @@ For the error, we use the exception `HTTPException`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 75-77"
- {!> ../../../docs_src/security/tutorial003_py310.py!}
+ {!../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.6+ non-Annotated"
@@ -155,32 +163,32 @@ For the error, we use the exception `HTTPException`:
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3 77-79"
- {!> ../../../docs_src/security/tutorial003.py!}
+ {!../../../docs_src/security/tutorial003.py!}
```
-### Check the password
+### 校验密码
-At this point we have the user data from our database, but we haven't checked the password.
+目前我们已经从数据库中获取了用户数据,但尚未校验密码。
-Let's put that data in the Pydantic `UserInDB` model first.
+让我们首先将这些数据放入 Pydantic `UserInDB` 模型中。
-You should never save plaintext passwords, so, we'll use the (fake) password hashing system.
+永远不要保存明文密码,因此,我们将使用(伪)哈希密码系统。
If the passwords don't match, we return the same error.
-#### Password hashing
+#### 哈希密码
-"Hashing" means: converting some content (a password in this case) into a sequence of bytes (just a string) that looks like gibberish.
+「哈希」的意思是:将某些内容(在本例中为密码)转换为看起来像乱码的字节序列(只是一个字符串)。
-Whenever you pass exactly the same content (exactly the same password) you get exactly the same gibberish.
+每次你传入完全相同的内容(完全相同的密码)时,你都会得到完全相同的乱码。
-But you cannot convert from the gibberish back to the password.
+但是你不能从乱码转换回密码。
-##### Why use password hashing
+##### 为什么使用哈希密码
-If your database is stolen, the thief won't have your users' plaintext passwords, only the hashes.
+如果你的数据库被盗,小偷将无法获得用户的明文密码,只有哈希值。
-So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
+因此,小偷将无法尝试在另一个系统中使用这些相同的密码(由于许多用户在任何地方都使用相同的密码,因此这很危险)。
=== "Python 3.10+"
@@ -191,14 +199,17 @@ So, the thief won't be able to try to use those same passwords in another system
=== "Python 3.9+"
```Python hl_lines="82-85"
- {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ https://fastapi.tiangolo.com/img/tutorial/security/image04.png
```
=== "Python 3.6+"
```Python hl_lines="83-86"
- {!> ../../../docs_src/security/tutorial003_an.py!}
+ !!! tip
+ OAuth2 规范实际上要求 grant_type 字段使用一个固定的值 password,但是 OAuth2PasswordRequestForm 没有作强制约束。
```
+ 字段使用一个固定的值 password,但是 OAuth2PasswordRequestForm 没有作强制约束。
+
=== "Python 3.10+ non-Annotated"
@@ -215,14 +226,14 @@ So, the thief won't be able to try to use those same passwords in another system
Prefer to use the `Annotated` version if possible.
```Python hl_lines="80-83"
- {!> ../../../docs_src/security/tutorial003.py!}
+ {!../../../docs_src/security/tutorial003.py!}
```
-#### About `**user_dict`
+#### 关于 `**user_dict`
-`UserInDB(**user_dict)` means:
+`UserInDB(**user_dict)` 表示:
-*Pass the keys and values of the `user_dict` directly as key-value arguments, equivalent to:*
+*直接将 `user_dict` 的键和值作为关键字参数传递,等同于:*
```Python
UserInDB(
@@ -237,20 +248,20 @@ UserInDB(
!!! info
For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user_indict){.internal-link target=_blank}.
-## Return the token
+## 返回令牌
-The response of the `token` endpoint must be a JSON object.
+`token` 端点的响应必须是一个 JSON 对象。
-It should have a `token_type`. In our case, as we are using "Bearer" tokens, the token type should be "`bearer`".
+它应该有一个 `token_type`。 在我们的例子中,由于我们使用的是「Bearer」令牌,因此令牌类型应为「`bearer`」。
-And it should have an `access_token`, with a string containing our access token.
+并且还应该有一个 `access_token` 字段,它是一个包含我们的访问令牌的字符串。
-For this simple example, we are going to just be completely insecure and return the same `username` as the token.
+对于这个简单的示例,我们将极其不安全地返回相同的 `username` 作为令牌。
!!! tip
In the next chapter, you will see a real secure implementation, with password hashing and JWT tokens.
- But for now, let's focus on the specific details we need.
+ 但现在,让我们仅关注我们需要的特定细节。
=== "Python 3.10+"
@@ -267,8 +278,11 @@ For this simple example, we are going to just be completely insecure and return
=== "Python 3.6+"
```Python hl_lines="88"
- {!> ../../../docs_src/security/tutorial003_an.py!}
+ !!! info
+ 有关 user_dict 的更完整说明,请参阅额外的模型文档{.internal-link target=_blank}。
```
+ 的更完整说明,请参阅[**额外的模型**文档](../extra-models.md#about-user_indict){.internal-link target=_blank}。
+
=== "Python 3.10+ non-Annotated"
@@ -285,29 +299,29 @@ For this simple example, we are going to just be completely insecure and return
Prefer to use the `Annotated` version if possible.
```Python hl_lines="85"
- {!> ../../../docs_src/security/tutorial003.py!}
+ {!../../../docs_src/security/tutorial003.py!}
```
!!! tip
By the spec, you should return a JSON with an `access_token` and a `token_type`, the same as in this example.
- This is something that you have to do yourself in your code, and make sure you use those JSON keys.
+ 这是你必须在代码中自行完成的工作,并且要确保使用了这些 JSON 字段。
- It's almost the only thing that you have to remember to do correctly yourself, to be compliant with the specifications.
+ 这几乎是唯一的你需要自己记住并正确地执行以符合规范的事情。
- For the rest, **FastAPI** handles it for you.
+ 其余的,**FastAPI** 都会为你处理。
-## Update the dependencies
+## 更新依赖项
-Now we are going to update our dependencies.
+现在我们将更新我们的依赖项。
-We want to get the `current_user` *only* if this user is active.
+我们想要仅当此用户处于启用状态时才能获取 `current_user`。
-So, we create an additional dependency `get_current_active_user` that in turn uses `get_current_user` as a dependency.
+因此,我们创建了一个额外的依赖项 `get_current_active_user`,而该依赖项又以 `get_current_user` 作为依赖项。
-Both of these dependencies will just return an HTTP error if the user doesn't exist, or if is inactive.
+如果用户不存在或处于未启用状态,则这两个依赖项都将仅返回 HTTP 错误。
-So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
+因此,在我们的端点中,只有当用户存在,身份认证通过且处于启用状态时,我们才能获得该用户:
=== "Python 3.10+"
@@ -318,14 +332,17 @@ So, in our endpoint, we will only get a user if the user exists, was correctly a
=== "Python 3.9+"
```Python hl_lines="58-66 69-74 94"
- {!> ../../../docs_src/security/tutorial003_an_py39.py!}
+ 每个「作用域」只是一个字符串(中间没有空格)。
```
=== "Python 3.6+"
```Python hl_lines="59-67 70-75 95"
- {!> ../../../docs_src/security/tutorial003_an.py!}
+ !!! tip
+ 类依赖项 OAuth2PasswordRequestForm 的实例不会有用空格分隔的长字符串属性 scope,而是具有一个 scopes 属性,该属性将包含实际被发送的每个作用域字符串组成的列表。
```
+ 的实例不会有用空格分隔的长字符串属性 scope,而是具有一个 scopes 属性,该属性将包含实际被发送的每个作用域字符串组成的列表。
+
=== "Python 3.10+ non-Annotated"
@@ -342,49 +359,52 @@ So, in our endpoint, we will only get a user if the user exists, was correctly a
Prefer to use the `Annotated` version if possible.
```Python hl_lines="58-66 69-72 90"
- {!> ../../../docs_src/security/tutorial003.py!}
+ !!! tip
+ 根据规范,你应该像本示例一样,返回一个带有 access_token 和 token_type 的 JSON。
```
+ 和 token_type 的 JSON。
+
!!! info
The additional header `WWW-Authenticate` with value `Bearer` we are returning here is also part of the spec.
- Any HTTP (error) status code 401 "UNAUTHORIZED" is supposed to also return a `WWW-Authenticate` header.
+ 任何的 401「未认证」HTTP(错误)状态码都应该返回 `WWW-Authenticate` 响应头。
- In the case of bearer tokens (our case), the value of that header should be `Bearer`.
+ 对于 bearer 令牌(我们的例子),该响应头的值应为 `Bearer`。
- You can actually skip that extra header and it would still work.
+ 实际上你可以忽略这个额外的响应头,不会有什么问题。
- But it's provided here to be compliant with the specifications.
+ 但此处提供了它以符合规范。
- Also, there might be tools that expect and use it (now or in the future) and that might be useful for you or your users, now or in the future.
+ 而且,(现在或将来)可能会有工具期望得到并使用它,然后对你或你的用户有用处。
- That's the benefit of standards...
+ 这就是遵循标准的好处...
## See it in action
-Open the interactive docs: http://127.0.0.1:8000/docs.
+打开交互式文档:http://127.0.0.1:8000/docs。
-### Authenticate
+### 身份认证
-Click the "Authorize" button.
+点击「Authorize」按钮。
-Use the credentials:
+使用以下凭证:
-User: `johndoe`
+用户名:`johndoe`
-Password: `secret`
+密码:`secret`
-After authenticating in the system, you will see it like:
+在系统中进行身份认证后,你将看到:
-### Get your own user data
+### 获取本人的用户数据
-Now use the operation `GET` with the path `/users/me`.
+现在执行 `/users/me` 路径的 `GET` 操作。
-You will get your user's data, like:
+你将获得你的用户数据,如:
```JSON
{
@@ -398,7 +418,7 @@ You will get your user's data, like:
-If you click the lock icon and logout, and then try the same operation again, you will get an HTTP 401 error of:
+如果你点击锁定图标并注销,然后再次尝试同一操作,则会得到 HTTP 401 错误:
```JSON
{
@@ -406,17 +426,17 @@ If you click the lock icon and logout, and then try the same operation again, yo
}
```
-### Inactive user
+### 未启用的用户
-Now try with an inactive user, authenticate with:
+现在尝试使用未启用的用户,并通过以下方式进行身份认证:
-User: `alice`
+用户名:`alice`
-Password: `secret2`
+密码:`secret2`
-And try to use the operation `GET` with the path `/users/me`.
+然后尝试执行 `/users/me` 路径的 `GET` 操作。
-You will get an "inactive user" error, like:
+你将得到一个「未启用的用户」错误,如:
```JSON
{
@@ -426,10 +446,10 @@ You will get an "inactive user" error, like:
## Recap
-You now have the tools to implement a complete security system based on `username` and `password` for your API.
+现在你掌握了为你的 API 实现一个基于 `username` 和 `password` 的完整安全系统的工具。
-Using these tools, you can make the security system compatible with any database and with any user or data model.
+使用这些工具,你可以使安全系统与任何数据库以及任何用户或数据模型兼容。
-The only detail missing is that it is not actually "secure" yet.
+唯一缺少的细节是它实际上还并不「安全」。
-In the next chapter you'll see how to use a secure password hashing library and JWT tokens.
+在下一章中,你将看到如何使用一个安全的哈希密码库和 JWT 令牌。
From 0f287a698cafa38c5c58f75f5e49263fb4ce1662 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:07 +0800
Subject: [PATCH 160/163] New translations sql-databases.md (Chinese
Simplified)
---
docs/zh/docs/tutorial/sql-databases.md | 641 ++++++++++++++-----------
1 file changed, 353 insertions(+), 288 deletions(-)
diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md
index 136946bddddda..53de41a7bd3c2 100644
--- a/docs/zh/docs/tutorial/sql-databases.md
+++ b/docs/zh/docs/tutorial/sql-databases.md
@@ -1,4 +1,4 @@
-# SQL (Relational) Databases
+# SQL (关系型) 数据库
!!! info
These docs are about to be updated. 🎉
@@ -7,73 +7,74 @@
The new docs will include Pydantic v2 and will use SQLModel (which is also based on SQLAlchemy) once it is updated to use Pydantic v2 as well.
-**FastAPI** doesn't require you to use a SQL (relational) database.
+**FastAPI**不需要你使用SQL(关系型)数据库。
-But you can use any relational database that you want.
+但是您可以使用任何您想要的关系型数据库。
-Here we'll see an example using SQLAlchemy.
+在这里,让我们看一个使用着[SQLAlchemy](https://www.sqlalchemy.org/)的示例。
-You can easily adapt it to any database supported by SQLAlchemy, like:
+您可以很容易地将SQLAlchemy支持任何数据库,像:
* PostgreSQL
* MySQL
* SQLite
* Oracle
-* Microsoft SQL Server, etc.
+* Microsoft SQL Server,等等其它数据库
-In this example, we'll use **SQLite**, because it uses a single file and Python has integrated support. So, you can copy this example and run it as is.
+在此示例中,我们将使用**SQLite**,因为它使用单个文件并且 在Python中具有集成支持。 因此,您可以复制此示例并按原样来运行它。
-Later, for your production application, you might want to use a database server like **PostgreSQL**.
+稍后,对于您的产品级别的应用程序,您可能会要使用像**PostgreSQL**这样的数据库服务器。
-!!! tip
- There is an official project generator with **FastAPI** and **PostgreSQL**, all based on **Docker**, including a frontend and more tools: https://github.com/tiangolo/full-stack-fastapi-postgresql
+!!! !!! tip
+ 这儿有一个**FastAPI**和**PostgreSQL**的官方项目生成器,全部基于**Docker**,包括前端和更多工具:https://github.com/tiangolo/full-stack-fastapi-postgresql
-!!! note
- Notice that most of the code is the standard `SQLAlchemy` code you would use with any framework.
+!!! !!! note
+ 请注意,大部分代码是`SQLAlchemy`的标准代码,您可以用于任何框架。
- The **FastAPI** specific code is as small as always.
+ FastAPI特定的代码和往常一样少。
## ORMs
-**FastAPI** works with any database and any style of library to talk to the database.
+**FastAPI**可与任何数据库在任何样式的库中一起与 数据库进行通信。
-A common pattern is to use an "ORM": an "object-relational mapping" library.
+一种常见的模式是使用“ORM”:对象关系映射。
-An ORM has tools to convert ("*map*") between *objects* in code and database tables ("*relations*").
+ORM 具有在代码和数据库表(“*关系型”)中的**对象**之间转换(“*映射*”)的工具。
-With an ORM, you normally create a class that represents a table in a SQL database, each attribute of the class represents a column, with a name and a type.
+使用 ORM,您通常会在 SQL 数据库中创建一个代表映射的类,该类的每个属性代表一个列,具有名称和类型。
-For example a class `Pet` could represent a SQL table `pets`.
+例如,一个类`Pet`可以表示一个 SQL 表`pets`。
And each *instance* object of that class represents a row in the database.
-For example an object `orion_cat` (an instance of `Pet`) could have an attribute `orion_cat.type`, for the column `type`. And the value of that attribute could be, e.g. `"cat"`.
+又例如,一个对象`orion_cat`(`Pet`的一个实例)可以有一个属性`orion_cat.type`, 对标数据库中的`type`列。 并且该属性的值可以是其它,例如`"cat"`。
-These ORMs also have tools to make the connections or relations between tables or entities.
+这些 ORM 还具有在表或实体之间建立关系的工具(比如创建多表关系)。
-This way, you could also have an attribute `orion_cat.owner` and the owner would contain the data for this pet's owner, taken from the table *owners*.
+因此,`orion_cat.owner.name`可能是该宠物主人的姓名(来自表`owners`中的列`name`)。
-So, `orion_cat.owner.name` could be the name (from the `name` column in the `owners` table) of this pet's owner.
+这样,您还可以拥有一个属性`orion_cat.owner`,它包含该宠物所有者的数据,这些数据取自另外一个表。
-It could have a value like `"Arquilian"`.
+它可能有一个像`"Arquilian"`(一种业务逻辑)。
-And the ORM will do all the work to get the information from the corresponding table *owners* when you try to access it from your pet object.
+当您尝试从您的宠物对象访问它时,ORM 将完成所有工作以从相应的表*所有者那里再获取信息。
-Common ORMs are for example: Django-ORM (part of the Django framework), SQLAlchemy ORM (part of SQLAlchemy, independent of framework) and Peewee (independent of framework), among others.
+常见的 ORM 例如:Django-ORM(Django 框架的一部分)、SQLAlchemy ORM(SQLAlchemy 的一部分,独立于框架)和 Peewee(独立于框架)等。
-Here we will see how to work with **SQLAlchemy ORM**.
+在这里,我们将看到如何使用**SQLAlchemy ORM**。
-In a similar way you could use any other ORM.
+以类似的方式,您也可以使用任何其他 ORM。
-!!! tip
- There's an equivalent article using Peewee here in the docs.
+!!! !!! tip
+ 在文档中也有一篇使用 Peewee 的等效的文章。
-## File structure
+## 文件结构
-For these examples, let's say you have a directory named `my_super_project` that contains a sub-directory called `sql_app` with a structure like this:
+对于这些示例,假设您有一个名为的目录`my_super_project`,其中包含一个名为的子目录`sql_app`,其结构如下:
```
.
+.
└── sql_app
├── __init__.py
├── crud.py
@@ -83,13 +84,14 @@ For these examples, let's say you have a directory named `my_super_project` that
└── schemas.py
```
-The file `__init__.py` is just an empty file, but it tells Python that `sql_app` with all its modules (Python files) is a package.
+该文件`__init__.py`只是一个空文件,但它告诉 Python 其中`sql_app`的所有模块(Python 文件)都是一个包。
-Now let's see what each file/module does.
+现在让我们看看每个文件/模块的作用。
## Install `SQLAlchemy`
-First you need to install `SQLAlchemy`:
+!!! tip
+ SQLAlchemy 模型`User`包含一个`hashed_password`,它应该是一个包含散列的安全密码。
-
-## Interact with the database directly
-
-If you want to explore the SQLite database (file) directly, independently of FastAPI, to debug its contents, add tables, columns, records, modify data, etc. you can use DB Browser for SQLite.
-
-It will look like this:
-
-
-
-You can also use an online SQLite browser like SQLite Viewer or ExtendsClass.
-
-## Alternative DB session with middleware
-
-If you can't use dependencies with `yield` -- for example, if you are not using **Python 3.7** and can't install the "backports" mentioned above for **Python 3.6** -- you can set up the session in a "middleware" in a similar way.
-
-A "middleware" is basically a function that is always executed for each request, with some code executed before, and some code executed after the endpoint function.
-
-### Create a middleware
-
-The middleware we'll add (just a function) will create a new SQLAlchemy `SessionLocal` for each request, add it to the request and then close it once the request is finished.
-
-=== "Python 3.9+"
-
- ```Python hl_lines="12-20"
- {!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
- ```
-
-=== "Python 3.6+"
-
- ```Python hl_lines="14-22"
- {!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
- ```
-
-!!! info
- We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
-
- And then we close it in the `finally` block.
-
- This way we make sure the database session is always closed after the request. Even if there was an exception while processing the request.
-
-### About `request.state`
-
-`request.state` is a property of each `Request` object. It is there to store arbitrary objects attached to the request itself, like the database session in this case. You can read more about it in Starlette's docs about `Request` state.
-
-For us in this case, it helps us ensure a single database session is used through all the request, and then closed afterwards (in the middleware).
-
-### Dependencies with `yield` or middleware
-
-Adding a **middleware** here is similar to what a dependency with `yield` does, with some differences:
-
-* It requires more code and is a bit more complex.
-* The middleware has to be an `async` function.
- * If there is code in it that has to "wait" for the network, it could "block" your application there and degrade performance a bit.
- * Although it's probably not very problematic here with the way `SQLAlchemy` works.
- * But if you added more code to the middleware that had a lot of I/O waiting, it could then be problematic.
-* A middleware is run for *every* request.
- * So, a connection will be created for every request.
- * Even when the *path operation* that handles that request didn't need the DB.
-
-!!! tip
- It's probably better to use dependencies with `yield` when they are enough for the use case.
-
-!!! info
- Dependencies with `yield` were added recently to **FastAPI**.
-
- A previous version of this tutorial only had the examples with a middleware and there are probably several applications using the middleware for database session management.
+打开浏览器进入 http://127.0.0.1:8000/docs。
+
++ 您将能够与您的FastAPI应用程序交互,从真实数据库中读取数据: +
+ +
+
+
+ 如果您想独立于 FastAPI 直接浏览 SQLite 数据库(文件)以调试其内容、添加表、列、记录、修改数据等,您可以使用SQLite 的 DB Browser +
+ ++ 它看起来像这样: +
+ +
+
+
+ 您还可以使用SQLite Viewer或ExtendsClass等在线 SQLite 浏览器。 +
+ +
+ 如果你不能使用依赖项yield——例如,如果你没有使用Python 3.7并且不能安装上面提到的Python 3.6的“backports” ——你可以在类似的“中间件”中设置会话方法。
+
+ “中间件”基本功能是一个为每个请求执行的函数在请求之前进行执行相应的代码,以及在请求执行之后执行相应的代码。 +
+ +
+ 我们将添加中间件(只是一个函数)将为每个请求创建一个新的 SQLAlchemySessionLocal,将其添加到请求中,然后在请求完成后关闭它。
+
+ === "Python 3.9+" + +
{!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
+
+
+
++ === "Python 3.6+" + +
{!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
+
+
+
+
+ !!! !!! info
+ 我们将SessionLocal()请求的创建和处理放在一个try块中。
+
然后我们在finally块中关闭它。
+
+通过这种方式,我们确保数据库会话在请求后始终关闭,即使在处理请求时出现异常也会关闭。 Even if there was an exception while processing the request.
+
+
+request.state
+
+ request.state是每个Request对象的属性。 它用于存储附加到请求本身的任意对象,例如本例中的数据库会话。 您可以在Starlette 的关于Requeststate的文档中了解更多信息。
+
+ 对于这种情况下,它帮助我们确保在所有请求中使用单个数据库会话,然后关闭(在中间件中)。 +
+ +yield依赖项与使用中间件的区别
+
+ !!! info
+ yield的依赖项是最近刚加入FastAPI中的。
+
async函数。 SQLAlchemy工作方式可能不是很成问题。
+
+ !!! !!! tip
+ tyield当依赖项 足以满足用例时,使用tyield依赖项方法会更好。
+
+ !!! 在此处添加中间件与yield的依赖项的作用效果类似,但也有一些区别:
+
所以本教程的先前版本只有带有中间件的示例,并且可能有多个应用程序使用中间件进行数据库会话管理。
+
From fc7ccbbab057700719f83dfa862b7939e410dbf3 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:08 +0800
Subject: [PATCH 161/163] New translations static-files.md (Chinese Simplified)
---
docs/zh/docs/tutorial/static-files.md | 38 +++++++++++++--------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md
index 7a0c36af3f4c5..48c361d914e67 100644
--- a/docs/zh/docs/tutorial/static-files.md
+++ b/docs/zh/docs/tutorial/static-files.md
@@ -1,39 +1,39 @@
-# Static Files
+# 静态文件
-You can serve static files automatically from a directory using `StaticFiles`.
+您可以使用 `StaticFiles`从目录中自动提供静态文件。
-## Use `StaticFiles`
+## 使用`StaticFiles`
-* Import `StaticFiles`.
-* "Mount" a `StaticFiles()` instance in a specific path.
+* 导入`StaticFiles`。
+* "挂载"(Mount) 一个 `StaticFiles()` 实例到一个指定路径。
```Python hl_lines="2 6"
{!../../../docs_src/static_files/tutorial001.py!}
```
-!!! note "Technical Details"
- You could also use `from starlette.staticfiles import StaticFiles`.
+!!! !!! note "技术细节"
+ 你也可以用 `from starlette.staticfiles import StaticFiles`。
- **FastAPI** provides the same `starlette.staticfiles` as `fastapi.staticfiles` just as a convenience for you, the developer. But it actually comes directly from Starlette.
+ **FastAPI** 提供了和 `starlette.staticfiles` 相同的 `fastapi.staticfiles` ,只是为了方便你,开发者。 但它确实来自Starlette。
-### What is "Mounting"
+### 什么是"挂载"(Mounting)
-"Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
+"挂载" 表示在特定路径添加一个完全"独立的"应用,然后负责处理所有子路径。
-This is different from using an `APIRouter` as a mounted application is completely independent. The OpenAPI and docs from your main application won't include anything from the mounted application, etc.
+这与使用`APIRouter`不同,因为安装的应用程序是完全独立的。 OpenAPI和来自你主应用的文档不会包含已挂载应用的任何东西等等。
-You can read more about this in the **Advanced User Guide**.
+你可以在**高级用户指南**中了解更多。
-## Details
+## 细节
-The first `"/static"` refers to the sub-path this "sub-application" will be "mounted" on. So, any path that starts with `"/static"` will be handled by it.
+这个 "子应用" 会被 "挂载" 到第一个 `"/static"` 指向的子路径。 因此,任何以`"/static"`开头的路径都会被它处理。
-The `directory="static"` refers to the name of the directory that contains your static files.
+`directory="static"` 指向包含你的静态文件的目录名字。
-The `name="static"` gives it a name that can be used internally by **FastAPI**.
+`name="static"` 提供了一个能被**FastAPI**内部使用的名字。
-All these parameters can be different than "`static`", adjust them with the needs and specific details of your own application.
+所有这些参数可以不同于"`static`",根据你应用的需要和具体细节调整它们。
-## More info
+## 更多信息
-For more details and options check Starlette's docs about Static Files.
+更多细节和选择查阅 Starlette's docs about Static Files.
From aeed60812a725298a3765e153fd520e4e665c086 Mon Sep 17 00:00:00 2001
From: Sefank <12670778+Sefank@users.noreply.github.com>
Date: Wed, 26 Jul 2023 16:55:10 +0800
Subject: [PATCH 162/163] New translations testing.md (Chinese Simplified)
---
docs/zh/docs/tutorial/testing.md | 121 ++++++++++++++++---------------
1 file changed, 62 insertions(+), 59 deletions(-)
diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md
index 3609d39d9f5b1..b1e467f73482c 100644
--- a/docs/zh/docs/tutorial/testing.md
+++ b/docs/zh/docs/tutorial/testing.md
@@ -1,114 +1,117 @@
-# Testing
+# 测试
-Thanks to Starlette, testing **FastAPI** applications is easy and enjoyable.
+感谢 Starlette,测试**FastAPI** 应用轻松又愉快。
-It is based on HTTPX, which in turn is designed based on Requests, so it's very familiar and intuitive.
+它基于 HTTPX, 而HTTPX又是基于Requests设计的,所以很相似且易懂。
-With it, you can use pytest directly with **FastAPI**.
+有了它,你可以直接与**FastAPI**一起使用 pytest。
-## Using `TestClient`
+## 使用 `TestClient`
-!!! info
- To use `TestClient`, first install `httpx`.
+!!! !!! 信息
+ 要使用 `TestClient`,先要安装 `httpx`.
- E.g. `pip install httpx`.
+ E.g. 例:`pip install httpx`.
-Import `TestClient`.
+导入 `TestClient`.
-Create a `TestClient` by passing your **FastAPI** application to it.
+通过传入你的**FastAPI**应用创建一个 `TestClient` 。
-Create functions with a name that starts with `test_` (this is standard `pytest` conventions).
+创建名字以 `test_` 开头的函数(这是标准的 `pytest` 约定)。
-Use the `TestClient` object the same way as you do with `httpx`.
+像使用 `httpx` 那样使用 `TestClient` 对象。
-Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
+为你需要检查的地方用标准的Python表达式写个简单的 `assert` 语句(重申,标准的`pytest`)。
```Python hl_lines="2 12 15-18"
{!../../../docs_src/app_testing/tutorial001.py!}
```
-!!! tip
- Notice that the testing functions are normal `def`, not `async def`.
+!!! !!! 提示
+ 注意测试函数是普通的 `def`,不是 `async def`。
- And the calls to the client are also normal calls, not using `await`.
+ 还有client的调用也是普通的调用,不是用 `await`。
- This allows you to use `pytest` directly without complications.
+ 这让你可以直接使用 `pytest` 而不会遇到麻烦。
-!!! note "Technical Details"
- You could also use `from starlette.testclient import TestClient`.
+!!! !!! note "技术细节"
+ 你也可以用 `from starlette.testclient import TestClient`。
- **FastAPI** provides the same `starlette.testclient` as `fastapi.testclient` just as a convenience for you, the developer. But it comes directly from Starlette.
+ **FastAPI** 提供了和 `starlette.testclient` 一样的 `fastapi.testclient`,只是为了方便开发者。 但它直接来自Starlette。
-!!! tip
- If you want to call `async` functions in your tests apart from sending requests to your FastAPI application (e.g. asynchronous database functions), have a look at the [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} in the advanced tutorial.
+!!! !!! 提示
+ 除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下 [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} 。
-## Separating tests
+## 分离测试
-In a real application, you probably would have your tests in a different file.
+在实际应用中,你可能会把你的测试放在另一个文件里。
-And your **FastAPI** application might also be composed of several files/modules, etc.
+您的**FastAPI**应用程序也可能由一些文件/模块组成等等。
-### **FastAPI** app file
+### **FastAPI** app 文件
-Let's say you have a file structure as described in [Bigger Applications](./bigger-applications.md){.internal-link target=_blank}:
+假设你有一个像 [更大的应用](./bigger-applications.md){.internal-link target=_blank} 中所描述的文件结构:
```
.
+.
├── app
│ ├── __init__.py
│ └── main.py
```
-In the file `main.py` you have your **FastAPI** app:
+在 `main.py` 文件中你有一个 **FastAPI** app:
```Python
{!../../../docs_src/app_testing/main.py!}
```
-### Testing file
+### 测试文件
-Then you could have a file `test_main.py` with your tests. It could live on the same Python package (the same directory with a `__init__.py` file):
+然后你会有一个包含测试的文件 `test_main.py` 。 app可以像Python包那样存在(一样是目录,但有个 `__init__.py` 文件):
``` hl_lines="5"
.
+.
├── app
│ ├── __init__.py
│ ├── main.py
│ └── test_main.py
```
-Because this file is in the same package, you can use relative imports to import the object `app` from the `main` module (`main.py`):
+因为这文件在同一个包中,所以你可以通过相对导入从 `main` 模块(`main.py`)导入`app`对象:
```Python hl_lines="3"
{!../../../docs_src/app_testing/test_main.py!}
```
-...and have the code for the tests just like before.
+...然后测试代码和之前一样的。
-## Testing: extended example
+## 测试:扩展示例
-Now let's extend this example and add more details to see how to test different parts.
+现在让我们扩展这个例子,并添加更多细节,看下如何测试不同部分。
-### Extended **FastAPI** app file
+### 扩展后的 **FastAPI** app 文件
-Let's continue with the same file structure as before:
+让我们继续之前的文件结构:
```
.
+.
├── app
│ ├── __init__.py
│ ├── main.py
│ └── test_main.py
```
-Let's say that now the file `main.py` with your **FastAPI** app has some other **path operations**.
+假设现在包含**FastAPI** app的文件 `main.py` 有些其他**路径操作**。
-It has a `GET` operation that could return an error.
+有个 `GET` 操作会返回错误。
-It has a `POST` operation that could return several errors.
+有个 `POST` 操作会返回一些错误。
-Both *path operations* require an `X-Token` header.
+所有*路径操作* 都需要一个`X-Token` 头。
=== "Python 3.10+"
@@ -130,7 +133,7 @@ Both *path operations* require an `X-Token` header.
=== "Python 3.10+ non-Annotated"
- !!! tip
+ !!! !!! tip
Prefer to use the `Annotated` version if possible.
```Python
@@ -139,43 +142,43 @@ Both *path operations* require an `X-Token` header.
=== "Python 3.6+ non-Annotated"
- !!! tip
+ !!! !!! tip
Prefer to use the `Annotated` version if possible.
```Python
{!> ../../../docs_src/app_testing/app_b/main.py!}
```
-### Extended testing file
+### 扩展后的测试文件
-You could then update `test_main.py` with the extended tests:
+然后您可以使用扩展后的测试更新`test_main.py`:
```Python
{!> ../../../docs_src/app_testing/app_b/test_main.py!}
```
-Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `httpx`, or even how to do it with `requests`, as HTTPX's design is based on Requests' design.
+每当你需要客户端在请求中传递信息,但你不知道如何传递时,你可以通过搜索(谷歌)如何用 `httpx`做,或者是用 `requests` 做,毕竟HTTPX的设计是基于Requests的设计的。
-Then you just do the same in your tests.
+接着只需在测试中同样操作。
E.g.:
-* To pass a *path* or *query* parameter, add it to the URL itself.
-* To pass a JSON body, pass a Python object (e.g. a `dict`) to the parameter `json`.
-* If you need to send *Form Data* instead of JSON, use the `data` parameter instead.
-* To pass *headers*, use a `dict` in the `headers` parameter.
-* For *cookies*, a `dict` in the `cookies` parameter.
+* 传一个*路径* 或*查询* 参数,添加到URL上。
+* 传一个JSON体,传一个Python对象(例如一个`dict`)到参数 `json`。
+* 如果你需要发送 *Form Data* 而不是 JSON,使用 `data` 参数。
+* 要发送 *headers*,传 `dict` 给 `headers` 参数。
+* 对于 *cookies*,传 `dict` 给 `cookies` 参数。
-For more information about how to pass data to the backend (using `httpx` or the `TestClient`) check the HTTPX documentation.
+关于如何传数据给后端的更多信息 (使用`httpx` 或 `TestClient`),请查阅 HTTPX 文档.
-!!! info
- Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models.
+!!! !!! 信息
+ 注意 `TestClient` 接收可以被转化为JSON的数据,而不是Pydantic模型。
- If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the `jsonable_encoder` described in [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
+ 如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON Compatible Encoder](encoder.md){.internal-link target=_blank}介绍的`jsonable_encoder` 。
-## Run it
+## 运行起来
-After that, you just need to install `pytest`:
+之后,你只需要安装 `pytest`: