* <ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a> für die Erstellung von APIs, inklusive Deklarationen von <abbrtitle="auch genannt Endpunkte, Routen">Pfad</abbr>-<abbrtitle="gemeint sind HTTP-Methoden wie POST, GET, PUT, DELETE">Operationen</abbr>, Parametern, Body-Anfragen, Sicherheit, usw.
* <ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a> für die Erstellung von APIs, inklusive Deklarationen von <abbrtitle="auch genannt Endpunkte, Routen">Pfad</abbr>-<abbrtitle="gemeint sind HTTP-Methoden wie POST, GET, PUT, DELETE">Operationen</abbr>, Parametern, Requestbodys, Sicherheit, usw.
* Automatische Dokumentation der Datenmodelle mit <ahref="https://json-schema.org/"class="external-link"target="_blank"><strong>JSON Schema</strong></a> (da OpenAPI selbst auf JSON Schema basiert).
* Um diese Standards herum entworfen, nach sorgfältigem Studium. Statt einer nachträglichen Schicht darüber.
* Dies ermöglicht auch automatische **Client-Code-Generierung** in vielen Sprachen.
@ -255,11 +255,11 @@ This includes many libraries to interact with cloud storage, video processing, a
1. This is the generator function. It's a "generator function" because it contains `yield` statements inside.
2. By using a `with` block, we make sure that the file-like object is closed after the generator function is done. So, after it finishes sending the response.
3. This `yield from` tells the function to iterate over that thing named `file_like`. And then, for each part iterated, yield that part as coming from this generator function.
3. This `yield from` tells the function to iterate over that thing named `file_like`. And then, for each part iterated, yield that part as coming from this generator function (`iterfile`).
So, it is a generator function that transfers the "generating" work to something else internally.
By doing it this way, we can put it in a `with` block, and that way, ensure that it is closed after finishing.
By doing it this way, we can put it in a `with` block, and that way, ensure that the file-like object is closed after finishing.
@ -37,7 +37,7 @@ This part is pretty normal, most of the code is probably already familiar to you
/// tip
The `callback_url` query parameter uses a Pydantic <ahref="https://docs.pydantic.dev/latest/concepts/types/#urls"class="external-link"target="_blank">URL</a> type.
The `callback_url` query parameter uses a Pydantic <ahref="https://docs.pydantic.dev/latest/api/networks/"class="external-link"target="_blank">Url</a> type.
@ -725,7 +725,7 @@ Here's how the hierarchy of dependencies and scopes looks like:
* This `security_scopes` parameter has a property `scopes` with a `list` containing all these scopes declared above, so:
* `security_scopes.scopes` will contain `["me", "items"]` for the *path operation*`read_own_items`.
* `security_scopes.scopes` will contain `["me"]` for the *path operation*`read_users_me`, because it is declared in the dependency `get_current_active_user`.
* `security_scopes.scopes` will contain `[]` (nothing) for the *path operation*`read_system_status`, because it didn't declare any `Security` with `scopes`, and its dependency, `get_current_user`, doesn't declare any `scope` either.
* `security_scopes.scopes` will contain `[]` (nothing) for the *path operation*`read_system_status`, because it didn't declare any `Security` with `scopes`, and its dependency, `get_current_user`, doesn't declare any `scopes` either.
@ -138,7 +138,7 @@ That means that any value read in Python from an environment variable will be a
## Pydantic `Settings`
Fortunately, Pydantic provides a great utility to handle these settings coming from environment variables with <ahref="https://docs.pydantic.dev/latest/usage/pydantic_settings/"class="external-link"target="_blank">Pydantic: Settings management</a>.
Fortunately, Pydantic provides a great utility to handle these settings coming from environment variables with <ahref="https://docs.pydantic.dev/latest/concepts/pydantic_settings/"class="external-link"target="_blank">Pydantic: Settings management</a>.
### Install `pydantic-settings`
@ -411,7 +411,7 @@ And then update your `config.py` with:
/// tip
The `model_config` attribute is used just for Pydantic configuration. You can read more at <ahref="https://docs.pydantic.dev/latest/usage/model_config/"class="external-link"target="_blank">Pydantic Model Config</a>.
The `model_config` attribute is used just for Pydantic configuration. You can read more at <ahref="https://docs.pydantic.dev/latest/concepts/config/"class="external-link"target="_blank">Pydantic: Concepts: Configuration</a>.
* <ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a> for API creation, including declarations of <abbrtitle="also known as: endpoints, routes">path</abbr><abbrtitle="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</abbr>, parameters, body requests, security, etc.
* <ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a> for API creation, including declarations of <abbrtitle="also known as: endpoints, routes">path</abbr><abbrtitle="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</abbr>, parameters, request bodies, security, etc.
* Automatic data model documentation with <ahref="https://json-schema.org/"class="external-link"target="_blank"><strong>JSON Schema</strong></a> (as OpenAPI itself is based on JSON Schema).
* Designed around these standards, after a meticulous study. Instead of an afterthought layer on top.
* This also allows using automatic **client code generation** in many languages.
@ -519,7 +519,7 @@ You will see a lot more of all this in practice in the [Tutorial - User Guide](t
/// tip
Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <ahref="https://docs.pydantic.dev/latest/concepts/models/#required-optional-fields"class="external-link"target="_blank">Required Optional fields</a>.
Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <ahref="https://docs.pydantic.dev/2.3/usage/models/#required-fields"class="external-link"target="_blank">Required Optional fields</a>.
* Email notifications sent after performing an action:
* As connecting to an email server and sending an email tends to be "slow" (several seconds), you can return the response right away and send the email notification in the background.
* Processing data:
* For example, let's say you receive a file that must go through a slow process, you can return a response of "Accepted" (HTTP 202) and process it in the background.
* For example, let's say you receive a file that must go through a slow process, you can return a response of "Accepted" (HTTP 202) and process the file in the background.
@ -220,7 +220,7 @@ Again, doing just that declaration, with **FastAPI** you get:
Apart from normal singular types like `str`, `int`, `float`, etc. you can use more complex singular types that inherit from `str`.
To see all the options you have, checkout the docs for <ahref="https://docs.pydantic.dev/latest/concepts/types/"class="external-link"target="_blank">Pydantic's exotic types</a>. You will see some examples in the next chapter.
To see all the options you have, checkout <ahref="https://docs.pydantic.dev/latest/concepts/types/"class="external-link"target="_blank">Pydantic's Type Overview</a>. You will see some examples in the next chapter.
For example, as in the `Image` model we have a `url` field, we can declare it to be an instance of Pydantic's `HttpUrl` instead of a `str`:
@ -4,7 +4,7 @@ When you need to send data from a client (let's say, a browser) to your API, you
A **request** body is data sent by the client to your API. A **response** body is the data your API sends to the client.
Your API almost always has to send a **response** body. But clients don't necessarily need to send **request** bodies all the time.
Your API almost always has to send a **response** body. But clients don't necessarily need to send **request bodies** all the time, sometimes they only request a path, maybe with some query parameters, but don't send a body.
To declare a **request** body, you use <ahref="https://docs.pydantic.dev/"class="external-link"target="_blank">Pydantic</a> models with all their power and benefits.
@ -18,11 +18,11 @@ Even if they are all in `localhost`, they use different protocols or ports, so,
So, let's say you have a frontend running in your browser at `http://localhost:8080`, and its JavaScript is trying to communicate with a backend running at `http://localhost` (because we don't specify a port, the browser will assume the default port `80`).
Then, the browser will send an HTTP `OPTIONS` request to the backend, and if the backend sends the appropriate headers authorizing the communication from this different origin (`http://localhost:8080`) then the browser will let the JavaScript in the frontend send its request to the backend.
Then, the browser will send an HTTP `OPTIONS` request to the `:80`-backend, and if the backend sends the appropriate headers authorizing the communication from this different origin (`http://localhost:8080`) then the `:8080`-browser will let the JavaScript in the frontend send its request to the `:80`-backend.
To achieve this, the backend must have a list of "allowed origins".
To achieve this, the `:80`-backend must have a list of "allowed origins".
In this case, it would have to include `http://localhost:8080` for the frontend to work correctly.
In this case, the list would have to include `http://localhost:8080` for the `:8080`-frontend to work correctly.
@ -36,7 +36,7 @@ Here are some of the additional data types you can use:
* `datetime.timedelta`:
* A Python `datetime.timedelta`.
* In requests and responses will be represented as a `float` of total seconds.
* Pydantic also allows representing it as a "ISO 8601 time diff encoding", <ahref="https://docs.pydantic.dev/latest/concepts/serialization/#json_encoders"class="external-link"target="_blank">see the docs for more info</a>.
* Pydantic also allows representing it as a "ISO 8601 time diff encoding", <ahref="https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers"class="external-link"target="_blank">see the docs for more info</a>.
* `frozenset`:
* In requests and responses, treated the same as a `set`:
* In requests, a list will be read, eliminating duplicates and converting it to a `set`.
The supporting additional functions are just to demo a possible flow of the data, but they of course are not providing any real security.
The supporting additional functions `fake_password_hasher` and `fake_save_user`are just to demo a possible flow of the data, but they of course are not providing any real security.
///
@ -194,7 +194,7 @@ That way, we can declare just the differences between the models (with plaintext
## `Union` or `anyOf`
You can declare a response to be the `Union` of two types, that means, that the response would be any of the two.
You can declare a response to be the `Union` of two or more types, that means, that the response would be any of them.
It will be defined in OpenAPI with `anyOf`.
@ -234,7 +234,7 @@ If it was in a type annotation we could have used the vertical bar, as:
some_variable: PlaneItem | CarItem
```
But if we put that in `response_model=PlaneItem | CarItem` we would get an error, because Python would try to perform an **invalid operation** between `PlaneItem` and `CarItem` instead of interpreting that as a type annotation.
But if we put that in the assignment `response_model=PlaneItem | CarItem` we would get an error, because Python would try to perform an **invalid operation** between `PlaneItem` and `CarItem` instead of interpreting that as a type annotation.
* Show a **clear error** for the client when the data is not valid
* **Document** the parameter in the OpenAPI schema *path operation* (so it will show up in the **automatic docs UI**)
## Alternative (old) `Query` as the default value
## Alternative (old):`Query` as the default value
Previous versions of FastAPI (before <abbrtitle="before 2023-03">0.95.0</abbr>) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you.
But it declares it explicitly as being a query parameter.
But the `Query` versions declare it explicitly as being a query parameter.
/// info
@ -457,7 +457,7 @@ Having a default value of any type, including `None`, makes the parameter option
///
## Make it required
## Required parameters
When we don't need to declare more validations or metadata, we can make the `q` query parameter required just by not declaring a default value, like:
@ -573,7 +573,7 @@ It is used by Pydantic and FastAPI to explicitly declare that a value is require
This will let **FastAPI** know that this parameter is required.
### Required with`None`
### Required, can be`None`
You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`.
@ -633,7 +633,7 @@ Prefer to use the `Annotated` version if possible.
/// tip
Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <ahref="https://docs.pydantic.dev/latest/concepts/models/#required-optional-fields"class="external-link"target="_blank">Required Optional fields</a>.
Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <ahref="https://docs.pydantic.dev/2.3/usage/models/#required-optional-fields"class="external-link"target="_blank">Required fields</a>.
///
@ -809,7 +809,7 @@ the default of `q` will be: `["foo", "bar"]` and your response will be:
}
```
#### Using `list`
#### Using just `list`
You can also use `list` directly instead of `List[str]` (or `list[str]` in Python 3.9+):
@ -1107,7 +1107,7 @@ The docs will show it like this:
To exclude a query parameter from the generated OpenAPI schema (and thus, from the automatic documentation systems), set the parameter `include_in_schema` of `Query` to `False`:
@ -152,7 +152,7 @@ Using `UploadFile` has several advantages over `bytes`:
* `filename`: A `str` with the original file name that was uploaded (e.g. `myimage.jpg`).
* `content_type`: A `str` with the content type (MIME type / media type) (e.g. `image/jpeg`).
* `file`: A <ahref="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile"class="external-link"target="_blank">`SpooledTemporaryFile`</a> (a <ahref="https://docs.python.org/3/glossary.html#term-file-like-object"class="external-link"target="_blank">file-like</a> object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
* `file`: A <ahref="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile"class="external-link"target="_blank">`SpooledTemporaryFile`</a> (a <ahref="https://docs.python.org/3/glossary.html#term-file-like-object"class="external-link"target="_blank">file-like</a> object). This is the actual Python file object that you can pass directly to other functions or libraries that expect a "file-like" object.
`UploadFile` has the following `async` methods. They all call the corresponding file methods underneath (using the internal `SpooledTemporaryFile`).
@ -236,9 +236,9 @@ That's why in this example we have to declare it in the `response_model` paramet
## Return Type and Data Filtering
Let's continue from the previous example. We wanted to **annotate the function with one type** but return something that includes **more data**.
Let's continue from the previous example. We wanted to **annotate the function with one type**, but we wanted to be able to return from the function something that actually includes **more data**.
We want FastAPI to keep **filtering** the data using the response model.
We want FastAPI to keep **filtering** the data using the response model. So that even though the function returns more data, the response will only include the fields declared in the response model.
In the previous example, because the classes were different, we had to use the `response_model` parameter. But that also means that we don't get the support from the editor and tools checking the function return type.
@ -306,7 +306,7 @@ The most common case would be [returning a Response directly as explained later
This simple case is handled automatically by FastAPI because the return type annotation is the class (or a subclass) of `Response`.
This simple case is handled automatically by FastAPI because the return type annotation is the class (or a subclass of)`Response`.
And tools will also be happy because both `RedirectResponse` and `JSONResponse` are subclasses of `Response`, so the type annotation is correct.
@ -455,7 +455,7 @@ The examples here use `.dict()` for compatibility with Pydantic v1, but you shou
/// info
FastAPI uses Pydantic model's `.dict()` with <ahref="https://docs.pydantic.dev/latest/concepts/serialization/#modeldict"class="external-link"target="_blank">its `exclude_unset` parameter</a> to achieve this.
FastAPI uses Pydantic model's `.dict()` with <ahref="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict"class="external-link"target="_blank">its `exclude_unset` parameter</a> to achieve this.
///
@ -466,7 +466,7 @@ You can also use:
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
as described in <ahref="https://docs.pydantic.dev/latest/concepts/serialization/#modeldict"class="external-link"target="_blank">the Pydantic docs</a> for `exclude_defaults` and `exclude_none`.
as described in <ahref="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict"class="external-link"target="_blank">the Pydantic docs</a> for `exclude_defaults` and `exclude_none`.
@ -44,7 +44,7 @@ That extra info will be added as-is to the output **JSON Schema** for that model
//// tab | Pydantic v2
In Pydantic version 2, you would use the attribute `model_config`, that takes a `dict` as described in <ahref="https://docs.pydantic.dev/latest/usage/model_config/"class="external-link"target="_blank">Pydantic's docs: Model Config</a>.
In Pydantic version 2, you would use the attribute `model_config`, that takes a `dict` as described in <ahref="https://docs.pydantic.dev/latest/api/config/"class="external-link"target="_blank">Pydantic's docs: Configuration</a>.
You can set `"json_schema_extra"` with a `dict` containing any additional data you would like to show up in the generated JSON Schema, including `examples`.