Browse Source

Merge branch 'master' into fix-duplicate-special-dependency-handling

pull/12406/head
Peter Volf 7 months ago
committed by GitHub
parent
commit
a11d975455
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      docs/de/docs/advanced/async-tests.md
  2. 91
      docs/de/docs/advanced/security/http-basic-auth.md
  3. 12
      docs/de/docs/tutorial/response-status-code.md
  4. 16
      docs/en/docs/advanced/additional-responses.md
  5. 52
      docs/en/docs/advanced/additional-status-codes.md
  6. 120
      docs/en/docs/advanced/advanced-dependencies.md
  7. 16
      docs/en/docs/advanced/async-tests.md
  8. 20
      docs/en/docs/advanced/behind-a-proxy.md
  9. 12
      docs/en/docs/advanced/middleware.md
  10. 30
      docs/en/docs/how-to/extending-openapi.md
  11. 6
      docs/en/docs/how-to/graphql.md
  12. 24
      docs/en/docs/release-notes.md
  13. 62
      docs/en/docs/tutorial/background-tasks.md
  14. 103
      docs/en/docs/tutorial/body-fields.md
  15. 92
      docs/en/docs/tutorial/body.md
  16. 4
      docs/en/docs/tutorial/static-files.md
  17. 57
      docs/fr/docs/python-types.md
  18. 24
      docs/fr/docs/tutorial/body.md
  19. 4
      docs/fr/docs/tutorial/debugging.md
  20. 56
      docs/fr/docs/tutorial/query-params-str-validations.md
  21. 24
      docs/fr/docs/tutorial/query-params.md
  22. 34
      docs/ko/docs/benchmarks.md
  23. 32
      docs/pl/docs/tutorial/first-steps.md
  24. 20
      docs/pt/docs/advanced/behind-a-proxy.md
  25. 359
      docs/pt/docs/tutorial/sql-databases.md

8
docs/de/docs/advanced/async-tests.md

