* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
* As the `q` parameter is declared with `= None`, it is optional.
* Without the `None` it would be required (as is the body in the case with `PUT`).
-* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
+* For `PUT` requests to `/items/{item_id}`, read the body as JSON:
* Check that it has a required attribute `name` that should be a `str`.
* Check that it has a required attribute `price` that has to be a `float`.
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
## Using the `jsonable_encoder` in a `Response`
-Because **FastAPI** doesn't do any change to a `Response` you return, you have to make sure it's contents are ready for it.
+Because **FastAPI** doesn't do any change to a `Response` you return, you have to make sure its contents are ready for it.
For example, you cannot put a Pydantic model in a `JSONResponse` without first converting it to a `dict` with all the data types (like `datetime`, `UUID`, etc) converted to JSON-compatible types.
### Concurrency + Parallelism: Web + Machine Learning
-With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attraction of NodeJS).
+With **FastAPI** you can take advantage of concurrency that is very common for web development (the same main attraction of NodeJS).
But you can also exploit the benefits of parallelism and multiprocessing (having multiple processes running in parallel) for **CPU bound** workloads like those in Machine Learning systems.
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
* As the `q` parameter is declared with `= None`, it is optional.
* Without the `None` it would be required (as is the body in the case with `PUT`).
-* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
+* For `PUT` requests to `/items/{item_id}`, read the body as JSON:
* Check that it has a required attribute `name` that should be a `str`.
* Check that it has a required attribute `price` that has to be a `float`.
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
{!../../../docs_src/python_types/tutorial009.py!}
```
-Using `Optional[str]` instead of just `str` will let the editor help you detecting errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
+Using `Optional[str]` instead of just `str` will let the editor help you detect errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
`Optional[Something]` is actually a shortcut for `Union[Something, None]`, they are equivalent.
# Bigger Applications - Multiple Files
-If you are building an application or a web API, it's rarely the case that you can put everything on a single file.
+If you are building an application or a web API, it's rarely the case that you can put everything in a single file.
**FastAPI** provides a convenience tool to structure your application while keeping all the flexibility.
{!../../../docs_src/bigger_applications/app/main.py!}
```
-That way, the original `APIRouter` will keep unmodified, so we can still share that same `app/internal/admin.py` file with other projects in the organization.
+That way, the original `APIRouter` will stay unmodified, so we can still share that same `app/internal/admin.py` file with other projects in the organization.
The result is that in our app, each of the *path operations* from the `admin` module will have:
////
-In this case, **FastAPI** will notice that there are more than one body parameters in the function (two parameters that are Pydantic models).
+In this case, **FastAPI** will notice that there is more than one body parameter in the function (there are two parameters that are Pydantic models).
So, it will then use the parameter names as keys (field names) in the body, and expect a body like:
* Put that data in a Pydantic model.
* Generate a `dict` without default values from the input model (using `exclude_unset`).
* This way you can update only the values actually set by the user, instead of overriding values already stored with default values in your model.
-* Create a copy of the stored model, updating it's attributes with the received partial updates (using the `update` parameter).
+* Create a copy of the stored model, updating its attributes with the received partial updates (using the `update` parameter).
* Convert the copied model to something that can be stored in your DB (for example, using the `jsonable_encoder`).
* This is comparable to using the model's `.model_dump()` method again, but it makes sure (and converts) the values to data types that can be converted to JSON, for example, `datetime` to `str`.
* Save the data to your DB.
<img src="/img/tutorial/body/image01.png">
-And will be also used in the API docs inside each *path operation* that needs them:
+And will also be used in the API docs inside each *path operation* that needs them:
<img src="/img/tutorial/body/image02.png">
* Create a list of allowed origins (as strings).
* Add it as a "middleware" to your **FastAPI** application.
-You can also specify if your backend allows:
+You can also specify whether your backend allows:
* Credentials (Authorization headers, Cookies, etc).
* Specific HTTP methods (`POST`, `PUT`) or all of them with the wildcard `"*"`.
...is what **FastAPI** will actually use to know what is the dependency.
-From it is that FastAPI will extract the declared parameters and that is what FastAPI will actually call.
+It is from this one that FastAPI will extract the declared parameters and that is what FastAPI will actually call.
---
* `Decimal`:
* Standard Python `Decimal`.
* In requests and responses, handled the same as a `float`.
-* You can check all the valid pydantic data types here: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic data types</a>.
+* You can check all the valid Pydantic data types here: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic data types</a>.
## Example
**FastAPI** uses it so that, if you use a Pydantic model in `response_model`, and your data has an error, you will see the error in your log.
-But the client/user will not see it. Instead, the client will receive an "Internal Server Error" with a HTTP status code `500`.
+But the client/user will not see it. Instead, the client will receive an "Internal Server Error" with an HTTP status code `500`.
It should be this way because if you have a Pydantic `ValidationError` in your *response* or anywhere in your code (not in the client's *request*), it's actually a bug in your code.
### Reuse **FastAPI**'s exception handlers
-If you want to use the exception along with the same default exception handlers from **FastAPI**, You can import and reuse the default exception handlers from `fastapi.exception_handlers`:
+If you want to use the exception along with the same default exception handlers from **FastAPI**, you can import and reuse the default exception handlers from `fastapi.exception_handlers`:
```Python hl_lines="2-5 15 21"
{!../../../docs_src/handling_errors/tutorial006.py!}
There is also an **Advanced User Guide** that you can read later after this **Tutorial - User guide**.
-The **Advanced User Guide**, builds on this, uses the same concepts, and teaches you some extra features.
+The **Advanced User Guide** builds on this one, uses the same concepts, and teaches you some extra features.
But you should first read the **Tutorial - User Guide** (what you are reading right now).
* A function `call_next` that will receive the `request` as a parameter.
* This function will pass the `request` to the corresponding *path operation*.
* Then it returns the `response` generated by the corresponding *path operation*.
-* You can then modify further the `response` before returning it.
+* You can then further modify the `response` before returning it.
```Python hl_lines="8-9 11 14"
{!../../../docs_src/middleware/tutorial001.py!}
You could **call** that same function in **other places** without FastAPI, and it would **work as expected**. If there's a **required** parameter (without a default value), your **editor** will let you know with an error, **Python** will also complain if you run it without passing the required parameter.
-When you don't use `Annotated` and instead use the **(old) default value style**, if you call that function without FastAPI in **other place**, you have to **remember** to pass the arguments to the function for it to work correctly, otherwise the values will be different from what you expect (e.g. `QueryInfo` or something similar instead of `str`). And your editor won't complain, and Python won't complain running that function, only when the operations inside error out.
+When you don't use `Annotated` and instead use the **(old) default value style**, if you call that function without FastAPI in **other places**, you have to **remember** to pass the arguments to the function for it to work correctly, otherwise the values will be different from what you expect (e.g. `QueryInfo` or something similar instead of `str`). And your editor won't complain, and Python won't complain running that function, only when the operations inside error out.
Because `Annotated` can have more than one metadata annotation, you could now even use the same function with other tools, like <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. 🚀
## Query parameter list / multiple values
-When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in other way, to receive multiple values.
+When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in another way, to receive multiple values.
For example, to declare a query parameter `q` that can appear multiple times in the URL, you can write:
In these examples you saw how to declare validations for `str` values.
-See the next chapters to see how to declare validations for other types, like numbers.
+See the next chapters to learn how to declare validations for other types, like numbers.
Before OpenAPI 3.1.0, OpenAPI used an older and modified version of **JSON Schema**.
-JSON Schema didn't have `examples`, so OpenAPI added it's own `example` field to its own modified version.
+JSON Schema didn't have `examples`, so OpenAPI added its own `example` field to its own modified version.
OpenAPI also added `example` and `examples` fields to other parts of the specification:
But it's the best one for our use case.
-And it might be the best for most use cases, unless you are an OAuth2 expert and know exactly why there's another option that suits better your needs.
+And it might be the best for most use cases, unless you are an OAuth2 expert and know exactly why there's another option that better suits your needs.
In that case, **FastAPI** also provides you with the tools to build it.
But you can have thousands of endpoints (*path operations*) using the same security system.
-And all of them (or any portion of them that you want) can take the advantage of re-using these dependencies or any other dependencies you create.
+And all of them (or any portion of them that you want) can take advantage of re-using these dependencies or any other dependencies you create.
And all these thousands of *path operations* can be as small as 3 lines: