mirror of
https://github.com/fastapi/fastapi.git
synced 2026-07-18 19:03:14 -04:00
🎨 Simplify docs hl_lines ranges and standardize 2 spaces between each range (#1863)
This commit is contained in:
@@ -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!}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user