@ -60,9 +60,7 @@ $ pytest
Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynchron aufgerufen werden soll:
```Python hl_lines="7"
{!../../docs_src/async_tests/test_main.py!}
```
{* ../../docs_src/async_tests/test_main.py hl[7] *}
/// tip | "Tipp"
@ -72,9 +70,7 @@ Beachten Sie, dass die Testfunktion jetzt `async def` ist und nicht nur `def` wi
Dann können wir einen `AsyncClient` mit der App erstellen und mit `await` asynchrone Requests an ihn senden.
```Python hl_lines="9-12"
{!../../docs_src/async_tests/test_main.py!}
```
{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
Das ist das Äquivalent zu:

91
docs/de/docs/advanced/security/http-basic-auth.md

@ -20,36 +20,7 @@ Wenn Sie dann den Benutzernamen und das Passwort eingeben, sendet der Browser di
* Diese gibt ein Objekt vom Typ `HTTPBasicCredentials` zurück:
* Es enthält den gesendeten `username` und das gesendete `password`.
//// tab | Python 3.9+
```Python hl_lines="4 8 12"
{!> ../../docs_src/security/tutorial006_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="2 7 11"
{!> ../../docs_src/security/tutorial006_an.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="2 6 10"
{!> ../../docs_src/security/tutorial006.py!}
```
////
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
Wenn Sie versuchen, die URL zum ersten Mal zu öffnen (oder in der Dokumentation auf den Button „Execute“ zu klicken), wird der Browser Sie nach Ihrem Benutzernamen und Passwort fragen:
<img src="/img/tutorial/security/image12.png">
@ -68,35 +39,7 @@ Um dies zu lösen, konvertieren wir zunächst den `username` und das `password`
Dann können wir `secrets.compare_digest()` verwenden, um sicherzustellen, dass `credentials.username` `"stanleyjobson"` und `credentials.password` `"swordfish"` ist.
//// tab | Python 3.9+
```Python hl_lines="1 12-24"
{!> ../../docs_src/security/tutorial007_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 12-24"
{!> ../../docs_src/security/tutorial007_an.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="1 11-21"
{!> ../../docs_src/security/tutorial007.py!}
```
////
{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
Dies wäre das gleiche wie:
@ -160,32 +103,4 @@ So ist Ihr Anwendungscode, dank der Verwendung von `secrets.compare_digest()`, v
Nachdem Sie festgestellt haben, dass die Anmeldeinformationen falsch sind, geben Sie eine `HTTPException` mit dem Statuscode 401 zurück (derselbe, der auch zurückgegeben wird, wenn keine Anmeldeinformationen angegeben werden) und fügen den Header `WWW-Authenticate` hinzu, damit der Browser die Anmeldeaufforderung erneut anzeigt:
//// tab | Python 3.9+
```Python hl_lines="26-30"
{!> ../../docs_src/security/tutorial007_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="26-30"
{!> ../../docs_src/security/tutorial007_an.py!}
```
////
//// tab | Python 3.8+ nicht annotiert
/// tip | "Tipp"
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
```Python hl_lines="23-27"
{!> ../../docs_src/security/tutorial007.py!}
```
////
{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}

12
docs/de/docs/tutorial/response-status-code.md

@ -8,9 +8,7 @@ So wie ein Responsemodell, können Sie auch einen HTTP-Statuscode für die Respo
* `@app.delete()`
* usw.
```Python hl_lines="6"
{!../../docs_src/response_status_code/tutorial001.py!}
```
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
/// note | "Hinweis"
@ -76,9 +74,7 @@ Um mehr über Statuscodes zu lernen, und welcher wofür verwendet wird, lesen Si
Schauen wir uns das vorherige Beispiel noch einmal an:
```Python hl_lines="6"
{!../../docs_src/response_status_code/tutorial001.py!}
```
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
`201` ist der Statuscode für „Created“ („Erzeugt“).
@ -86,9 +82,7 @@ Aber Sie müssen sich nicht daran erinnern, welcher dieser Codes was bedeutet.
Sie können die Hilfsvariablen von `fastapi.status` verwenden.
```Python hl_lines="1 6"
{!../../docs_src/response_status_code/tutorial002.py!}
```
{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
Diese sind nur eine Annehmlichkeit und enthalten dieselbe Nummer, aber auf diese Weise können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden:

16
docs/en/docs/advanced/additional-responses.md

@ -26,9 +26,7 @@ Each of those response `dict`s can have a key `model`, containing a Pydantic mod
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!}
```
{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *}
/// note
@ -177,9 +175,7 @@ You can use this same `responses` parameter to add different media types for the
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!}
```
{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
/// note
@ -207,9 +203,7 @@ For example, you can declare a response with a status code `404` that uses a Pyd
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!}
```
{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *}
It will all be combined and included in your OpenAPI, and shown in the API docs:
@ -243,9 +237,7 @@ You can use that technique to reuse some predefined responses in your *path oper
For example:
```Python hl_lines="13-17 26"
{!../../docs_src/additional_responses/tutorial004.py!}
```
{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
## More information about OpenAPI responses

52
docs/en/docs/advanced/additional-status-codes.md

@ -14,57 +14,7 @@ But you also want it to accept new items. And when the items didn't exist before
To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
//// tab | Python 3.10+
```Python hl_lines="4 25"
{!> ../../docs_src/additional_status_codes/tutorial001_an_py310.py!}
```
////
//// tab | Python 3.9+
```Python hl_lines="4 25"
{!> ../../docs_src/additional_status_codes/tutorial001_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="4 26"
{!> ../../docs_src/additional_status_codes/tutorial001_an.py!}
```
////
//// tab | Python 3.10+ non-Annotated
/// tip
Prefer to use the `Annotated` version if possible.
///
```Python hl_lines="2 23"
{!> ../../docs_src/additional_status_codes/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip
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_an_py310.py hl[4,25] *}
/// warning

120
docs/en/docs/advanced/advanced-dependencies.md

@ -18,35 +18,7 @@ Not the class itself (which is already a callable), but an instance of that clas
To do that, we declare a method `__call__`:
//// tab | Python 3.9+
```Python hl_lines="12"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="11"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip
Prefer to use the `Annotated` version if possible.
///
```Python hl_lines="10"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *}
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.
@ -54,35 +26,7 @@ In this case, this `__call__` is what **FastAPI** will use to check for addition
And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency:
//// tab | Python 3.9+
```Python hl_lines="9"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="8"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip
Prefer to use the `Annotated` version if possible.
///
```Python hl_lines="7"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *}
In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code.
@ -90,35 +34,7 @@ In this case, **FastAPI** won't ever touch or care about `__init__`, we will use
We could create an instance of this class with:
//// tab | Python 3.9+
```Python hl_lines="18"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="17"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip
Prefer to use the `Annotated` version if possible.
///
```Python hl_lines="16"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *}
And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`.
@ -134,35 +50,7 @@ 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`:
//// tab | Python 3.9+
```Python hl_lines="22"
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="21"
{!> ../../docs_src/dependencies/tutorial011_an.py!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip
Prefer to use the `Annotated` version if possible.
///
```Python hl_lines="20"
{!> ../../docs_src/dependencies/tutorial011.py!}
```
////
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *}
/// tip

16
docs/en/docs/advanced/async-tests.md

@ -32,15 +32,11 @@ For a simple example, let's consider a file structure similar to the one describ
The file `main.py` would have:
```Python
{!../../docs_src/async_tests/main.py!}
```
{* ../../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!}
```
{* ../../docs_src/async_tests/test_main.py *}
## Run it
@ -60,9 +56,7 @@ $ pytest
The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously:
```Python hl_lines="7"
{!../../docs_src/async_tests/test_main.py!}
```
{* ../../docs_src/async_tests/test_main.py hl[7] *}
/// tip
@ -72,9 +66,7 @@ Note that the test function is now `async def` instead of just `def` as before w
Then we can create an `AsyncClient` with the app, and send async requests to it, using `await`.
```Python hl_lines="9-12"
{!../../docs_src/async_tests/test_main.py!}
```
{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
This is the equivalent to:

20
docs/en/docs/advanced/behind-a-proxy.md

@ -18,9 +18,7 @@ In this case, the original path `/app` would actually be served at `/api/v1/app`
Even though all your code is written assuming there's just `/app`.
```Python hl_lines="6"
{!../../docs_src/behind_a_proxy/tutorial001.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *}
And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to the app server (probably Uvicorn via FastAPI CLI), keeping your application convinced that it is being served at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`.
@ -98,9 +96,7 @@ You can get the current `root_path` used by your application for each request, i
Here we are including it in the message just for demonstration purposes.
```Python hl_lines="8"
{!../../docs_src/behind_a_proxy/tutorial001.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
Then, if you start Uvicorn with:
@ -127,9 +123,7 @@ The response would be something like:
Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app:
```Python hl_lines="3"
{!../../docs_src/behind_a_proxy/tutorial002.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn.
@ -309,9 +303,7 @@ If you pass a custom list of `servers` and there's a `root_path` (because your A
For example:
```Python hl_lines="4-7"
{!../../docs_src/behind_a_proxy/tutorial003.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
Will generate an OpenAPI schema like:
@ -358,9 +350,7 @@ The docs UI will interact with the server that you select.
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!}
```
{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
and then it won't include it in the OpenAPI schema.

12
docs/en/docs/advanced/middleware.md

@ -57,17 +57,13 @@ Enforces that all incoming requests must either be `https` or `wss`.
Any incoming request to `http` or `ws` will be redirected to the secure scheme instead.
```Python hl_lines="2 6"
{!../../docs_src/advanced_middleware/tutorial001.py!}
```
{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
## `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!}
```
{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
The following arguments are supported:
@ -81,9 +77,7 @@ Handles GZip responses for any request that includes `"gzip"` in the `Accept-Enc
The middleware will handle both standard and streaming responses.
```Python hl_lines="2 6"
{!../../docs_src/advanced_middleware/tutorial003.py!}
```
{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
The following arguments are supported:

30
docs/en/docs/how-to/extending-openapi.md

@ -43,25 +43,24 @@ For example, let's add <a href="https://github.com/Rebilly/ReDoc/blob/master/doc
First, write all your **FastAPI** application as normally:
```Python hl_lines="1 4 7-9"
{!../../docs_src/extending_openapi/tutorial001.py!}
```
{* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *}
### 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!}
```
{* ../../docs_src/extending_openapi/tutorial001.py hl[2,15:21] *}
### 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!}
```
{* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *}
### Cache the OpenAPI schema
@ -71,17 +70,18 @@ That way, your application won't have to generate the schema every time a user o
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!}
```
{* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *}
### Override the method
Now you can replace the `.openapi()` method with your new function.
```Python hl_lines="29"
{!../../docs_src/extending_openapi/tutorial001.py!}
```
{* ../../docs_src/extending_openapi/tutorial001.py hl[29] *}
### Check it

6
docs/en/docs/how-to/graphql.md

@ -35,9 +35,9 @@ Depending on your use case, you might prefer to use a different library, but if
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!}
```
{* ../../docs_src/graphql/tutorial001.py hl[3,22,25:26] *}
You can learn more about Strawberry in the <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry documentation</a>.

24
docs/en/docs/release-notes.md

@ -9,6 +9,27 @@ hide:
### Docs
* 📝 Update includes in `docs/fr/docs/tutorial/body.md`. PR [#12596](https://github.com/fastapi/fastapi/pull/12596) by [@kantandane](https://github.com/kantandane).
* 📝 Update includes in `docs/fr/docs/tutorial/debugging.md`. PR [#12595](https://github.com/fastapi/fastapi/pull/12595) by [@kantandane](https://github.com/kantandane).
* 📝 Update includes in `docs/fr/docs/tutorial/query-params-str-validations.md`. PR [#12591](https://github.com/fastapi/fastapi/pull/12591) by [@kantandane](https://github.com/kantandane).
* 📝 Update includes in `docs/fr/docs/tutorial/query-params.md`. PR [#12589](https://github.com/fastapi/fastapi/pull/12589) by [@kantandane](https://github.com/kantandane).
* 📝 Update includes in `docs/en/tutorial/body-fields.md`. PR [#12588](https://github.com/fastapi/fastapi/pull/12588) by [@lucaromagnoli](https://github.com/lucaromagnoli).
* 📝 Update includes in `docs/de/docs/tutorial/response-status-code.md`. PR [#12585](https://github.com/fastapi/fastapi/pull/12585) by [@abejaranoh](https://github.com/abejaranoh).
* 📝 Update includes in `docs/en/docs/tutorial/body.md`. PR [#12586](https://github.com/fastapi/fastapi/pull/12586) by [@lucaromagnoli](https://github.com/lucaromagnoli).
* 📝 Update includes in `docs/en/docs/advanced/behind-a-proxy.md`. PR [#12583](https://github.com/fastapi/fastapi/pull/12583) by [@imjuanleonard](https://github.com/imjuanleonard).
* 📝 Update includes syntax for `docs/pl/docs/tutorial/first-steps.md`. PR [#12584](https://github.com/fastapi/fastapi/pull/12584) by [@sebkozlo](https://github.com/sebkozlo).
* 📝 Update includes in `docs/en/docs/advanced/middleware.md`. PR [#12582](https://github.com/fastapi/fastapi/pull/12582) by [@montanarograziano](https://github.com/montanarograziano).
* 📝 Update includes in `docs/en/docs/advanced/additional-status-codes.md`. PR [#12577](https://github.com/fastapi/fastapi/pull/12577) by [@krishnamadhavan](https://github.com/krishnamadhavan).
* 📝 Update includes in `docs/en/docs/advanced/advanced-dependencies.md`. PR [#12578](https://github.com/fastapi/fastapi/pull/12578) by [@krishnamadhavan](https://github.com/krishnamadhavan).
* 📝 Update includes in `docs/en/docs/advanced/additional-responses.md`. PR [#12576](https://github.com/fastapi/fastapi/pull/12576) by [@krishnamadhavan](https://github.com/krishnamadhavan).
* 📝 Update includes in `docs/en/docs/tutorial/static-files.md`. PR [#12575](https://github.com/fastapi/fastapi/pull/12575) by [@lucaromagnoli](https://github.com/lucaromagnoli).
* 📝 Update includes in `docs/en/docs/advanced/async-tests.md`. PR [#12568](https://github.com/fastapi/fastapi/pull/12568) by [@krishnamadhavan](https://github.com/krishnamadhavan).
* 📝 Update includes in `docs/pt/docs/advanced/behind-a-proxy.md`. PR [#12563](https://github.com/fastapi/fastapi/pull/12563) by [@asmioglou](https://github.com/asmioglou).
* 📝 Update includes in `docs/de/docs/advanced/security/http-basic-auth.md`. PR [#12561](https://github.com/fastapi/fastapi/pull/12561) by [@Nimitha-jagadeesha](https://github.com/Nimitha-jagadeesha).
* 📝 Update includes in `docs/en/docs/tutorial/background-tasks.md`. PR [#12559](https://github.com/fastapi/fastapi/pull/12559) by [@FarhanAliRaza](https://github.com/FarhanAliRaza).
* 📝 Update includes in `docs/fr/docs/python-types.md`. PR [#12558](https://github.com/fastapi/fastapi/pull/12558) by [@Ismailtlem](https://github.com/Ismailtlem).
* 📝 Update includes in `docs/en/docs/how-to/graphql.md`. PR [#12564](https://github.com/fastapi/fastapi/pull/12564) by [@philipokiokio](https://github.com/philipokiokio).
* 📝 Update includes in `docs/en/docs/how-to/extending-openapi.md`. PR [#12562](https://github.com/fastapi/fastapi/pull/12562) by [@philipokiokio](https://github.com/philipokiokio).
* 📝 Update includes for `docs/en/docs/how-to/configure-swagger-ui.md`. PR [#12556](https://github.com/fastapi/fastapi/pull/12556) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update includes for `docs/en/docs/how-to/separate-openapi-schemas.md`. PR [#12555](https://github.com/fastapi/fastapi/pull/12555) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update includes for `docs/en/docs/advanced/security/http-basic-auth.md`. PR [#12553](https://github.com/fastapi/fastapi/pull/12553) by [@tiangolo](https://github.com/tiangolo).
@ -21,6 +42,9 @@ hide:
### Translations
* 📝 Update includes in `docs/de/docs/advanced/async-tests.md`. PR [#12567](https://github.com/fastapi/fastapi/pull/12567) by [@imjuanleonard](https://github.com/imjuanleonard).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/sql-databases.md`. PR [#12530](https://github.com/fastapi/fastapi/pull/12530) by [@ilacftemp](https://github.com/ilacftemp).
* 🌐 Add Korean translation for `docs/ko/docs/benchmarks.md`. PR [#12540](https://github.com/fastapi/fastapi/pull/12540) by [@Limsunoh](https://github.com/Limsunoh).
* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/separate-openapi-schemas.md`. PR [#12518](https://github.com/fastapi/fastapi/pull/12518) by [@ilacftemp](https://github.com/ilacftemp).
* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/deployment/index.md`. PR [#12521](https://github.com/fastapi/fastapi/pull/12521) by [@codingjenny](https://github.com/codingjenny).
* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/deployment/cloud.md`. PR [#12522](https://github.com/fastapi/fastapi/pull/12522) by [@codingjenny](https://github.com/codingjenny).

62
docs/en/docs/tutorial/background-tasks.md

@ -15,9 +15,7 @@ This includes, for example:
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!}
```
{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
**FastAPI** will create the object of type `BackgroundTasks` for you and pass it as that parameter.
@ -33,17 +31,13 @@ In this case, the task function will write to a file (simulating sending an emai
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!}
```
{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
## 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!}
```
{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
`.add_task()` receives as arguments:
@ -57,57 +51,9 @@ Using `BackgroundTasks` also works with the dependency injection system, you can
**FastAPI** knows what to do in each case and how to reuse the same object, so that all the background tasks are merged together and are run in the background afterwards:
//// tab | Python 3.10+
```Python hl_lines="13 15 22 25"
{!> ../../docs_src/background_tasks/tutorial002_an_py310.py!}
```
{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
////
//// tab | Python 3.9+
```Python hl_lines="13 15 22 25"
{!> ../../docs_src/background_tasks/tutorial002_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="14 16 23 26"
{!> ../../docs_src/background_tasks/tutorial002_an.py!}
```
////
//// tab | 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!}
```
////
//// tab | Python 3.8+ 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.

103
docs/en/docs/tutorial/body-fields.md

@ -6,57 +6,8 @@ The same way you can declare additional validation and metadata in *path operati
First, you have to import it:
//// tab | Python 3.10+
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *}
```Python hl_lines="4"
{!> ../../docs_src/body_fields/tutorial001_an_py310.py!}
```
////
//// tab | Python 3.9+
```Python hl_lines="4"
{!> ../../docs_src/body_fields/tutorial001_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="4"
{!> ../../docs_src/body_fields/tutorial001_an.py!}
```
////
//// tab | 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!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip
Prefer to use the `Annotated` version if possible.
///
```Python hl_lines="4"
{!> ../../docs_src/body_fields/tutorial001.py!}
```
////
/// warning
@ -68,57 +19,7 @@ Notice that `Field` is imported directly from `pydantic`, not from `fastapi` as
You can then use `Field` with model attributes:
//// tab | Python 3.10+
```Python hl_lines="11-14"
{!> ../../docs_src/body_fields/tutorial001_an_py310.py!}
```
////
//// tab | Python 3.9+
```Python hl_lines="11-14"
{!> ../../docs_src/body_fields/tutorial001_an_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="12-15"
{!> ../../docs_src/body_fields/tutorial001_an.py!}
```
////
//// tab | 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!}
```
////
//// tab | Python 3.8+ non-Annotated
/// tip
Prefer to use the `Annotated` version if possible.
///
```Python hl_lines="11-14"
{!> ../../docs_src/body_fields/tutorial001.py!}
```
////
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *}
`Field` works the same way as `Query`, `Path` and `Body`, it has all the same parameters, etc.

92
docs/en/docs/tutorial/body.md

@ -22,21 +22,7 @@ As it is discouraged, the interactive docs with Swagger UI won't show the docume
First, you need to import `BaseModel` from `pydantic`:
//// tab | Python 3.10+
```Python hl_lines="2"
{!> ../../docs_src/body/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="4"
{!> ../../docs_src/body/tutorial001.py!}
```
////
{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
## Create your data model
@ -44,21 +30,8 @@ Then you declare your data model as a class that inherits from `BaseModel`.
Use standard Python types for all the attributes:
//// tab | Python 3.10+
```Python hl_lines="5-9"
{!> ../../docs_src/body/tutorial001_py310.py!}
```
////
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
//// tab | Python 3.8+
```Python hl_lines="7-11"
{!> ../../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.
@ -86,21 +59,7 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
To add it to your *path operation*, declare it the same way you declared path and query parameters:
//// tab | Python 3.10+
```Python hl_lines="16"
{!> ../../docs_src/body/tutorial001_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="18"
{!> ../../docs_src/body/tutorial001.py!}
```
////
{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
...and declare its type as the model you created, `Item`.
@ -167,21 +126,7 @@ It improves editor support for Pydantic models, with:
Inside of the function, you can access all the attributes of the model object directly:
//// tab | Python 3.10+
```Python hl_lines="19"
{!> ../../docs_src/body/tutorial002_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="21"
{!> ../../docs_src/body/tutorial002.py!}
```
////
## Request body + path parameters
@ -189,21 +134,8 @@ 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**.
//// tab | Python 3.10+
```Python hl_lines="15-16"
{!> ../../docs_src/body/tutorial003_py310.py!}
```
////
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
//// tab | Python 3.8+
```Python hl_lines="17-18"
{!> ../../docs_src/body/tutorial003.py!}
```
////
## Request body + path + query parameters
@ -211,21 +143,7 @@ You can also declare **body**, **path** and **query** parameters, all at the sam
**FastAPI** will recognize each of them and take the data from the correct place.
//// tab | Python 3.10+
```Python hl_lines="16"
{!> ../../docs_src/body/tutorial004_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="18"
{!> ../../docs_src/body/tutorial004.py!}
```
////
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
The function parameters will be recognized as follows:

4
docs/en/docs/tutorial/static-files.md

@ -7,9 +7,7 @@ You can serve static files automatically from a directory using `StaticFiles`.
* Import `StaticFiles`.
* "Mount" a `StaticFiles()` instance in a specific path.
```Python hl_lines="2 6"
{!../../docs_src/static_files/tutorial001.py!}
```
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
/// note | "Technical Details"

57
docs/fr/docs/python-types.md

@ -23,9 +23,7 @@ Si vous êtes un expert Python, et que vous savez déjà **tout** sur les annota
Prenons un exemple simple :
```Python
{!../../docs_src/python_types/tutorial001.py!}
```
{*../../docs_src/python_types/tutorial001.py*}
Exécuter ce programe affiche :
@ -39,9 +37,7 @@ La fonction :
* Convertit la première lettre de chaque paramètre en majuscules grâce à `title()`.
* Concatène les résultats avec un espace entre les deux.
```Python hl_lines="2"
{!../../docs_src/python_types/tutorial001.py!}
```
{*../../docs_src/python_types/tutorial001.py hl[2] *}
### Limitations
@ -84,9 +80,7 @@ C'est tout.
Ce sont des annotations de types :
```Python hl_lines="1"
{!../../docs_src/python_types/tutorial002.py!}
```
{*../../docs_src/python_types/tutorial002.py hl[1] *}
À ne pas confondre avec la déclaration de valeurs par défaut comme ici :
@ -114,9 +108,7 @@ Vous pouvez donc dérouler les options jusqu'à trouver la méthode à laquelle
Cette fonction possède déjà des annotations de type :
```Python hl_lines="1"
{!../../docs_src/python_types/tutorial003.py!}
```
{*../../docs_src/python_types/tutorial003.py hl[1] *}
Comme l'éditeur connaît le type des variables, vous n'avez pas seulement l'auto-complétion, mais aussi de la détection d'erreurs :
@ -124,9 +116,7 @@ Comme l'éditeur connaît le type des variables, vous n'avez pas seulement l'aut
Maintenant que vous avez connaissance du problème, convertissez `age` en <abbr title="string">chaîne de caractères</abbr> grâce à `str(age)` :
```Python hl_lines="2"
{!../../docs_src/python_types/tutorial004.py!}
```
{*../../docs_src/python_types/tutorial004.py hl[2] *}
## Déclarer des types
@ -145,9 +135,7 @@ Comme par exemple :
* `bool`
* `bytes`
```Python hl_lines="1"
{!../../docs_src/python_types/tutorial005.py!}
```
{*../../docs_src/python_types/tutorial005.py hl[1] *}
### Types génériques avec des paramètres de types
@ -163,9 +151,7 @@ Par exemple, définissons une variable comme `list` de `str`.
Importez `List` (avec un `L` majuscule) depuis `typing`.
```Python hl_lines="1"
{!../../docs_src/python_types/tutorial006.py!}
```
{*../../docs_src/python_types/tutorial006.py hl[1] *}
Déclarez la variable, en utilisant la syntaxe des deux-points (`:`).
@ -173,9 +159,7 @@ Et comme type, mettez `List`.
Les listes étant un type contenant des types internes, mettez ces derniers entre crochets (`[`, `]`) :
```Python hl_lines="4"
{!../../docs_src/python_types/tutorial006.py!}
```
{*../../docs_src/python_types/tutorial006.py hl[4] *}
/// tip | "Astuce"
@ -201,9 +185,7 @@ Et pourtant, l'éditeur sait qu'elle est de type `str` et pourra donc vous aider
C'est le même fonctionnement pour déclarer un `tuple` ou un `set` :
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial007.py!}
```
{*../../docs_src/python_types/tutorial007.py hl[1,4] *}
Dans cet exemple :
@ -216,9 +198,7 @@ Pour définir un `dict`, il faut lui passer 2 paramètres, séparés par une vir
Le premier paramètre de type est pour les clés et le second pour les valeurs du dictionnaire (`dict`).
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial008.py!}
```
{*../../docs_src/python_types/tutorial008.py hl[1,4] *}
Dans cet exemple :
@ -230,9 +210,7 @@ Dans cet exemple :
Vous pouvez aussi utiliser `Optional` pour déclarer qu'une variable a un type, comme `str` mais qu'il est "optionnel" signifiant qu'il pourrait aussi être `None`.
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial009.py!}
```
{*../../docs_src/python_types/tutorial009.py hl[1,4] *}
Utiliser `Optional[str]` plutôt que `str` permettra à l'éditeur de vous aider à détecter les erreurs où vous supposeriez qu'une valeur est toujours de type `str`, alors qu'elle pourrait aussi être `None`.
@ -255,15 +233,12 @@ Vous pouvez aussi déclarer une classe comme type d'une variable.
Disons que vous avez une classe `Person`, avec une variable `name` :
```Python hl_lines="1-3"
{!../../docs_src/python_types/tutorial010.py!}
```
{*../../docs_src/python_types/tutorial010.py hl[1:3] *}
Vous pouvez ensuite déclarer une variable de type `Person` :
```Python hl_lines="6"
{!../../docs_src/python_types/tutorial010.py!}
```
{*../../docs_src/python_types/tutorial010.py hl[6] *}
Et vous aurez accès, encore une fois, au support complet offert par l'éditeur :
@ -283,9 +258,7 @@ Ainsi, votre éditeur vous offrira un support adapté pour l'objet résultant.
Extrait de la documentation officielle de **Pydantic** :
```Python
{!../../docs_src/python_types/tutorial011.py!}
```
{*../../docs_src/python_types/tutorial011.py*}
/// info

24
docs/fr/docs/tutorial/body.md

@ -22,9 +22,7 @@ Ceci étant découragé, la documentation interactive générée par Swagger UI
Commencez par importer la classe `BaseModel` du module `pydantic` :
```Python hl_lines="4"
{!../../docs_src/body/tutorial001.py!}
```
{* ../../docs_src/body/tutorial001.py hl[4] *}
## Créez votre modèle de données
@ -32,9 +30,7 @@ Déclarez ensuite votre modèle de données en tant que classe qui hérite de `B
Utilisez les types Python standard pour tous les attributs :
```Python hl_lines="7-11"
{!../../docs_src/body/tutorial001.py!}
```
{* ../../docs_src/body/tutorial001.py hl[7:11] *}
Tout comme pour la déclaration de paramètres de requête, quand un attribut de modèle a une valeur par défaut, il n'est pas nécessaire. Sinon, cet attribut doit être renseigné dans le corps de la requête. Pour rendre ce champ optionnel simplement, utilisez `None` comme valeur par défaut.
@ -62,9 +58,7 @@ Par exemple, le modèle ci-dessus déclare un "objet" JSON (ou `dict` Python) te
Pour l'ajouter à votre *opération de chemin*, déclarez-le comme vous déclareriez des paramètres de chemin ou de requête :
```Python hl_lines="18"
{!../../docs_src/body/tutorial001.py!}
```
{* ../../docs_src/body/tutorial001.py hl[18] *}
...et déclarez que son type est le modèle que vous avez créé : `Item`.
@ -131,9 +125,7 @@ Ce qui améliore le support pour les modèles Pydantic avec :
Dans la fonction, vous pouvez accéder à tous les attributs de l'objet du modèle directement :
```Python hl_lines="21"
{!../../docs_src/body/tutorial002.py!}
```
{* ../../docs_src/body/tutorial002.py hl[21] *}
## Corps de la requête + paramètres de chemin
@ -141,9 +133,7 @@ Vous pouvez déclarer des paramètres de chemin et un corps de requête pour la
**FastAPI** est capable de reconnaître que les paramètres de la fonction qui correspondent aux paramètres de chemin doivent être **récupérés depuis le chemin**, et que les paramètres de fonctions déclarés comme modèles Pydantic devraient être **récupérés depuis le corps de la requête**.
```Python hl_lines="17-18"
{!../../docs_src/body/tutorial003.py!}
```
{* ../../docs_src/body/tutorial003.py hl[17:18] *}
## Corps de la requête + paramètres de chemin et de requête
@ -151,9 +141,7 @@ Vous pouvez aussi déclarer un **corps**, et des paramètres de **chemin** et de
**FastAPI** saura reconnaître chacun d'entre eux et récupérer la bonne donnée au bon endroit.
```Python hl_lines="18"
{!../../docs_src/body/tutorial004.py!}
```
{* ../../docs_src/body/tutorial004.py hl[18] *}
Les paramètres de la fonction seront reconnus comme tel :

4
docs/fr/docs/tutorial/debugging.md

@ -6,9 +6,7 @@ Vous pouvez connecter le <abbr title="En anglais: debugger">débogueur</abbr> da
Dans votre application FastAPI, importez et exécutez directement `uvicorn` :
```Python hl_lines="1 15"
{!../../docs_src/debugging/tutorial001.py!}
```
{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
### À propos de `__name__ == "__main__"`

56
docs/fr/docs/tutorial/query-params-str-validations.md

@ -4,9 +4,7 @@
Commençons avec cette application pour exemple :
```Python hl_lines="9"
{!../../docs_src/query_params_str_validations/tutorial001.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial001.py hl[9] *}
Le paramètre de requête `q` a pour type `Union[str, None]` (ou `str | None` en Python 3.10), signifiant qu'il est de type `str` mais pourrait aussi être égal à `None`, et bien sûr, la valeur par défaut est `None`, donc **FastAPI** saura qu'il n'est pas requis.
@ -26,17 +24,13 @@ Nous allons imposer que bien que `q` soit un paramètre optionnel, dès qu'il es
Pour cela, importez d'abord `Query` depuis `fastapi` :
```Python hl_lines="3"
{!../../docs_src/query_params_str_validations/tutorial002.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[3] *}
## Utiliser `Query` comme valeur par défaut
Construisez ensuite la valeur par défaut de votre paramètre avec `Query`, en choisissant 50 comme `max_length` :
```Python hl_lines="9"
{!../../docs_src/query_params_str_validations/tutorial002.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *}
Comme nous devons remplacer la valeur par défaut `None` dans la fonction par `Query()`, nous pouvons maintenant définir la valeur par défaut avec le paramètre `Query(default=None)`, il sert le même objectif qui est de définir cette valeur par défaut.
@ -86,17 +80,13 @@ Cela va valider les données, montrer une erreur claire si ces dernières ne son
Vous pouvez aussi rajouter un second paramètre `min_length` :
```Python hl_lines="9"
{!../../docs_src/query_params_str_validations/tutorial003.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial003.py hl[9] *}
## Ajouter des validations par expressions régulières
On peut définir une <abbr title="Une expression régulière, regex ou regexp est une suite de caractères qui définit un pattern de correspondance pour les chaînes de caractères.">expression régulière</abbr> à laquelle le paramètre doit correspondre :
```Python hl_lines="10"
{!../../docs_src/query_params_str_validations/tutorial004.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial004.py hl[10] *}
Cette expression régulière vérifie que la valeur passée comme paramètre :
@ -114,9 +104,7 @@ De la même façon que vous pouvez passer `None` comme premier argument pour l'u
Disons que vous déclarez le paramètre `q` comme ayant une longueur minimale de `3`, et une valeur par défaut étant `"fixedquery"` :
```Python hl_lines="7"
{!../../docs_src/query_params_str_validations/tutorial005.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *}
/// note | "Rappel"
@ -146,9 +134,7 @@ q: Union[str, None] = Query(default=None, min_length=3)
Donc pour déclarer une valeur comme requise tout en utilisant `Query`, il faut utiliser `...` comme premier argument :
```Python hl_lines="7"
{!../../docs_src/query_params_str_validations/tutorial006.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *}
/// info
@ -164,9 +150,7 @@ Quand on définit un paramètre de requête explicitement avec `Query` on peut a
Par exemple, pour déclarer un paramètre de requête `q` qui peut apparaître plusieurs fois dans une URL, on écrit :
```Python hl_lines="9"
{!../../docs_src/query_params_str_validations/tutorial011.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *}
Ce qui fait qu'avec une URL comme :
@ -201,9 +185,7 @@ La documentation sera donc mise à jour automatiquement pour autoriser plusieurs
Et l'on peut aussi définir une liste de valeurs par défaut si aucune n'est fournie :
```Python hl_lines="9"
{!../../docs_src/query_params_str_validations/tutorial012.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *}
Si vous allez à :
@ -228,9 +210,7 @@ et la réponse sera :
Il est aussi possible d'utiliser directement `list` plutôt que `List[str]` :
```Python hl_lines="7"
{!../../docs_src/query_params_str_validations/tutorial013.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *}
/// note
@ -256,15 +236,11 @@ Il se peut donc que certains d'entre eux n'utilisent pas toutes les métadonnée
Vous pouvez ajouter un `title` :
```Python hl_lines="10"
{!../../docs_src/query_params_str_validations/tutorial007.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial007.py hl[10] *}
Et une `description` :
```Python hl_lines="13"
{!../../docs_src/query_params_str_validations/tutorial008.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *}
## Alias de paramètres
@ -284,9 +260,7 @@ Mais vous avez vraiment envie que ce soit exactement `item-query`...
Pour cela vous pouvez déclarer un `alias`, et cet alias est ce qui sera utilisé pour trouver la valeur du paramètre :
```Python hl_lines="9"
{!../../docs_src/query_params_str_validations/tutorial009.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *}
## Déprécier des paramètres
@ -296,9 +270,7 @@ Il faut qu'il continue à exister pendant un certain temps car vos clients l'uti
On utilise alors l'argument `deprecated=True` de `Query` :
```Python hl_lines="18"
{!../../docs_src/query_params_str_validations/tutorial010.py!}
```
{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *}
La documentation le présentera comme il suit :

24
docs/fr/docs/tutorial/query-params.md

@ -2,9 +2,7 @@
Quand vous déclarez des paramètres dans votre fonction de chemin qui ne font pas partie des paramètres indiqués dans le chemin associé, ces paramètres sont automatiquement considérés comme des paramètres de "requête".
```Python hl_lines="9"
{!../../docs_src/query_params/tutorial001.py!}
```
{* ../../docs_src/query_params/tutorial001.py hl[9] *}
La partie appelée requête (ou **query**) dans une URL est l'ensemble des paires clés-valeurs placées après le `?` , séparées par des `&`.
@ -63,9 +61,7 @@ Les valeurs des paramètres de votre fonction seront :
De la même façon, vous pouvez définir des paramètres de requête comme optionnels, en leur donnant comme valeur par défaut `None` :
```Python hl_lines="9"
{!../../docs_src/query_params/tutorial002.py!}
```
{* ../../docs_src/query_params/tutorial002.py hl[9] *}
Ici, le paramètre `q` sera optionnel, et aura `None` comme valeur par défaut.
@ -87,9 +83,7 @@ Le `Optional` dans `Optional[str]` n'est pas utilisé par **FastAPI** (**FastAPI
Vous pouvez aussi déclarer des paramètres de requête comme booléens (`bool`), **FastAPI** les convertira :
```Python hl_lines="9"
{!../../docs_src/query_params/tutorial003.py!}
```
{* ../../docs_src/query_params/tutorial003.py hl[9] *}
Avec ce code, en allant sur :
@ -131,9 +125,7 @@ Et vous n'avez pas besoin de les déclarer dans un ordre spécifique.
Ils seront détectés par leurs noms :
```Python hl_lines="8 10"
{!../../docs_src/query_params/tutorial004.py!}
```
{* ../../docs_src/query_params/tutorial004.py hl[8,10] *}
## Paramètres de requête requis
@ -143,9 +135,7 @@ Si vous ne voulez pas leur donner de valeur par défaut mais juste les rendre op
Mais si vous voulez rendre un paramètre de requête obligatoire, vous pouvez juste ne pas y affecter de valeur par défaut :
```Python hl_lines="6-7"
{!../../docs_src/query_params/tutorial005.py!}
```
{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
Ici le paramètre `needy` est un paramètre requis (ou obligatoire) de type `str`.
@ -189,9 +179,7 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
Et bien sur, vous pouvez définir certains paramètres comme requis, certains avec des valeurs par défaut et certains entièrement optionnels :
```Python hl_lines="10"
{!../../docs_src/query_params/tutorial006.py!}
```
{* ../../docs_src/query_params/tutorial006.py hl[10] *}
Ici, on a donc 3 paramètres de requête :

34
docs/ko/docs/benchmarks.md

@ -0,0 +1,34 @@
# 벤치마크
독립적인 TechEmpower 벤치마크에 따르면 **FastAPI** 애플리케이션이 Uvicorn을 사용하여 <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">가장 빠른 Python 프레임워크 중 하나</a>로 실행되며, Starlette와 Uvicorn 자체(내부적으로 FastAPI가 사용하는 도구)보다 조금 아래에 위치합니다.
그러나 벤치마크와 비교를 확인할 때 다음 사항을 염두에 두어야 합니다.
## 벤치마크와 속도
벤치마크를 확인할 때, 일반적으로 여러 가지 유형의 도구가 동등한 것으로 비교되는 것을 볼 수 있습니다.
특히, Uvicorn, Starlette, FastAPI가 함께 비교되는 경우가 많습니다(다른 여러 도구와 함께).
도구가 해결하는 문제가 단순할수록 성능이 더 좋아집니다. 그리고 대부분의 벤치마크는 도구가 제공하는 추가 기능을 테스트하지 않습니다.
계층 구조는 다음과 같습니다:
* **Uvicorn**: ASGI 서버
* **Starlette**: (Uvicorn 사용) 웹 마이크로 프레임워크
* **FastAPI**: (Starlette 사용) API 구축을 위한 데이터 검증 등 여러 추가 기능이 포함된 API 마이크로 프레임워크
* **Uvicorn**:
* 서버 자체 외에는 많은 추가 코드가 없기 때문에 최고의 성능을 발휘합니다.
* 직접 Uvicorn으로 응용 프로그램을 작성하지는 않을 것입니다. 즉, 사용자의 코드에는 적어도 Starlette(또는 **FastAPI**)에서 제공하는 모든 코드가 포함되어야 합니다. 그렇게 하면 최종 응용 프로그램은 프레임워크를 사용하고 앱 코드와 버그를 최소화하는 것과 동일한 오버헤드를 갖게 됩니다.
* Uvicorn을 비교할 때는 Daphne, Hypercorn, uWSGI 등의 응용 프로그램 서버와 비교하세요.
* **Starlette**:
* Uvicorn 다음으로 좋은 성능을 발휘합니다. 사실 Starlette는 Uvicorn을 사용하여 실행됩니다. 따라서 더 많은 코드를 실행해야 하기 때문에 Uvicorn보다 "느려질" 수밖에 없습니다.
* 하지만 경로 기반 라우팅 등 간단한 웹 응용 프로그램을 구축할 수 있는 도구를 제공합니다.
* Starlette를 비교할 때는 Sanic, Flask, Django 등의 웹 프레임워크(또는 마이크로 프레임워크)와 비교하세요.
* **FastAPI**:
* Starlette가 Uvicorn을 사용하므로 Uvicorn보다 빨라질 수 없는 것과 마찬가지로, **FastAPI**는 Starlette를 사용하므로 더 빠를 수 없습니다.
* FastAPI는 Starlette에 추가적으로 더 많은 기능을 제공합니다. API를 구축할 때 거의 항상 필요한 데이터 검증 및 직렬화와 같은 기능들이 포함되어 있습니다. 그리고 이를 사용하면 문서 자동화 기능도 제공됩니다(문서 자동화는 응용 프로그램 실행 시 오버헤드를 추가하지 않고 시작 시 생성됩니다).
* FastAPI를 사용하지 않고 직접 Starlette(또는 Sanic, Flask, Responder 등)를 사용했다면 데이터 검증 및 직렬화를 직접 구현해야 합니다. 따라서 최종 응용 프로그램은 FastAPI를 사용한 것과 동일한 오버헤드를 가지게 될 것입니다. 많은 경우 데이터 검증 및 직렬화가 응용 프로그램에서 작성된 코드 중 가장 많은 부분을 차지합니다.
* 따라서 FastAPI를 사용함으로써 개발 시간, 버그, 코드 라인을 줄일 수 있으며, FastAPI를 사용하지 않았을 때와 동일하거나 더 나은 성능을 얻을 수 있습니다(코드에서 모두 구현해야 하기 때문에).
* FastAPI를 비교할 때는 Flask-apispec, NestJS, Molten 등 데이터 검증, 직렬화 및 문서화가 통합된 자동 데이터 검증, 직렬화 및 문서화를 제공하는 웹 응용 프로그램 프레임워크(또는 도구 집합)와 비교하세요.

32
docs/pl/docs/tutorial/first-steps.md

@ -2,9 +2,7 @@
Najprostszy plik FastAPI może wyglądać tak:
```Python
{!../../docs_src/first_steps/tutorial001.py!}
```
{* ../../docs_src/first_steps/tutorial001.py *}
Skopiuj to do pliku `main.py`.
@ -133,9 +131,7 @@ Możesz go również użyć do automatycznego generowania kodu dla klientów, kt
### Krok 1: zaimportuj `FastAPI`
```Python hl_lines="1"
{!../../docs_src/first_steps/tutorial001.py!}
```
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
`FastAPI` jest klasą, która zapewnia wszystkie funkcjonalności Twojego API.
@ -149,9 +145,7 @@ Oznacza to, że możesz korzystać ze wszystkich funkcjonalności <a href="https
### Krok 2: utwórz instancję `FastAPI`
```Python hl_lines="3"
{!../../docs_src/first_steps/tutorial001.py!}
```
{*../../docs_src/first_steps/tutorial001.py hl[3] *}
Zmienna `app` będzie tutaj "instancją" klasy `FastAPI`.
@ -171,9 +165,7 @@ $ uvicorn main:app --reload
Jeśli stworzysz swoją aplikację, np.:
```Python hl_lines="3"
{!../../docs_src/first_steps/tutorial002.py!}
```
{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
I umieścisz to w pliku `main.py`, to będziesz mógł tak wywołać `uvicorn`:
@ -250,9 +242,7 @@ Będziemy je również nazywali "**operacjami**".
#### Zdefiniuj *dekorator operacji na ścieżce*
```Python hl_lines="6"
{!../../docs_src/first_steps/tutorial001.py!}
```
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
`@app.get("/")` mówi **FastAPI** że funkcja poniżej odpowiada za obsługę żądań, które trafiają do:
@ -306,9 +296,7 @@ To jest nasza "**funkcja obsługująca ścieżkę**":
* **operacja**: to `get`.
* **funkcja**: to funkcja poniżej "dekoratora" (poniżej `@app.get("/")`).
```Python hl_lines="7"
{!../../docs_src/first_steps/tutorial001.py!}
```
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
Jest to funkcja Python.
@ -320,9 +308,7 @@ W tym przypadku jest to funkcja "asynchroniczna".
Możesz również zdefiniować to jako normalną funkcję zamiast `async def`:
```Python hl_lines="7"
{!../../docs_src/first_steps/tutorial003.py!}
```
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
/// note
@ -332,9 +318,7 @@ Jeśli nie znasz różnicy, sprawdź [Async: *"In a hurry?"*](../async.md#in-a-h
### Krok 5: zwróć zawartość
```Python hl_lines="8"
{!../../docs_src/first_steps/tutorial001.py!}
```
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
Możesz zwrócić `dict`, `list`, pojedynczą wartość jako `str`, `int`, itp.

20
docs/pt/docs/advanced/behind-a-proxy.md

@ -18,9 +18,7 @@ Nesse caso, o caminho original `/app` seria servido em `/api/v1/app`.
Embora todo o seu código esteja escrito assumindo que existe apenas `/app`.
```Python hl_lines="6"
{!../../docs_src/behind_a_proxy/tutorial001.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *}
E o proxy estaria **"removendo"** o **prefixo do caminho** dinamicamente antes de transmitir a solicitação para o servidor da aplicação (provavelmente Uvicorn via CLI do FastAPI), mantendo sua aplicação convencida de que está sendo servida em `/app`, para que você não precise atualizar todo o seu código para incluir o prefixo `/api/v1`.
@ -98,9 +96,7 @@ Você pode obter o `root_path` atual usado pela sua aplicação para cada solici
Aqui estamos incluindo ele na mensagem apenas para fins de demonstração.
```Python hl_lines="8"
{!../../docs_src/behind_a_proxy/tutorial001.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
Então, se você iniciar o Uvicorn com:
@ -127,9 +123,7 @@ A resposta seria algo como:
Alternativamente, se você não tiver uma maneira de fornecer uma opção de linha de comando como `--root-path` ou equivalente, você pode definir o parâmetro `--root-path` ao criar sua aplicação FastAPI:
```Python hl_lines="3"
{!../../docs_src/behind_a_proxy/tutorial002.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
Passar o `root_path`h para `FastAPI` seria o equivalente a passar a opção de linha de comando `--root-path` para Uvicorn ou Hypercorn.
@ -309,9 +303,7 @@ Se você passar uma lista personalizada de `servers` e houver um `root_path` (po
Por exemplo:
```Python hl_lines="4-7"
{!../../docs_src/behind_a_proxy/tutorial003.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
Gerará um OpenAPI schema como:
@ -358,9 +350,7 @@ A interface de documentação interagirá com o servidor que você selecionar.
Se você não quiser que o **FastAPI** inclua um servidor automático usando o `root_path`, você pode usar o parâmetro `root_path_in_servers=False`:
```Python hl_lines="9"
{!../../docs_src/behind_a_proxy/tutorial004.py!}
```
{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
e então ele não será incluído no OpenAPI schema.

359
docs/pt/docs/tutorial/sql-databases.md

@ -0,0 +1,359 @@
# Bancos de Dados SQL (Relacionais)
**FastAPI** não exige que você use um banco de dados SQL (relacional). Mas você pode usar **qualquer banco de dados** que quiser.
Aqui veremos um exemplo usando <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel</a>.
**SQLModel** é construído sobre <a href="https://www.sqlalchemy.org/" class="external-link" target="_blank">SQLAlchemy</a> e Pydantic. Ele foi criado pelo mesmo autor do **FastAPI** para ser o par perfeito para aplicações **FastAPI** que precisam usar **bancos de dados SQL**.
/// tip | Dica
Você pode usar qualquer outra biblioteca de banco de dados SQL ou NoSQL que quiser (em alguns casos chamadas de <abbr title="Object Relational Mapper, um termo sofisticado para uma biblioteca onde algumas classes representam tabelas SQL e instâncias representam linhas nessas tabelas">"ORMs"</abbr>), o FastAPI não obriga você a usar nada. 😎
///
Como o SQLModel é baseado no SQLAlchemy, você pode facilmente usar **qualquer banco de dados suportado** pelo SQLAlchemy (o que também os torna suportados pelo SQLModel), como:
* PostgreSQL
* MySQL
* SQLite
* Oracle
* Microsoft SQL Server, etc.
Neste exemplo, usaremos **SQLite**, porque ele usa um único arquivo e o Python tem suporte integrado. Assim, você pode copiar este exemplo e executá-lo como está.
Mais tarde, para sua aplicação em produção, você pode querer usar um servidor de banco de dados como o **PostgreSQL**.
/// tip | Dica
Existe um gerador de projetos oficial com **FastAPI** e **PostgreSQL** incluindo um frontend e mais ferramentas: <a href="https://github.com/fastapi/full-stack-fastapi-template" class="external-link" target="_blank">https://github.com/fastapi/full-stack-fastapi-template</a>
///
Este é um tutorial muito simples e curto, se você quiser aprender sobre bancos de dados em geral, sobre SQL ou recursos mais avançados, acesse a <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">documentação do SQLModel</a>.
## Instalar o `SQLModel`
Primeiro, certifique-se de criar seu [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e, em seguida, instalar o `sqlmodel`:
<div class="termy">
```console
$ pip install sqlmodel
---> 100%
```
</div>
## Criar o App com um Único Modelo
Vamos criar a primeira versão mais simples do app com um único modelo **SQLModel**.
Depois, vamos melhorá-lo aumentando a segurança e versatilidade com **múltiplos modelos** abaixo. 🤓
### Criar Modelos
Importe o `SQLModel` e crie um modelo de banco de dados:
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *}
A classe `Hero` é muito semelhante a um modelo Pydantic (na verdade, por baixo dos panos, ela *é um modelo Pydantic*).
Existem algumas diferenças:
* `table=True` informa ao SQLModel que este é um *modelo de tabela*, ele deve representar uma **tabela** no banco de dados SQL, não é apenas um *modelo de dados* (como seria qualquer outra classe Pydantic comum).
* `Field(primary_key=True)` informa ao SQLModel que o `id` é a **chave primária** no banco de dados SQL (você pode aprender mais sobre chaves primárias SQL na documentação do SQLModel).
Ao ter o tipo como `int | None`, o SQLModel saberá que essa coluna deve ser um `INTEGER` no banco de dados SQL e que ela deve ser `NULLABLE`.
* `Field(index=True)` informa ao SQLModel que ele deve criar um **índice SQL** para essa coluna, o que permitirá buscas mais rápidas no banco de dados ao ler dados filtrados por essa coluna.
O SQLModel saberá que algo declarado como `str` será uma coluna SQL do tipo `TEXT` (ou `VARCHAR`, dependendo do banco de dados).
### Criar um Engine
Um `engine` SQLModel (por baixo dos panos, ele é na verdade um `engine` do SQLAlchemy) é o que **mantém as conexões** com o banco de dados.
Você teria **um único objeto `engine`** para todo o seu código se conectar ao mesmo banco de dados.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *}
Usar `check_same_thread=False` permite que o FastAPI use o mesmo banco de dados SQLite em diferentes threads. Isso é necessário, pois **uma única requisição** pode usar **mais de uma thread** (por exemplo, em dependências).
Não se preocupe, com a forma como o código está estruturado, garantiremos que usamos **uma única *sessão* SQLModel por requisição** mais tarde, isso é realmente o que o `check_same_thread` está tentando conseguir.
### Criar as Tabelas
Em seguida, adicionamos uma função que usa `SQLModel.metadata.create_all(engine)` para **criar as tabelas** para todos os *modelos de tabela*.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *}
### Criar uma Dependência de Sessão
Uma **`Session`** é o que armazena os **objetos na memória** e acompanha as alterações necessárias nos dados, para então **usar o `engine`** para se comunicar com o banco de dados.
Vamos criar uma **dependência** do FastAPI com `yield` que fornecerá uma nova `Session` para cada requisição. Isso é o que garante que usamos uma única sessão por requisição. 🤓
Então, criamos uma dependência `Annotated` chamada `SessionDep` para simplificar o restante do código que usará essa dependência.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *}
### Criar Tabelas de Banco de Dados na Inicialização
Vamos criar as tabelas do banco de dados quando o aplicativo for iniciado.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *}
Aqui, criamos as tabelas em um evento de inicialização do aplicativo.
Para produção, você provavelmente usaria um script de migração que é executado antes de iniciar seu app. 🤓
/// tip | Dica
O SQLModel terá utilitários de migração envolvendo o Alembic, mas por enquanto, você pode usar o <a href="https://alembic.sqlalchemy.org/en/latest/" class="external-link" target="_blank">Alembic</a> diretamente.
///
### Criar um Hero
Como cada modelo SQLModel também é um modelo Pydantic, você pode usá-lo nas mesmas **anotações de tipo** que usaria para modelos Pydantic.
Por exemplo, se você declarar um parâmetro do tipo `Hero`, ele será lido do **corpo JSON**.
Da mesma forma, você pode declará-lo como o **tipo de retorno** da função, e então o formato dos dados aparecerá na interface de documentação automática da API.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *}
</details>
Aqui, usamos a dependência `SessionDep` (uma `Session`) para adicionar o novo `Hero` à instância `Session`, fazer commit das alterações no banco de dados, atualizar os dados no `hero` e então retorná-lo.
### Ler Heroes
Podemos **ler** `Hero`s do banco de dados usando um `select()`. Podemos incluir um `limit` e `offset` para paginar os resultados.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *}
### Ler um Único Hero
Podemos **ler** um único `Hero`.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *}
### Deletar um Hero
Também podemos **deletar** um `Hero`.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *}
### Executar o App
Você pode executar o app:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Então, vá para a interface `/docs`, você verá que o **FastAPI** está usando esses **modelos** para **documentar** a API, e ele também os usará para **serializar** e **validar** os dados.
<div class="screenshot">
<img src="/img/tutorial/sql-databases/image01.png">
</div>
## Atualizar o App com Múltiplos Modelos
Agora vamos **refatorar** este app um pouco para aumentar a **segurança** e **versatilidade**.
Se você verificar o app anterior, na interface você pode ver que, até agora, ele permite que o cliente decida o `id` do `Hero` a ser criado. 😱
Não deveríamos deixar isso acontecer, eles poderiam sobrescrever um `id` que já atribuimos na base de dados. Decidir o `id` deve ser feito pelo **backend** ou pelo **banco de dados**, **não pelo cliente**.
Além disso, criamos um `secret_name` para o hero, mas até agora estamos retornando ele em todos os lugares, isso não é muito **secreto**... 😅
Vamos corrigir essas coisas adicionando alguns **modelos extras**. Aqui é onde o SQLModel vai brilhar. ✨
### Criar Múltiplos Modelos
No **SQLModel**, qualquer classe de modelo que tenha `table=True` é um **modelo de tabela**.
E qualquer classe de modelo que não tenha `table=True` é um **modelo de dados**, esses são na verdade apenas modelos Pydantic (com alguns recursos extras pequenos). 🤓
Com o SQLModel, podemos usar a **herança** para **evitar duplicação** de todos os campos em todos os casos.
#### `HeroBase` - a classe base
Vamos começar com um modelo `HeroBase` que tem todos os **campos compartilhados** por todos os modelos:
* `name`
* `age`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *}
#### `Hero` - o *modelo de tabela*
Em seguida, vamos criar `Hero`, o verdadeiro *modelo de tabela*, com os **campos extras** que nem sempre estão nos outros modelos:
* `id`
* `secret_name`
Como `Hero` herda de `HeroBase`, ele **também** tem os **campos** declarados em `HeroBase`, então todos os campos para `Hero` são:
* `id`
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *}
#### `HeroPublic` - o *modelo de dados* público
Em seguida, criamos um modelo `HeroPublic`, que será **retornado** para os clientes da API.
Ele tem os mesmos campos que `HeroBase`, então não incluirá `secret_name`.
Finalmente, a identidade dos nossos heróis está protegida! 🥷
Ele também declara novamente `id: int`. Ao fazer isso, estamos fazendo um **contrato** com os clientes da API, para que eles possam sempre esperar que o `id` estará lá e será um `int` (nunca será `None`).
/// tip | Dica
Fazer com que o modelo de retorno garanta que um valor esteja sempre disponível e sempre seja um `int` (não `None`) é muito útil para os clientes da API, eles podem escrever código muito mais simples com essa certeza.
Além disso, **clientes gerados automaticamente** terão interfaces mais simples, para que os desenvolvedores que se comunicam com sua API possam ter uma experiência muito melhor trabalhando com sua API. 😎
///
Todos os campos em `HeroPublic` são os mesmos que em `HeroBase`, com `id` declarado como `int` (não `None`):
* `id`
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *}
#### `HeroCreate` - o *modelo de dados* para criar um hero
Agora criamos um modelo `HeroCreate`, este é o que **validará** os dados dos clientes.
Ele tem os mesmos campos que `HeroBase`, e também tem `secret_name`.
Agora, quando os clientes **criarem um novo hero**, eles enviarão o `secret_name`, ele será armazenado no banco de dados, mas esses nomes secretos não serão retornados na API para os clientes.
/// tip | Dica
É assim que você trataria **senhas**. Receba-as, mas não as retorne na API.
Você também faria um **hash** com os valores das senhas antes de armazená-los, **nunca os armazene em texto simples**.
///
Os campos de `HeroCreate` são:
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *}
#### `HeroUpdate` - o *modelo de dados* para atualizar um hero
Não tínhamos uma maneira de **atualizar um hero** na versão anterior do app, mas agora com **múltiplos modelos**, podemos fazer isso. 🎉
O *modelo de dados* `HeroUpdate` é um pouco especial, ele tem **todos os mesmos campos** que seriam necessários para criar um novo hero, mas todos os campos são **opcionais** (todos têm um valor padrão). Dessa forma, quando você atualizar um hero, poderá enviar apenas os campos que deseja atualizar.
Como todos os **campos realmente mudam** (o tipo agora inclui `None` e eles agora têm um valor padrão de `None`), precisamos **declarar novamente** todos eles.
Não precisamos herdar de `HeroBase`, pois estamos redeclarando todos os campos. Vou deixá-lo herdando apenas por consistência, mas isso não é necessário. É mais uma questão de gosto pessoal. 🤷
Os campos de `HeroUpdate` são:
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *}
### Criar com `HeroCreate` e retornar um `HeroPublic`
Agora que temos **múltiplos modelos**, podemos atualizar as partes do app que os utilizam.
Recebemos na requisição um *modelo de dados* `HeroCreate`, e a partir dele, criamos um *modelo de tabela* `Hero`.
Esse novo *modelo de tabela* `Hero` terá os campos enviados pelo cliente, e também terá um `id` gerado pelo banco de dados.
Em seguida, retornamos o mesmo *modelo de tabela* `Hero` como está na função. Mas como declaramos o `response_model` com o *modelo de dados* `HeroPublic`, o **FastAPI** usará `HeroPublic` para validar e serializar os dados.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *}
/// tip | Dica
Agora usamos `response_model=HeroPublic` em vez da **anotação de tipo de retorno** `-> HeroPublic` porque o valor que estamos retornando na verdade *não* é um `HeroPublic`.
Se tivéssemos declarado `-> HeroPublic`, seu editor e o linter reclamariam (com razão) que você está retornando um `Hero` em vez de um `HeroPublic`.
Ao declará-lo no `response_model`, estamos dizendo ao **FastAPI** para fazer o seu trabalho, sem interferir nas anotações de tipo e na ajuda do seu editor e de outras ferramentas.
///
### Ler Heroes com `HeroPublic`
Podemos fazer o mesmo que antes para **ler** `Hero`s, novamente, usamos `response_model=list[HeroPublic]` para garantir que os dados sejam validados e serializados corretamente.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *}
### Ler Um Hero com `HeroPublic`
Podemos **ler** um único herói:
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *}
### Atualizar um Hero com `HeroUpdate`
Podemos **atualizar um hero**. Para isso, usamos uma operação HTTP `PATCH`.
E no código, obtemos um `dict` com todos os dados enviados pelo cliente, **apenas os dados enviados pelo cliente**, excluindo quaisquer valores que estariam lá apenas por serem os valores padrão. Para fazer isso, usamos `exclude_unset=True`. Este é o truque principal. 🪄
Em seguida, usamos `hero_db.sqlmodel_update(hero_data)` para atualizar o `hero_db` com os dados de `hero_data`.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *}
### Deletar um Hero Novamente
**Deletar** um hero permanece praticamente o mesmo.
Não vamos satisfazer o desejo de refatorar tudo neste aqui. 😅
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *}
### Executar o App Novamente
Você pode executar o app novamente:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
If you go to the `/docs` API UI, you will see that it is now updated, and it won't expect to receive the `id` from the client when creating a hero, etc.
<div class="screenshot">
<img src="/img/tutorial/sql-databases/image02.png">
</div>
## Recapitulando
Você pode usar <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">**SQLModel**</a> para interagir com um banco de dados SQL e simplificar o código com *modelos de dados* e *modelos de tabela*.
Você pode aprender muito mais na documentação do **SQLModel**, há um mini <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">tutorial sobre como usar SQLModel com **FastAPI**</a> mais longo. 🚀
Loading…
Cancel
Save