If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="9 14"
+```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="4 9 10 11 12 25 26 27"
+```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write:
-```Python hl_lines="18 23"
+```Python hl_lines="18 23"
{!../../../docs_src/additional_responses/tutorial001.py!}
```
The generated responses in the OpenAPI for this *path operation* will be:
-```JSON hl_lines="3 4 5 6 7 8 9 10 11 12"
+```JSON hl_lines="3-12"
{
"responses": {
"404": {
The schemas are referenced to another place inside the OpenAPI schema:
-```JSON hl_lines="4 5 6 7 8 9 10 11 12 13 14 15 16"
+```JSON hl_lines="4-16"
{
"components": {
"schemas": {
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 20 21 22 23 24 28"
+```Python hl_lines="19-24 28"
{!../../../docs_src/additional_responses/tutorial002.py!}
```
And a response with a status code `200` that uses your `response_model`, but includes a custom `example`:
-```Python hl_lines="20 21 22 23 24 25 26 27 28 29 30 31"
+```Python hl_lines="20-31"
{!../../../docs_src/additional_responses/tutorial003.py!}
```
For example:
-```Python hl_lines="13 14 15 16 17 26"
+```Python hl_lines="13-17 26"
{!../../../docs_src/additional_responses/tutorial004.py!}
```
* Create a `metadata` object.
* Create a table `notes` using the `metadata` object.
-```Python hl_lines="4 14 16 17 18 19 20 21 22"
+```Python hl_lines="4 14 16-22"
{!../../../docs_src/async_sql_databases/tutorial001.py!}
```
* Create a `DATABASE_URL`.
* Create a `database` object.
-```Python hl_lines="3 9 12"
+```Python hl_lines="3 9 12"
{!../../../docs_src/async_sql_databases/tutorial001.py!}
```
* Create an `engine`.
* Create all the tables from the `metadata` object.
-```Python hl_lines="25 26 27 28"
+```Python hl_lines="25-28"
{!../../../docs_src/async_sql_databases/tutorial001.py!}
```
* Notes to be created (`NoteIn`).
* Notes to be returned (`Note`).
-```Python hl_lines="31 32 33 36 37 38 39"
+```Python hl_lines="31-33 36-39"
{!../../../docs_src/async_sql_databases/tutorial001.py!}
```
* Create your `FastAPI` application.
* Create event handlers to connect and disconnect from the database.
-```Python hl_lines="42 45 46 47 50 51 52"
+```Python hl_lines="42 45-47 50-52"
{!../../../docs_src/async_sql_databases/tutorial001.py!}
```
Create the *path operation function* to read notes:
-```Python hl_lines="55 56 57 58"
+```Python hl_lines="55-58"
{!../../../docs_src/async_sql_databases/tutorial001.py!}
```
Create the *path operation function* to create notes:
-```Python hl_lines="61 62 63 64 65"
+```Python hl_lines="61-65"
{!../../../docs_src/async_sql_databases/tutorial001.py!}
```
Then we can create an `AsyncClient` with the app, and send async requests to it, using `await`.
-```Python hl_lines="9 10"
+```Python hl_lines="9-10"
{!../../../docs_src/async_tests/test_main.py!}
```
The docs UI would also need the OpenAPI schema to declare that this API `server` is located at `/api/v1` (behind the proxy). For example:
-```JSON hl_lines="4 5 6 7 8"
+```JSON hl_lines="4-8"
{
"openapi": "3.0.2",
// More stuff here
For example:
-```Python hl_lines="4 5 6 7"
+```Python hl_lines="4-7"
{!../../../docs_src/behind_a_proxy/tutorial003.py!}
```
Will generate an OpenAPI schema like:
-```JSON hl_lines="5 6 7"
+```JSON hl_lines="5-7"
{
"openapi": "3.0.2",
// More stuff here
That way, the same route class can handle gzip compressed or uncompressed requests.
-```Python hl_lines="8 9 10 11 12 13 14 15"
+```Python hl_lines="8-15"
{!../../../docs_src/custom_request_and_route/tutorial001.py!}
```
Here we use it to create a `GzipRequest` from the original request.
-```Python hl_lines="18 19 20 21 22 23 24 25 26"
+```Python hl_lines="18-26"
{!../../../docs_src/custom_request_and_route/tutorial001.py!}
```
All we need to do is handle the request inside a `try`/`except` block:
-```Python hl_lines="13 15"
+```Python hl_lines="13 15"
{!../../../docs_src/custom_request_and_route/tutorial002.py!}
```
If an exception occurs, the`Request` instance will still be in scope, so we can read and make use of the request body when handling the error:
-```Python hl_lines="16 17 18"
+```Python hl_lines="16-18"
{!../../../docs_src/custom_request_and_route/tutorial002.py!}
```
In this example, the *path operations* under the `router` will use the custom `TimedRoute` class, and will have an extra `X-Response-Time` header in the response with the time it took to generate the response:
-```Python hl_lines="13 14 15 16 17 18 19 20"
+```Python hl_lines="13-20"
{!../../../docs_src/custom_request_and_route/tutorial003.py!}
```
Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
-```Python hl_lines="2 7"
+```Python hl_lines="2 7"
{!../../../docs_src/custom_response/tutorial001b.py!}
```
* Import `HTMLResponse`.
* Pass `HTMLResponse` as the parameter `content_type` of your *path operation*.
-```Python hl_lines="2 7"
+```Python hl_lines="2 7"
{!../../../docs_src/custom_response/tutorial002.py!}
```
The same example from above, returning an `HTMLResponse`, could look like:
-```Python hl_lines="2 7 19"
+```Python hl_lines="2 7 19"
{!../../../docs_src/custom_response/tutorial003.py!}
```
For example, it could be something like:
-```Python hl_lines="7 23 21"
+```Python hl_lines="7 21 23"
{!../../../docs_src/custom_response/tutorial004.py!}
```
!!! 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!}
```
This includes many libraries to interact with cloud storage, video processing, and others.
-```Python hl_lines="2 10 11"
+```Python hl_lines="2 10-11"
{!../../../docs_src/custom_response/tutorial008.py!}
```
In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
-```Python hl_lines="2 4"
+```Python hl_lines="2 4"
{!../../../docs_src/custom_response/tutorial010.py!}
```
First, write all your **FastAPI** application as normally:
-```Python hl_lines="1 4 7 8 9"
+```Python hl_lines="1 4 7-9"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
-```Python hl_lines="2 15 16 17 18 19 20"
+```Python hl_lines="2 15-20"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
-```Python hl_lines="21 22 23"
+```Python hl_lines="21-23"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
It will be generated only once, and then the same cached schema will be used for the next requests.
-```Python hl_lines="13 14 24 25"
+```Python hl_lines="13-14 24-25"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
* Import `StaticFiles`.
* "Mount" a `StaticFiles()` instance in a specific path.
-```Python hl_lines="7 11"
+```Python hl_lines="7 11"
{!../../../docs_src/extending_openapi/tutorial002.py!}
```
And similarly for ReDoc...
-```Python hl_lines="2 3 4 5 6 14 15 16 17 18 19 20 21 22 25 26 27 30 31 32 33 34 35 36"
+```Python hl_lines="2-6 14-22 25-27 30-36"
{!../../../docs_src/extending_openapi/tutorial002.py!}
```
Now, to be able to test that everything works, create a *path operation*:
-```Python hl_lines="39 40 41"
+```Python hl_lines="39-41"
{!../../../docs_src/extending_openapi/tutorial002.py!}
```
Import `graphene` and define your GraphQL data:
-```Python hl_lines="1 6 7 8 9 10"
+```Python hl_lines="1 6-10"
{!../../../docs_src/graphql/tutorial001.py!}
```
Then import and add Starlette's `GraphQLApp`:
-```Python hl_lines="3 14"
+```Python hl_lines="3 14"
{!../../../docs_src/graphql/tutorial001.py!}
```
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 7 8"
+```Python hl_lines="2 6-8"
{!../../../docs_src/advanced_middleware/tutorial002.py!}
```
For now, don't pay attention to the rest, only the imports:
-```Python hl_lines="3 4 5"
+```Python hl_lines="3-5"
{!../../../docs_src/nosql_databases/tutorial001.py!}
```
* Set defaults for timeouts.
* Return it.
-```Python hl_lines="12 13 14 15 16 17 18 19 20 21"
+```Python hl_lines="12-21"
{!../../../docs_src/nosql_databases/tutorial001.py!}
```
First, let's create a `User` model:
-```Python hl_lines="24 25 26 27 28"
+```Python hl_lines="24-28"
{!../../../docs_src/nosql_databases/tutorial001.py!}
```
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 32 33"
+```Python hl_lines="31-33"
{!../../../docs_src/nosql_databases/tutorial001.py!}
```
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 <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
-```Python hl_lines="36 37 38 39 40 41 42"
+```Python hl_lines="36-42"
{!../../../docs_src/nosql_databases/tutorial001.py!}
```
Also, Couchbase recommends not using a single `Bucket` object in multiple "<abbr title="A sequence of code being executed by the program, while at the same time, or at intervals, there can be others being executed too.">thread</abbr>s", so, we can just get the bucket directly and pass it to our utility functions:
-```Python hl_lines="49 50 51 52 53"
+```Python hl_lines="49-53"
{!../../../docs_src/nosql_databases/tutorial001.py!}
```
This part is pretty normal, most of the code is probably already familiar to you:
-```Python hl_lines="10 11 12 13 14 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54"
+```Python hl_lines="10-14 37-54"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
But as we are never calling `app.include_router(some_router)`, we need to set the `default_response_class` during creation of the `APIRouter`.
-```Python hl_lines="5 26"
+```Python hl_lines="5 26"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
* 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="17 18 19 22 23 29 30 31 32 33"
+```Python hl_lines="17-19 22-23 29-33"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
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!}
```
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!}
```
And then you can set cookies in that *temporal* response object.
-```Python hl_lines="1 8 9"
+```Python hl_lines="1 8-9"
{!../../../docs_src/response_cookies/tutorial002.py!}
```
Then set Cookies in it, and then return it:
-```Python hl_lines="10 11 12"
+```Python hl_lines="10-12"
{!../../../docs_src/response_cookies/tutorial001.py!}
```
For those cases, you can use the `jsonable_encoder` to convert your data before passing it to a response:
-```Python hl_lines="6 7 21 22"
+```Python hl_lines="6-7 21-22"
{!../../../docs_src/response_directly/tutorial001.py!}
```
And then you can set headers in that *temporal* response object.
-```Python hl_lines="1 7 8"
+```Python hl_lines="1 7-8"
{!../../../docs_src/response_headers/tutorial002.py!}
```
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:
-```Python hl_lines="10 11 12"
+```Python hl_lines="10-12"
{!../../../docs_src/response_headers/tutorial001.py!}
```
* It returns an object of type `HTTPBasicCredentials`:
* It contains the `username` and `password` sent.
-```Python hl_lines="2 6 10"
+```Python hl_lines="2 6 10"
{!../../../docs_src/security/tutorial006.py!}
```
For this, use the Python standard module <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> to check the username and password:
-```Python hl_lines="1 11 12 13"
+```Python hl_lines="1 11-13"
{!../../../docs_src/security/tutorial007.py!}
```
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 hl_lines="15 16 17 18 19"
+```Python hl_lines="15-19"
{!../../../docs_src/security/tutorial007.py!}
```
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 hl_lines="2 4 8 12 46 64 105 107 108 109 110 111 112 113 114 115 121 122 123 124 128 129 130 131 132 133 134 139 153"
+```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 153"
{!../../../docs_src/security/tutorial005.py!}
```
The `scopes` parameter receives a `dict` with each scope as a key and the description as the value:
-```Python hl_lines="62 63 64 65"
+```Python hl_lines="62-65"
{!../../../docs_src/security/tutorial005.py!}
```
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 in the `WWW-Authenticate` header (this is part of the spec).
-```Python hl_lines="105 107 108 109 110 111 112 113 114 115"
+```Python hl_lines="105 107-115"
{!../../../docs_src/security/tutorial005.py!}
```
We also verify that we have a user with that username, and if not, we raise that same exception we created before.
-```Python hl_lines="46 116 117 118 119 120 121 122 123 124 125 126 127"
+```Python hl_lines="46 116-127"
{!../../../docs_src/security/tutorial005.py!}
```
For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`.
-```Python hl_lines="128 129 130 131 132 133 134"
+```Python hl_lines="128-134"
{!../../../docs_src/security/tutorial005.py!}
```
You can use all the same validation features and tools you use for Pydantic models, like different data types and additional validations with `Field()`.
-```Python hl_lines="2 5 6 7 8 11"
+```Python hl_lines="2 5-8 11"
{!../../../docs_src/settings/tutorial001.py!}
```
Then you can use the new `settings` object in your application:
-```Python hl_lines="18 19 20"
+```Python hl_lines="18-20"
{!../../../docs_src/settings/tutorial001.py!}
```
And then use it in a file `main.py`:
-```Python hl_lines="3 11 12 13"
+```Python hl_lines="3 11-13"
{!../../../docs_src/settings/app01/main.py!}
```
Now we create a dependency that returns a new `config.Settings()`.
-```Python hl_lines="5 11 12"
+```Python hl_lines="5 11-12"
{!../../../docs_src/settings/app02/main.py!}
```
And then we can require it from the *path operation function* as a dependency and use it anywhere we need it.
-```Python hl_lines="16 18 19 20"
+```Python hl_lines="16 18-20"
{!../../../docs_src/settings/app02/main.py!}
```
Then it would be very easy to provide a different settings object during testing by creating a dependency override for `get_settings`:
-```Python hl_lines="8 9 12 21"
+```Python hl_lines="8-9 12 21"
{!../../../docs_src/settings/app02/test_main.py!}
```
And then update your `config.py` with:
-```Python hl_lines="9 10"
+```Python hl_lines="9-10"
{!../../../docs_src/settings/app03/config.py!}
```
We will create a `PeeweeConnectionState`:
-```Python hl_lines="10 11 12 13 14 15 16 17 18 19"
+```Python hl_lines="10-19"
{!../../../docs_src/sql_databases_peewee/sql_app/database.py!}
```
Import `db` from `database` (the file `database.py` from above) and use it here.
-```Python hl_lines="3 6 7 8 9 10 11 12 15 16 17 18 19 20 21"
+```Python hl_lines="3 6-12 15-21"
{!../../../docs_src/sql_databases_peewee/sql_app/models.py!}
```
Create all the same Pydantic models as in the SQLAlchemy tutorial:
-```Python hl_lines="16 17 18 21 22 25 26 27 28 29 30 34 35 38 39 42 43 44 45 46 47 48"
+```Python hl_lines="16-18 21-22 25-30 34-35 38-39 42-48"
{!../../../docs_src/sql_databases_peewee/sql_app/schemas.py!}
```
We are going to create a custom `PeeweeGetterDict` class and use it in all the same Pydantic *models* / schemas that use `orm_mode`:
-```Python hl_lines="3 8 9 10 11 12 13 31 49"
+```Python hl_lines="3 8-13 31 49"
{!../../../docs_src/sql_databases_peewee/sql_app/schemas.py!}
```
Create all the same CRUD utils as in the SQLAlchemy tutorial, all the code is very similar:
-```Python hl_lines="1 4 5 8 9 12 13 16 17 18 19 20 23 24 27 28 29 30"
+```Python hl_lines="1 4-5 8-9 12-13 16-20 23-24 27-30"
{!../../../docs_src/sql_databases_peewee/sql_app/crud.py!}
```
In a very simplistic way create the database tables:
-```Python hl_lines="9 10 11"
+```Python hl_lines="9-11"
{!../../../docs_src/sql_databases_peewee/sql_app/main.py!}
```
Create a dependency that will connect the database right at the beginning of a request and disconnect it at the end:
-```Python hl_lines="23 24 25 26 27 28 29"
+```Python hl_lines="23-29"
{!../../../docs_src/sql_databases_peewee/sql_app/main.py!}
```
For that, we need to create another `async` dependency `reset_db_state()` that is used as a sub-dependency in `get_db()`. It will set the value for the context variable (with just a default `dict`) that will be used as the database state for the whole request. And then the dependency `get_db()` will store in it the database state (connection, transactions, etc).
-```Python hl_lines="18 19 20"
+```Python hl_lines="18-20"
{!../../../docs_src/sql_databases_peewee/sql_app/main.py!}
```
So, you would reset it with:
-```Python hl_lines="3 4"
+```Python hl_lines="3-4"
async def reset_db_state():
database.db.obj._state._state.set(db_state_default.copy())
database.db.obj._state.reset()
Now, finally, here's the standard **FastAPI** *path operations* code.
-```Python hl_lines="32 33 34 35 36 37 40 41 42 43 46 47 48 49 50 51 52 53 56 57 58 59 60 61 62 65 66 67 68 71 72 73 74 75 76 77 78 79"
+```Python hl_lines="32-37 40-43 46-53 56-62 65-68 71-79"
{!../../../docs_src/sql_databases_peewee/sql_app/main.py!}
```
First, create the main, top-level, **FastAPI** application, and its *path operations*:
-```Python hl_lines="3 6 7 8"
+```Python hl_lines="3 6-8"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
This sub-application is just another standard FastAPI application, but this is the one that will be "mounted":
-```Python hl_lines="11 14 15 16"
+```Python hl_lines="11 14-16"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
In this case, it will be mounted at the path `/subapi`:
-```Python hl_lines="11 19"
+```Python hl_lines="11 19"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
* Declare a `Request` parameter in the *path operation* that will return a template.
* Use the `templates` you created to render and return a `TemplateResponse`, passing the `request` as one of the key-value pairs in the Jinja2 "context".
-```Python hl_lines="4 11 15 16"
+```Python hl_lines="4 11 15-16"
{!../../../docs_src/templates/tutorial001.py!}
```
So the new file structure looks like:
-``` hl_lines="9 10 11"
+``` hl_lines="9-11"
.
└── sql_app
├── __init__.py
But the rest of the session code is more or less the same, we just copy it.
-```Python hl_lines="8 9 10 11 12 13"
+```Python hl_lines="8-13"
{!../../../docs_src/sql_databases/sql_app/tests/test_sql_app.py!}
```
Now we create the dependency override and add it to the overrides for our app.
-```Python hl_lines="19 20 21 22 23 24 27"
+```Python hl_lines="19-24 27"
{!../../../docs_src/sql_databases/sql_app/tests/test_sql_app.py!}
```
Then we can just test the app as normally.
-```Python hl_lines="32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47"
+```Python hl_lines="32-47"
{!../../../docs_src/sql_databases/sql_app/tests/test_sql_app.py!}
```
And then **FastAPI** will call that override instead of the original dependency.
-```Python hl_lines="26 27 30"
+```Python hl_lines="26-27 30"
{!../../../docs_src/dependency_testing/tutorial001.py!}
```
When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement:
-```Python hl_lines="9 10 11 12 20 21 22 23 24"
+```Python hl_lines="9-12 20-24"
{!../../../docs_src/app_testing/tutorial003.py!}
```
For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket:
-```Python hl_lines="27 28 29 30 31"
+```Python hl_lines="27-31"
{!../../../docs_src/app_testing/tutorial002.py!}
```
For that you need to access the request directly.
-```Python hl_lines="1 7 8"
+```Python hl_lines="1 7-8"
{!../../../docs_src/using_request_directly/tutorial001.py!}
```
But it's the simplest way to focus on the server-side of WebSockets and have a working example:
-```Python hl_lines="2 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 41 42 43"
+```Python hl_lines="2 6-38 41-43"
{!../../../docs_src/websockets/tutorial001.py!}
```
In your **FastAPI** application, create a `websocket`:
-```Python hl_lines="1 46 47"
+```Python hl_lines="1 46-47"
{!../../../docs_src/websockets/tutorial001.py!}
```
In your WebSocket route you can `await` for messages and send messages.
-```Python hl_lines="48 49 50 51 52"
+```Python hl_lines="48-52"
{!../../../docs_src/websockets/tutorial001.py!}
```
They work the same way as for other FastAPI endpoints/*path operations*:
-```Python hl_lines="58 59 60 61 62 63 64 65 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83"
+```Python hl_lines="58-65 68-83"
{!../../../docs_src/websockets/tutorial002.py!}
```
And then mount that under a path.
-```Python hl_lines="2 3 22"
+```Python hl_lines="2-3 22"
{!../../../docs_src/wsgi/tutorial001.py!}
```
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"
+```Python hl_lines="2-3"
@app.get('/burgers')
async def read_burgers():
burgers = await get_burgers(2)
If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="9 14"
+```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="4 9 10 11 12 25 26 27"
+```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
You would do the same to declare `tuple`s and `set`s:
-```Python hl_lines="1 4"
+```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial007.py!}
```
The second type parameter is for the values of the `dict`:
-```Python hl_lines="1 4"
+```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
```
You can also use `Optional` to declare that a variable has a type, like `str`, but that it is "optional", which means that it could also be `None`:
-```Python hl_lines="1 4"
+```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial009.py!}
```
Let's say you have a class `Person`, with a name:
-```Python hl_lines="1 2 3"
+```Python hl_lines="1-3"
{!../../../docs_src/python_types/tutorial010.py!}
```
First, import `BackgroundTasks` and define a parameter in your *path operation function* with a type declaration of `BackgroundTasks`:
-```Python hl_lines="1 13"
+```Python hl_lines="1 13"
{!../../../docs_src/background_tasks/tutorial001.py!}
```
And as the write operation doesn't use `async` and `await`, we define the function with normal `def`:
-```Python hl_lines="6 7 8 9"
+```Python hl_lines="6-9"
{!../../../docs_src/background_tasks/tutorial001.py!}
```
**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 hl_lines="13 15 22 25"
+```Python hl_lines="13 15 22 25"
{!../../../docs_src/background_tasks/tutorial002.py!}
```
You import it and create an "instance" the same way you would with the class `FastAPI`:
-```Python hl_lines="1 3"
+```Python hl_lines="1 3"
{!../../../docs_src/bigger_applications/app/routers/users.py!}
```
Use it the same way you would use the `FastAPI` class:
-```Python hl_lines="6 11 16"
+```Python hl_lines="6 11 16"
{!../../../docs_src/bigger_applications/app/routers/users.py!}
```
And we don't want to have to explicitly type `/items/` and `tags=["items"]` in every *path operation* (we will be able to do it later):
-```Python hl_lines="6 11"
+```Python hl_lines="6 11"
{!../../../docs_src/bigger_applications/app/routers/items.py!}
```
But we can add custom `tags` and `responses` that will be applied to a specific *path operation*:
-```Python hl_lines="18 19"
+```Python hl_lines="18-19"
{!../../../docs_src/bigger_applications/app/routers/items.py!}
```
You import and create a `FastAPI` class as normally:
-```Python hl_lines="1 5"
+```Python hl_lines="1 5"
{!../../../docs_src/bigger_applications/app/main.py!}
```
And we can add a list of `dependencies` that will be added to all the *path operations* in the router and will be executed/solved for each request made to them. Note that, much like dependencies in *path operation decorators*, no value will be passed to your *path operation function*.
-```Python hl_lines="8 9 10 14 15 16 17 18 19 20"
+```Python hl_lines="8-10 14-20"
{!../../../docs_src/bigger_applications/app/main.py!}
```
You can then use `Field` with model attributes:
-```Python hl_lines="11 12 13 14"
+```Python hl_lines="11-14"
{!../../../docs_src/body_fields/tutorial001.py!}
```
And you can also declare body parameters as optional, by setting the default to `None`:
-```Python hl_lines="19 20 21"
+```Python hl_lines="19-21"
{!../../../docs_src/body_multiple_params/tutorial001.py!}
```
Then we can import `Set` and declare `tags` as a `set` of `str`:
-```Python hl_lines="1 14"
+```Python hl_lines="1 14"
{!../../../docs_src/body_nested_models/tutorial003.py!}
```
For example, we can define an `Image` model:
-```Python hl_lines="9 10 11"
+```Python hl_lines="9-11"
{!../../../docs_src/body_nested_models/tutorial004.py!}
```
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"
+```Python hl_lines="4 10"
{!../../../docs_src/body_nested_models/tutorial005.py!}
```
You can define arbitrarily deeply nested models:
-```Python hl_lines="9 14 20 23 27"
+```Python hl_lines="9 14 20 23 27"
{!../../../docs_src/body_nested_models/tutorial007.py!}
```
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 31 32 33 34 35"
+```Python hl_lines="30-35"
{!../../../docs_src/body_updates/tutorial001.py!}
```
* Save the data to your DB.
* Return the updated model.
-```Python hl_lines="30 31 32 33 34 35 36 37"
+```Python hl_lines="30-37"
{!../../../docs_src/body_updates/tutorial002.py!}
```
Use standard Python types for all the attributes:
-```Python hl_lines="7 8 9 10 11"
+```Python hl_lines="7-11"
{!../../../docs_src/body/tutorial001.py!}
```
**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 hl_lines="17 18"
+```Python hl_lines="17-18"
{!../../../docs_src/body/tutorial003.py!}
```
* 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 7 8 9 10 11 13 14 15 16 17 18 19"
+```Python hl_lines="2 6-11 13-19"
{!../../../docs_src/cors/tutorial001.py!}
```
In your FastAPI application, import and run `uvicorn` directly:
-```Python hl_lines="1 15"
+```Python hl_lines="1 15"
{!../../../docs_src/debugging/tutorial001.py!}
```
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParams`:
-```Python hl_lines="11 12 13 14 15"
+```Python hl_lines="11-15"
{!../../../docs_src/dependencies/tutorial002.py!}
```
They can declare request requirements (like headers) or other sub-dependencies:
-```Python hl_lines="6 11"
+```Python hl_lines="6 11"
{!../../../docs_src/dependencies/tutorial006.py!}
```
These dependencies can `raise` exceptions, the same as normal dependencies:
-```Python hl_lines="8 13"
+```Python hl_lines="8 13"
{!../../../docs_src/dependencies/tutorial006.py!}
```
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 hl_lines="9 14"
+```Python hl_lines="9 14"
{!../../../docs_src/dependencies/tutorial006.py!}
```
Only the code prior to and including the `yield` statement is executed before sending a response:
-```Python hl_lines="2 3 4"
+```Python hl_lines="2-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"
+```Python hl_lines="5-6"
{!../../../docs_src/dependencies/tutorial007.py!}
```
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"
+```Python hl_lines="3 5"
{!../../../docs_src/dependencies/tutorial007.py!}
```
For example, `dependency_c` can have a dependency on `dependency_b`, and `dependency_b` on `dependency_a`:
-```Python hl_lines="4 12 20"
+```Python hl_lines="4 12 20"
{!../../../docs_src/dependencies/tutorial008.py!}
```
And, in turn, `dependency_b` needs the value from `dependency_a` (here named `dep_a`) to be available for its exit code.
-```Python hl_lines="16 17 24 25"
+```Python hl_lines="16-17 24-25"
{!../../../docs_src/dependencies/tutorial008.py!}
```
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 2 3 4 5 6 7 8 9 13"
+```Python hl_lines="1-9 13"
{!../../../docs_src/dependencies/tutorial010.py!}
```
It is just a function that can take all the same parameters that a *path operation function* can take:
-```Python hl_lines="8 9"
+```Python hl_lines="8-9"
{!../../../docs_src/dependencies/tutorial001.py!}
```
You could create a first dependency ("dependable") like:
-```Python hl_lines="8 9"
+```Python hl_lines="8-9"
{!../../../docs_src/dependencies/tutorial005.py!}
```
It receives an object, like a Pydantic model, and returns a JSON compatible version:
-```Python hl_lines="5 22"
+```Python hl_lines="5 22"
{!../../../docs_src/encoder/tutorial001.py!}
```
Here's an example *path operation* with parameters using some of the above types.
-```Python hl_lines="1 3 12 13 14 15 16"
+```Python hl_lines="1 3 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 hl_lines="18 19"
+```Python hl_lines="18-19"
{!../../../docs_src/extra_data_types/tutorial001.py!}
```
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 34 35 40 41"
+```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
{!../../../docs_src/extra_models/tutorial001.py!}
```
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"
+```Python hl_lines="9 15-16 19-20 23-24"
{!../../../docs_src/extra_models/tutorial002.py!}
```
!!! note
When defining a <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a>, 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 19 20 33"
+```Python hl_lines="1 14-15 18-20 33"
{!../../../docs_src/extra_models/tutorial003.py!}
```
For that, use the standard Python `typing.List`:
-```Python hl_lines="1 20"
+```Python hl_lines="1 20"
{!../../../docs_src/extra_models/tutorial004.py!}
```
In this case, you can use `typing.Dict`:
-```Python hl_lines="1 8"
+```Python hl_lines="1 8"
{!../../../docs_src/extra_models/tutorial005.py!}
```
You could add a custom exception handler with `@app.exception_handler()`:
-```Python hl_lines="5 6 7 13 14 15 16 17 18 24"
+```Python hl_lines="5-7 13-18 24"
{!../../../docs_src/handling_errors/tutorial003.py!}
```
The exception handler will receive a `Request` and the exception.
-```Python hl_lines="2 14 15 16"
+```Python hl_lines="2 14-16"
{!../../../docs_src/handling_errors/tutorial004.py!}
```
For example, you could want to return a plain text response instead of JSON for these errors:
-```Python hl_lines="3 4 9 10 11 22"
+```Python hl_lines="3-4 9-11 22"
{!../../../docs_src/handling_errors/tutorial004.py!}
```
You will receive a response telling you that the data is invalid containing the received body:
-```JSON hl_lines="12 13 14 15"
+```JSON hl_lines="12-15"
{
"detail": [
{
You can import and re-use the default exception handlers from `fastapi.exception_handlers`:
-```Python hl_lines="2 3 4 5 15 21"
+```Python hl_lines="2-5 15 21"
{!../../../docs_src/handling_errors/tutorial006.py!}
```
To set them, use the parameters `title`, `description`, and `version`:
-```Python hl_lines="4 5 6"
+```Python hl_lines="4-6"
{!../../../docs_src/metadata/tutorial001.py!}
```
Create metadata for your tags and pass it to the `openapi_tags` parameter:
-```Python hl_lines="3 4 5 6 7 8 9 10 11 12 13 14 15 16 18"
+```Python hl_lines="3-16 18"
{!../../../docs_src/metadata/tutorial004.py!}
```
* 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"
+```Python hl_lines="8-9 11 14"
{!../../../docs_src/middleware/tutorial001.py!}
```
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"
+```Python hl_lines="10 12-13"
{!../../../docs_src/middleware/tutorial001.py!}
```
You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
-```Python hl_lines="17 22 27"
+```Python hl_lines="17 22 27"
{!../../../docs_src/path_operation_configuration/tutorial002.py!}
```
You can add a `summary` and `description`:
-```Python hl_lines="20 21"
+```Python hl_lines="20-21"
{!../../../docs_src/path_operation_configuration/tutorial003.py!}
```
You can write <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
-```Python hl_lines="19 20 21 22 23 24 25 26 27"
+```Python hl_lines="19-27"
{!../../../docs_src/path_operation_configuration/tutorial004.py!}
```
You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
-```Python hl_lines="6 7"
+```Python hl_lines="6-7"
{!../../../docs_src/path_params/tutorial001.py!}
```
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}`:
-```Python hl_lines="6 11"
+```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
Then create class attributes with fixed values, which will be the available valid values:
-```Python hl_lines="1 6 7 8 9"
+```Python hl_lines="1 6-9"
{!../../../docs_src/path_params/tutorial005.py!}
```
They will be detected by name:
-```Python hl_lines="8 10"
+```Python hl_lines="8 10"
{!../../../docs_src/query_params/tutorial004.py!}
```
But when you want to make a query parameter required, you can just not declare any default value:
-```Python hl_lines="6 7"
+```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
To use that, declare a `List` of `bytes` or `UploadFile`:
-```Python hl_lines="10 15"
+```Python hl_lines="10 15"
{!../../../docs_src/request_files/tutorial002.py!}
```
Here we are declaring a `UserIn` model, it will contain a plaintext password:
-```Python hl_lines="9 11"
+```Python hl_lines="9 11"
{!../../../docs_src/response_model/tutorial002.py!}
```
And we are using this model to declare our input and the same model to declare our output:
-```Python hl_lines="17 18"
+```Python hl_lines="17-18"
{!../../../docs_src/response_model/tutorial002.py!}
```
We can instead create an input model with the plaintext password and an output model without it:
-```Python hl_lines="9 11 16"
+```Python hl_lines="9 11 16"
{!../../../docs_src/response_model/tutorial003.py!}
```
Your response model could have default values, like:
-```Python hl_lines="11 13 14"
+```Python hl_lines="11 13-14"
{!../../../docs_src/response_model/tutorial004.py!}
```
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"
+```Python hl_lines="3 5"
{
"name": "Bar",
"description": "The bartenders",
If the data has the same values as the default ones, like the item with ID `baz`:
-```Python hl_lines="3 5 6"
+```Python hl_lines="3 5-6"
{
"name": "Baz",
"description": None,
This also applies to `response_model_by_alias` that works similarly.
-```Python hl_lines="31 37"
+```Python hl_lines="31 37"
{!../../../docs_src/response_model/tutorial005.py!}
```
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"
+```Python hl_lines="31 37"
{!../../../docs_src/response_model/tutorial006.py!}
```
You can use the convenience variables from `fastapi.status`.
-```Python hl_lines="1 6"
+```Python hl_lines="1 6"
{!../../../docs_src/response_status_code/tutorial002.py!}
```
You can declare an example for a Pydantic model using `Config` and `schema_extra`, as described in <a href="https://pydantic-docs.helpmanual.io/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic's docs: Schema customization</a>:
-```Python hl_lines="15 16 17 18 19 20 21 22 23"
+```Python hl_lines="15-23"
{!../../../docs_src/schema_extra_example/tutorial001.py!}
```
In `Field`, `Path`, `Query`, `Body` and others you'll see later, you can also declare extra info for the JSON Schema by passing any other arbitrary arguments to the function, for example, to add an `example`:
-```Python hl_lines="4 10 11 12 13"
+```Python hl_lines="4 10-13"
{!../../../docs_src/schema_extra_example/tutorial002.py!}
```
For example, you can pass an `example` for a body request to `Body`:
-```Python hl_lines="21 22 23 24 25 26"
+```Python hl_lines="21-26"
{!../../../docs_src/schema_extra_example/tutorial003.py!}
```
The same way we use Pydantic to declare bodies, we can use it anywhere else:
-```Python hl_lines="5 12 13 14 15 16"
+```Python hl_lines="5 12-16"
{!../../../docs_src/security/tutorial002.py!}
```
`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 hl_lines="19 20 21 22 26 27"
+```Python hl_lines="19-22 26-27"
{!../../../docs_src/security/tutorial002.py!}
```
And all these thousands of *path operations* can be as small as 3 lines:
-```Python hl_lines="30 31 32"
+```Python hl_lines="30-32"
{!../../../docs_src/security/tutorial002.py!}
```
And another one to authenticate and return a user.
-```Python hl_lines="7 48 55 56 59 60 69 70 71 72 73 74 75"
+```Python hl_lines="7 48 55-56 59-60 69-75"
{!../../../docs_src/security/tutorial004.py!}
```
Create a utility function to generate a new access token.
-```Python hl_lines="6 12 13 14 28 29 30 78 79 80 81 82 83 84 85 86"
+```Python hl_lines="6 12-14 28-30 78-86"
{!../../../docs_src/security/tutorial004.py!}
```
If the token is invalid, return an HTTP error right away.
-```Python hl_lines="89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106"
+```Python hl_lines="89-106"
{!../../../docs_src/security/tutorial004.py!}
```
Create a real JWT access token and return it.
-```Python hl_lines="115 116 117 118 119 120 121 122 123 124 125 126 127 128"
+```Python hl_lines="115-128"
{!../../../docs_src/security/tutorial004.py!}
```
For the error, we use the exception `HTTPException`:
-```Python hl_lines="3 77 78 79"
+```Python hl_lines="3 77-79"
{!../../../docs_src/security/tutorial003.py!}
```
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 hl_lines="80 81 82 83"
+```Python hl_lines="80-83"
{!../../../docs_src/security/tutorial003.py!}
```
So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
-```Python hl_lines="58 59 60 61 62 63 64 65 66 67 69 70 71 72 90"
+```Python hl_lines="58-67 69-72 90"
{!../../../docs_src/security/tutorial003.py!}
```
### Import the SQLAlchemy parts
-```Python hl_lines="1 2 3"
+```Python hl_lines="1-3"
{!../../../docs_src/sql_databases/sql_app/database.py!}
```
### Create a database URL for SQLAlchemy
-```Python hl_lines="5 6"
+```Python hl_lines="5-6"
{!../../../docs_src/sql_databases/sql_app/database.py!}
```
We will later use this `engine` in other places.
-```Python hl_lines="8 9 10"
+```Python hl_lines="8-10"
{!../../../docs_src/sql_databases/sql_app/database.py!}
```
These classes are the SQLAlchemy models.
-```Python hl_lines="4 7 8 18 19"
+```Python hl_lines="4 7-8 18-19"
{!../../../docs_src/sql_databases/sql_app/models.py!}
```
And we pass a SQLAlchemy class "type", as `Integer`, `String`, and `Boolean`, that defines the type in the database, as an argument.
-```Python hl_lines="1 10 11 12 13 21 22 23 24"
+```Python hl_lines="1 10-13 21-24"
{!../../../docs_src/sql_databases/sql_app/models.py!}
```
This will become, more or less, a "magic" attribute that will contain the values from other tables related to this one.
-```Python hl_lines="2 15 26"
+```Python hl_lines="2 15 26"
{!../../../docs_src/sql_databases/sql_app/models.py!}
```
But for security, the `password` won't be in other Pydantic *models*, for example, it won't be sent from the API when reading a user.
-```Python hl_lines="3 6 7 8 11 12 23 24 27 28"
+```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!../../../docs_src/sql_databases/sql_app/schemas.py!}
```
Not only the IDs of those items, but all the data that we defined in the Pydantic *model* for reading items: `Item`.
-```Python hl_lines="15 16 17 31 32 33 34"
+```Python hl_lines="15-17 31-34"
{!../../../docs_src/sql_databases/sql_app/schemas.py!}
```
In the `Config` class, set the attribute `orm_mode = True`.
-```Python hl_lines="15 19 20 31 36 37"
+```Python hl_lines="15 19-20 31 36-37"
{!../../../docs_src/sql_databases/sql_app/schemas.py!}
```
* Read multiple users.
* Read a single item.
-```Python hl_lines="1 3 6 7 10 11 14 15 27 28"
+```Python hl_lines="1 3 6-7 10-11 14-15 27-28"
{!../../../docs_src/sql_databases/sql_app/crud.py!}
```
* `commit` the changes to the database (so that they are saved).
* `refresh` your instance (so that it contains any new data from the database, like the generated ID).
-```Python hl_lines="18 19 20 21 22 23 24 31 32 33 34 35 36"
+```Python hl_lines="18-24 31-36"
{!../../../docs_src/sql_databases/sql_app/crud.py!}
```
Our dependency will create a new SQLAlchemy `SessionLocal` that will be used in a single request, and then close it once the request is finished.
-```Python hl_lines="15 16 17 18 19 20"
+```Python hl_lines="15-20"
{!../../../docs_src/sql_databases/sql_app/main.py!}
```
Now, finally, here's the standard **FastAPI** *path operations* code.
-```Python hl_lines="23 24 25 26 27 28 31 32 33 34 37 38 39 40 41 42 45 46 47 48 49 52 53 54 55"
+```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
{!../../../docs_src/sql_databases/sql_app/main.py!}
```
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 hl_lines="14 15 16 17 18 19 20 21 22"
+```Python hl_lines="14-22"
{!../../../docs_src/sql_databases/sql_app/alt_main.py!}
```
* Import `StaticFiles`.
* "Mount" a `StaticFiles()` instance in a specific path.
-```Python hl_lines="2 6"
+```Python hl_lines="2 6"
{!../../../docs_src/static_files/tutorial001.py!}
```
Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
-```Python hl_lines="2 12 15 16 17 18"
+```Python hl_lines="2 12 15-18"
{!../../../docs_src/app_testing/tutorial001.py!}
```
Por lo tanto, si estás utilizando una library que te dice que puedes llamarla con `await`, debes crear las *path operation functions* que la usan con `async def`, como en:
-```Python hl_lines="2 3"
+```Python hl_lines="2-3"
@app.get('/burgers')
async def read_burgers():
burgers = await get_burgers(2)
Si tu código usa `async` / `await`, usa `async def`:
-```Python hl_lines="7 12"
+```Python hl_lines="7 12"
from fastapi import FastAPI
from typing import Optional
Declara el body usando las declaraciones de tipo estándares de Python gracias a Pydantic.
-```Python hl_lines="2 7 8 9 10 23 24 25"
+```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
Harías lo mismo para declarar `tuple`s y `set`s:
-```Python hl_lines="1 4"
+```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial007.py!}
```
El segundo sub-tipo es para los valores del `dict`:
-```Python hl_lines="1 4"
+```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
```
Digamos que tienes una clase `Person`con un nombre:
-```Python hl_lines="1 2 3"
+```Python hl_lines="1-3"
{!../../../docs_src/python_types/tutorial009.py!}
```
If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="7 12"
+```Python hl_lines="7 12"
from fastapi import FastAPI
from typing import Optional
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="2 7 8 9 10 23 24 25"
+```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
Se seu código utiliza `async` / `await`, use `async def`:
-```Python hl_lines="9 14"
+```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
Declare o corpo utilizando tipos padrão Python, graças ao Pydantic.
-```Python hl_lines="4 9 10 11 12 25 26 27"
+```Python hl_lines="4 9-12 25-27"
from fastapi import FastAPI
from pydantic import BaseModel
If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="9 14"
+```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="4 9 10 11 12 25 26 27"
+```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="9 14"
+```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="4 9 10 11 12 25 26 27"
+```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
如果你的代码里会出现 `async` / `await`,请使用 `async def`:
-```Python hl_lines="9 14"
+```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
我们借助 Pydantic 来使用标准的 Python 类型声明请求体。
-```Python hl_lines="4 9 10 11 12 25 26 27"
+```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
声明 `tuple` 和 `set` 的方法也是一样的:
-```Python hl_lines="1 4"
+```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial007.py!}
```
第二个子类型声明 `dict` 的所有值:
-```Python hl_lines="1 4"
+```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
```
假设你有一个名为 `Person` 的类,拥有 name 属性:
-```Python hl_lines="1 2 3"
+```Python hl_lines="1-3"
{!../../../docs_src/python_types/tutorial009.py!}
```
然后,你可以对模型属性使用 `Field`:
-```Python hl_lines="9 10"
+```Python hl_lines="9-10"
{!../../../docs_src/body_fields/tutorial001.py!}
```
你还可以通过将默认值设置为 `None` 来将请求体参数声明为可选参数:
-```Python hl_lines="17 18 19"
+```Python hl_lines="17-19"
{!../../../docs_src/body_multiple_params/tutorial001.py!}
```
使用标准的 Python 类型来声明所有属性:
-```Python hl_lines="5 6 7 8 9"
+```Python hl_lines="5-9"
{!../../../docs_src/body/tutorial001.py!}
```
**FastAPI** 将识别出与路径参数匹配的函数参数应**从路径中获取**,而声明为 Pydantic 模型的函数参数应**从请求体中获取**。
-```Python hl_lines="15 16"
+```Python hl_lines="15-16"
{!../../../docs_src/body/tutorial003.py!}
```
你可以使用与 Python 格式化字符串相同的语法来声明路径"参数"或"变量":
-```Python hl_lines="6 7"
+```Python hl_lines="6-7"
{!../../../docs_src/path_params/tutorial001.py!}
```
然后,你还可以使用路径 `/users/{user_id}` 来通过用户 ID 获取关于特定用户的数据。
由于*路径操作*是按顺序依次运行的,你需要确保路径 `/users/me` 声明在路径 `/users/{user_id}`之前:
-```Python hl_lines="6 11"
+```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
然后创建具有固定值的类属性,这些固定值将是可用的有效值:
-```Python hl_lines="1 6 7 8 9"
+```Python hl_lines="1 6-9"
{!../../../docs_src/path_params/tutorial005.py!}
```
在返回给客户端之前,它们将被转换为对应的值:
-```Python hl_lines="18 20 21"
+```Python hl_lines="18-21"
{!../../../docs_src/path_params/tutorial005.py!}
```
它们将通过名称被检测到:
-```Python hl_lines="6 8"
+```Python hl_lines="6 8"
{!../../../docs_src/query_params/tutorial004.py!}
```
但当你想让一个查询参数成为必需的,不声明任何默认值就可以:
-```Python hl_lines="6 7"
+```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```