mirror of https://github.com/tiangolo/fastapi.git
🎨 Simplify docs hl_lines ranges and standardize 2 spaces between each range (#1863)
This commit is contained in:
parent
dfdd371c52
commit
be669059fb
|
|
@ -153,7 +153,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
|||
|
||||
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
|
||||
|
|
@ -245,7 +245,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -23,7 +23,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 23"
|
||||
```Python hl_lines="18 23"
|
||||
{!../../../docs_src/additional_responses/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ For example, to declare another response with a status code `404` and a Pydantic
|
|||
|
||||
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": {
|
||||
|
|
@ -83,7 +83,7 @@ The generated responses in the OpenAPI for this *path operation* will be:
|
|||
|
||||
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": {
|
||||
|
|
@ -168,7 +168,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 20 21 22 23 24 28"
|
||||
```Python hl_lines="19-24 28"
|
||||
{!../../../docs_src/additional_responses/tutorial002.py!}
|
||||
```
|
||||
|
||||
|
|
@ -192,7 +192,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 21 22 23 24 25 26 27 28 29 30 31"
|
||||
```Python hl_lines="20-31"
|
||||
{!../../../docs_src/additional_responses/tutorial003.py!}
|
||||
```
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ You can use that technique to re-use some predefined responses in your *path ope
|
|||
|
||||
For example:
|
||||
|
||||
```Python hl_lines="13 14 15 16 17 26"
|
||||
```Python hl_lines="13-17 26"
|
||||
{!../../../docs_src/additional_responses/tutorial004.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Later, for your production application, you might want to use a database server
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ Later, for your production application, you might want to use a database server
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ Here, this section would run directly, right before starting your **FastAPI** ap
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ Create Pydantic models for:
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ So, you will be able to see it all in the interactive API docs.
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ So, you will be able to see it all in the interactive API docs.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ That documents (and validates, serializes, filters) the output data, as a `list`
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ The marker `@pytest.mark.asyncio` tells pytest that this test function should be
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ proxy --> server
|
|||
|
||||
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
|
||||
|
|
@ -290,13 +290,13 @@ If you pass a custom list of `servers` and there's a `root_path` (because your A
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ If there's no `gzip` in the header, it will not try to decompress the body.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ This method returns a function. And that function is what will receive a request
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -84,13 +84,13 @@ We can also use this same approach to access the request body in an exception ha
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -104,6 +104,6 @@ You can also set the `route_class` parameter of an `APIRouter`:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ For example, if you are squeezing performance, you can install and use <a href="
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ As seen in [Return a Response directly](response-directly.md){.internal-link tar
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ The `response_class` will then be used only to document the OpenAPI *path operat
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ An alternative JSON response using <a href="https://github.com/ultrajson/ultrajs
|
|||
!!! 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!}
|
||||
```
|
||||
|
||||
|
|
@ -179,7 +179,7 @@ If you have a file-like object (e.g. the object returned by `open()`), you can r
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ The parameter that defines this is `default_response_class`.
|
|||
|
||||
In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
|
||||
|
||||
```Python hl_lines="2 4"
|
||||
```Python hl_lines="2 4"
|
||||
{!../../../docs_src/custom_response/tutorial010.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ 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 8 9"
|
||||
```Python hl_lines="1 4 7-9"
|
||||
{!../../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ First, write all your **FastAPI** application as normally:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ Then, use the same utility function to generate the OpenAPI schema, inside a `cu
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ 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 24 25"
|
||||
```Python hl_lines="13-14 24-25"
|
||||
{!../../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ $ pip install aiofiles
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ You can re-use FastAPI's internal functions to create the HTML pages for the doc
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ And similarly for ReDoc...
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ GraphQL is implemented with Graphene, you can check <a href="https://docs.graphe
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ Import `graphene` and define your GraphQL data:
|
|||
|
||||
Then import and add Starlette's `GraphQLApp`:
|
||||
|
||||
```Python hl_lines="3 14"
|
||||
```Python hl_lines="3 14"
|
||||
{!../../../docs_src/graphql/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Any incoming requests to `http` or `ws` will be redirected to the secure scheme
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ You can adapt it to any other NoSQL database like:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ This utility function will:
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ As **Couchbase** "documents" are actually just "JSON objects", we can model them
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ This will have the data that is actually stored in the database.
|
|||
|
||||
We don't create it as a subclass of Pydantic's `BaseModel` but as a subclass of our own `User`, because it will have all the attributes in `User` plus a couple more:
|
||||
|
||||
```Python hl_lines="31 32 33"
|
||||
```Python hl_lines="31-33"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ Now create a function that will:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ As our code is calling Couchbase and we are not using the <a href="https://docs.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ It will have a *path operation* that will receive an `Invoice` body, and a query
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ Because of that, you need to declare what will be the `default_response_class`,
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ It should look just like a normal FastAPI *path operation*:
|
|||
* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`.
|
||||
* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`.
|
||||
|
||||
```Python hl_lines="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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ If you want to use your APIs' function names as `operationId`s, you can iterate
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -47,6 +47,6 @@ Adding an `\f` (an escaped "form feed" character) causes **FastAPI** to truncate
|
|||
|
||||
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!}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ You can declare a parameter of type `Response` in your *path operation function*
|
|||
|
||||
And then you can set cookies in that *temporal* response object.
|
||||
|
||||
```Python hl_lines="1 8 9"
|
||||
```Python hl_lines="1 8-9"
|
||||
{!../../../docs_src/response_cookies/tutorial002.py!}
|
||||
```
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ To do that, you can create a response as described in [Return a Response Directl
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ For example, you cannot put a Pydantic model in a `JSONResponse` without first c
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ You can declare a parameter of type `Response` in your *path operation function*
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ You can also add headers when you return a `Response` directly.
|
|||
|
||||
Create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank} and pass the headers as an additional parameter:
|
||||
|
||||
```Python hl_lines="10 11 12"
|
||||
```Python hl_lines="10-12"
|
||||
{!../../../docs_src/response_headers/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Then, when you type that username and password, the browser sends them in the he
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ Use a dependency to check if the username and password are correct.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -102,6 +102,6 @@ That way, using `secrets.compare_digest()` in your application code, it will be
|
|||
|
||||
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!}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ They are normally used to declare specific security permissions, for example:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ The first change is that now we are declaring the OAuth2 security scheme with tw
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ We create an `HTTPException` that we can re-use (`raise`) later at several point
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ Instead of, for example, a `dict`, or something else, as it could break the appl
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ We now verify that all the scopes required, by this dependency and all the depen
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ The same way as with Pydantic models, you declare class attributes with type ann
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ Next it will convert and validate the data. So, when you use that `settings` obj
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ For example, you could have a file `config.py` with:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ Notice that now we don't create a default instance `settings = Settings()`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ Now we create a dependency that returns a new `config.Settings()`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -235,7 +235,7 @@ And then we can require it from the *path operation function* as a dependency an
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -272,7 +272,7 @@ APP_NAME="ChimichangApp"
|
|||
|
||||
And then update your `config.py` with:
|
||||
|
||||
```Python hl_lines="9 10"
|
||||
```Python hl_lines="9-10"
|
||||
{!../../../docs_src/settings/app03/config.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ This might seem a bit complex (and it actually is), you don't really need to com
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ This is the same you would do if you followed the Peewee tutorial and updated th
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ Now let's check the file `sql_app/schemas.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!}
|
||||
```
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ But recent versions of Pydantic allow providing a custom class that inherits fro
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -235,7 +235,7 @@ Now let's see the file `sql_app/crud.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!}
|
||||
```
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ And now in the file `sql_app/main.py` let's integrate and use all the other part
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ In a very simplistic way create the database tables:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ For all the `contextvars` parts to work, we need to make sure we have an indepen
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -310,7 +310,7 @@ If you are using a <a href="http://docs.peewee-orm.com/en/latest/peewee/database
|
|||
|
||||
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()
|
||||
|
|
@ -320,7 +320,7 @@ async def reset_db_state():
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ If you need to have two independent FastAPI applications, with their own indepen
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ Then, create your sub-application, and its *path operations*.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ In your top-level application, `app`, mount the sub-application, `subapi`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ $ pip install aiofiles
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ We create a new file at `sql_app/tests/test_sql_app.py`.
|
|||
|
||||
So the new file structure looks like:
|
||||
|
||||
``` hl_lines="9 10 11"
|
||||
``` hl_lines="9-11"
|
||||
.
|
||||
└── sql_app
|
||||
├── __init__.py
|
||||
|
|
@ -48,7 +48,7 @@ For the tests we'll use a file `test.db` instead of `sql_app.db`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ So we add that line here, with the new file.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ Now we create the dependency override and add it to the overrides for our app.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ To override a dependency for testing, you put as a key the original dependency (
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
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!}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ You can use the same `TestClient` to test WebSockets.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Let's imagine you want to get the client's IP address/host inside of your *path
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ In production you would have one of the options above.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ But it's the simplest way to focus on the server-side of WebSockets and have a w
|
|||
|
||||
In your **FastAPI** application, create a `websocket`:
|
||||
|
||||
```Python hl_lines="1 46 47"
|
||||
```Python hl_lines="1 46-47"
|
||||
{!../../../docs_src/websockets/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ In your **FastAPI** application, create a `websocket`:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ In WebSocket endpoints you can import from `fastapi` and use:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Then wrap the WSGI (e.g. Flask) app with the middleware.
|
|||
|
||||
And then mount that under a path.
|
||||
|
||||
```Python hl_lines="2 3 22"
|
||||
```Python hl_lines="2-3 22"
|
||||
{!../../../docs_src/wsgi/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ burgers = get_burgers(2)
|
|||
|
||||
So, if you are using a library that tells you that you can call it with `await`, you need to create the *path operation functions* that uses it with `async def`, like in:
|
||||
|
||||
```Python hl_lines="2 3"
|
||||
```Python hl_lines="2-3"
|
||||
@app.get('/burgers')
|
||||
async def read_burgers():
|
||||
burgers = await get_burgers(2)
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
|||
|
||||
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
|
||||
|
|
@ -245,7 +245,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ And still, the editor knows it is a `str`, and provides support for that.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ The first type parameter is for the keys of the `dict`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ This means:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -249,7 +249,7 @@ You can also declare a class as the type of a variable.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +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"
|
||||
```Python hl_lines="1 13"
|
||||
{!../../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ 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 7 8 9"
|
||||
```Python hl_lines="6-9"
|
||||
{!../../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ Using `BackgroundTasks` also works with the dependency injection system, you can
|
|||
|
||||
**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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ You can create the *path operations* for that module using `APIRouter`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ And then you use it to declare your *path operations*.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ But let's say that this time we are more lazy.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ We are not adding the prefix `/items/` nor the `tags=["items"]` to add them late
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ This will be the main file in your application that ties everything together.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ And we can add predefined `responses` that will be included in all the *path ope
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ First, you have to import it:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ First, of course, you can mix `Path`, `Query` and request body parameter declara
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ And Python has a special data type for sets of unique items, the `set`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ All that, arbitrarily nested.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ To see all the options you have, checkout the docs for <a href="https://pydantic
|
|||
|
||||
For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `HttpUrl`:
|
||||
|
||||
```Python hl_lines="4 10"
|
||||
```Python hl_lines="4 10"
|
||||
{!../../../docs_src/body_nested_models/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ This will expect (convert, validate, document, etc) a JSON body like:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ To update an item you can use the <a href="https://developer.mozilla.org/en-US/d
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ In summary, to apply partial updates you would:
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ Then you declare your data model as a class that inherits from `BaseModel`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ You can declare path parameters and body requests at the same time.
|
|||
|
||||
**FastAPI** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared to be Pydantic models should be **taken from the request body**.
|
||||
|
||||
```Python hl_lines="17 18"
|
||||
```Python hl_lines="17-18"
|
||||
{!../../../docs_src/body/tutorial003.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ You can also specify if your backend allows:
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ You can connect the debugger in your editor, for example with Visual Studio Code
|
|||
|
||||
In your FastAPI application, import and run `uvicorn` directly:
|
||||
|
||||
```Python hl_lines="1 15"
|
||||
```Python hl_lines="1 15"
|
||||
{!../../../docs_src/debugging/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ That also applies to callables with no parameters at all. The same as it would b
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ You can use the same dependency *functions* you use normally.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ They can declare request requirements (like headers) or other sub-dependencies:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ And they can return values or not, the values won't be used.
|
|||
|
||||
So, you can re-use a normal dependency (that returns a value) you already use somewhere else, and even though the value won't be used, the dependency will be executed:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
```Python hl_lines="9 14"
|
||||
{!../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ For example, you could use this to create a database session and close it after
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ The yielded value is what is injected into *path operations* and other dependenc
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ So, you can look for that specific exception inside the dependency with `except
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ You can have sub-dependencies and "trees" of sub-dependencies of any size and sh
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ In this case `dependency_c`, to execute its exit code, needs the value from `dep
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -207,7 +207,7 @@ In Python, you can create Context Managers by <a href="https://docs.python.org/3
|
|||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Let's first focus on the dependency.
|
|||
|
||||
It is just a function that can take all the same parameters that a *path operation function* can take:
|
||||
|
||||
```Python hl_lines="8 9"
|
||||
```Python hl_lines="8-9"
|
||||
{!../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ They can be as **deep** as you need them to be.
|
|||
|
||||
You could create a first dependency ("dependable") like:
|
||||
|
||||
```Python hl_lines="8 9"
|
||||
```Python hl_lines="8-9"
|
||||
{!../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ You can use `jsonable_encoder` for that.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -55,12 +55,12 @@ Here are some of the additional data types you can use:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ This is especially the case for user models, because:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ All the data conversion, validation, documentation, etc. will still work as norm
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ To do that, use the standard Python type hint <a href="https://docs.python.org/3
|
|||
!!! 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!}
|
||||
```
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ The same way, you can declare responses of lists of objects.
|
|||
|
||||
For that, use the standard Python `typing.List`:
|
||||
|
||||
```Python hl_lines="1 20"
|
||||
```Python hl_lines="1 20"
|
||||
{!../../../docs_src/extra_models/tutorial004.py!}
|
||||
```
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ This is useful if you don't know the valid field/attribute names (that would be
|
|||
|
||||
In this case, you can use `typing.Dict`:
|
||||
|
||||
```Python hl_lines="1 8"
|
||||
```Python hl_lines="1 8"
|
||||
{!../../../docs_src/extra_models/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ And you want to handle this exception globally with FastAPI.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ To override it, import the `RequestValidationError` and use it with `@app.except
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -179,7 +179,7 @@ The same way, you can override the `HTTPException` handler.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ Now try sending an invalid item like:
|
|||
|
||||
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": [
|
||||
{
|
||||
|
|
@ -256,7 +256,7 @@ You could also just want to use the exception somehow, but then use the same def
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ You can set the:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ Let's try that in an example with tags for `users` and `items`.
|
|||
|
||||
Create metadata for your tags and pass it to the `openapi_tags` parameter:
|
||||
|
||||
```Python hl_lines="3 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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ The middleware function receives:
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ And also after the `response` is generated, before returning it.
|
|||
|
||||
For example, you could add a custom header `X-Process-Time` containing the time in seconds that it took to process the request and generate a response:
|
||||
|
||||
```Python hl_lines="10 12 13"
|
||||
```Python hl_lines="10 12-13"
|
||||
{!../../../docs_src/middleware/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ That status code will be used in the response and will be added to the OpenAPI s
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ They will be added to the OpenAPI schema and used by the automatic documentation
|
|||
|
||||
You can add a `summary` and `description`:
|
||||
|
||||
```Python hl_lines="20 21"
|
||||
```Python hl_lines="20-21"
|
||||
{!../../../docs_src/path_operation_configuration/tutorial003.py!}
|
||||
```
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ As descriptions tend to be long and cover multiple lines, you can declare the *p
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ And then you can also have a path `/users/{user_id}` to get data about a specifi
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ By inheriting from `str` the API docs will be able to know that the values must
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ And you don't have to declare them in any specific order.
|
|||
|
||||
They will be detected by name:
|
||||
|
||||
```Python hl_lines="8 10"
|
||||
```Python hl_lines="8 10"
|
||||
{!../../../docs_src/query_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ If you don't want to add a specific value but just make it optional, set the def
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ They would be associated to the same "form field" sent using "form data".
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ But most importantly:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ But if we use the same model for another *path operation*, we could be sending o
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ And both models will be used for the interactive API documentation:
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ So, if you send a request to that *path operation* for the item with ID `foo`, t
|
|||
|
||||
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",
|
||||
|
|
@ -151,7 +151,7 @@ they will be included in the response.
|
|||
|
||||
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,
|
||||
|
|
@ -185,7 +185,7 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ But you don't have to memorize what each of these codes mean.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ There are several ways you can declare extra JSON Schema information.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ That extra info will be added as-is to the output JSON Schema.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ The same way you can pass extra info to `Field`, you can do the same with `Path`
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ First, let's create a Pydantic user model.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ The same as we were doing before in the *path operation* directly, our new depen
|
|||
|
||||
`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!}
|
||||
```
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ And all of them (or any portion of them that you want) can take the advantage of
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ And another utility to verify if a received password matches the hash stored.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ Define a Pydantic Model that will be used in the token endpoint for the response
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ Decode the received token, verify it, and return the current user.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ Create a `timedelta` with the expiration time of the token.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ If there is no such user, we return an error saying "incorrect username or passw
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ If your database is stolen, the thief won't have your users' plaintext passwords
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ Both of these dependencies will just return an HTTP error if the user doesn't ex
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -86,13 +86,13 @@ Let's refer to the file `sql_app/database.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!}
|
||||
```
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ The first step is to create a SQLAlchemy "engine".
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ Create classes that inherit from it.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ We use `Column` from SQLAlchemy as the default value.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ For this, we use `relationship` provided by SQLAlchemy ORM.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -248,7 +248,7 @@ So, the user will also have a `password` when creating it.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -278,7 +278,7 @@ The same way, when reading a user, we can now declare that `items` will contain
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ This <a href="https://pydantic-docs.helpmanual.io/#config" class="external-link"
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -366,7 +366,7 @@ Create utility functions to:
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ The steps are:
|
|||
* `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!}
|
||||
```
|
||||
|
||||
|
|
@ -462,7 +462,7 @@ For that, we will create a new dependency with `yield`, as explained before in t
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -492,7 +492,7 @@ This will then give us better editor support inside the *path operation function
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -640,7 +640,7 @@ A "middleware" is basically a function that is always executed for each request,
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ $ pip install aiofiles
|
|||
* 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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Use the `TestClient` object the same way as you do with `requests`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ hamburguesas = get_burgers (2)
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
|||
|
||||
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
|
||||
|
||||
|
|
@ -242,7 +242,7 @@ Ahora modifica el archivo `main.py` para recibir un <abbr title="cuerpo del mens
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ El editor aún sabe que es un `str` y provee soporte para ello.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ El primer sub-tipo es para los keys del `dict`.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ También puedes declarar una clase como el tipo de una variable.
|
|||
|
||||
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!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ def read_item(item_id: int, q: str = Optional[None]):
|
|||
|
||||
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
|
||||
|
||||
|
|
@ -247,7 +247,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
|||
|
||||
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
|
||||
|
|
@ -238,7 +238,7 @@ Agora modifique o arquivo `main.py` para receber um corpo para uma requisição
|
|||
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
|||
|
||||
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
|
||||
|
|
@ -249,7 +249,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
|||
|
||||
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
|
||||
|
|
@ -249,7 +249,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ def read_item(item_id: int, q: Optional[str] = None):
|
|||
|
||||
如果你的代码里会出现 `async` / `await`,请使用 `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
|
@ -245,7 +245,7 @@ INFO: Application startup complete.
|
|||
|
||||
我们借助 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
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ John Doe
|
|||
|
||||
声明 `tuple` 和 `set` 的方法也是一样的:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ John Doe
|
|||
|
||||
第二个子类型声明 `dict` 的所有值:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ John Doe
|
|||
|
||||
假设你有一个名为 `Person` 的类,拥有 name 属性:
|
||||
|
||||
```Python hl_lines="1 2 3"
|
||||
```Python hl_lines="1-3"
|
||||
{!../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
然后,你可以对模型属性使用 `Field`:
|
||||
|
||||
```Python hl_lines="9 10"
|
||||
```Python hl_lines="9-10"
|
||||
{!../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
你还可以通过将默认值设置为 `None` 来将请求体参数声明为可选参数:
|
||||
|
||||
```Python hl_lines="17 18 19"
|
||||
```Python hl_lines="17-19"
|
||||
{!../../../docs_src/body_multiple_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
使用标准的 Python 类型来声明所有属性:
|
||||
|
||||
```Python hl_lines="5 6 7 8 9"
|
||||
```Python hl_lines="5-9"
|
||||
{!../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ Pydantic 本身甚至也进行了一些更改以支持此功能。
|
|||
|
||||
**FastAPI** 将识别出与路径参数匹配的函数参数应**从路径中获取**,而声明为 Pydantic 模型的函数参数应**从请求体中获取**。
|
||||
|
||||
```Python hl_lines="15 16"
|
||||
```Python hl_lines="15-16"
|
||||
{!../../../docs_src/body/tutorial003.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
你可以使用与 Python 格式化字符串相同的语法来声明路径"参数"或"变量":
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
```Python hl_lines="6-7"
|
||||
{!../../../docs_src/path_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
然后,你还可以使用路径 `/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!}
|
||||
```
|
||||
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
|
||||
然后创建具有固定值的类属性,这些固定值将是可用的有效值:
|
||||
|
||||
```Python hl_lines="1 6 7 8 9"
|
||||
```Python hl_lines="1 6-9"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
|
@ -179,7 +179,7 @@
|
|||
|
||||
在返回给客户端之前,它们将被转换为对应的值:
|
||||
|
||||
```Python hl_lines="18 20 21"
|
||||
```Python hl_lines="18-21"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ http://127.0.0.1:8000/items/foo?short=yes
|
|||
|
||||
它们将通过名称被检测到:
|
||||
|
||||
```Python hl_lines="6 8"
|
||||
```Python hl_lines="6 8"
|
||||
{!../../../docs_src/query_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ http://127.0.0.1:8000/items/foo?short=yes
|
|||
|
||||
但当你想让一个查询参数成为必需的,不声明任何默认值就可以:
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
```Python hl_lines="6-7"
|
||||
{!../../../docs_src/query_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue