]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
📝 Add permalinks to headers in English docs (#13993)
authorMotov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Sun, 31 Aug 2025 09:15:41 +0000 (11:15 +0200)
committerGitHub <noreply@github.com>
Sun, 31 Aug 2025 09:15:41 +0000 (09:15 +0000)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
112 files changed:
README.md
docs/en/docs/about/index.md
docs/en/docs/advanced/additional-responses.md
docs/en/docs/advanced/additional-status-codes.md
docs/en/docs/advanced/advanced-dependencies.md
docs/en/docs/advanced/async-tests.md
docs/en/docs/advanced/behind-a-proxy.md
docs/en/docs/advanced/custom-response.md
docs/en/docs/advanced/dataclasses.md
docs/en/docs/advanced/events.md
docs/en/docs/advanced/generate-clients.md
docs/en/docs/advanced/index.md
docs/en/docs/advanced/middleware.md
docs/en/docs/advanced/openapi-callbacks.md
docs/en/docs/advanced/openapi-webhooks.md
docs/en/docs/advanced/path-operation-advanced-configuration.md
docs/en/docs/advanced/response-change-status-code.md
docs/en/docs/advanced/response-cookies.md
docs/en/docs/advanced/response-directly.md
docs/en/docs/advanced/response-headers.md
docs/en/docs/advanced/security/http-basic-auth.md
docs/en/docs/advanced/security/index.md
docs/en/docs/advanced/security/oauth2-scopes.md
docs/en/docs/advanced/settings.md
docs/en/docs/advanced/sub-applications.md
docs/en/docs/advanced/templates.md
docs/en/docs/advanced/testing-dependencies.md
docs/en/docs/advanced/testing-events.md
docs/en/docs/advanced/testing-websockets.md
docs/en/docs/advanced/using-request-directly.md
docs/en/docs/advanced/websockets.md
docs/en/docs/advanced/wsgi.md
docs/en/docs/alternatives.md
docs/en/docs/async.md
docs/en/docs/benchmarks.md
docs/en/docs/deployment/cloud.md
docs/en/docs/deployment/concepts.md
docs/en/docs/deployment/docker.md
docs/en/docs/deployment/https.md
docs/en/docs/deployment/index.md
docs/en/docs/deployment/manually.md
docs/en/docs/deployment/server-workers.md
docs/en/docs/deployment/versions.md
docs/en/docs/environment-variables.md
docs/en/docs/fastapi-cli.md
docs/en/docs/features.md
docs/en/docs/help-fastapi.md
docs/en/docs/history-design-future.md
docs/en/docs/how-to/conditional-openapi.md
docs/en/docs/how-to/configure-swagger-ui.md
docs/en/docs/how-to/custom-docs-ui-assets.md
docs/en/docs/how-to/custom-request-and-route.md
docs/en/docs/how-to/extending-openapi.md
docs/en/docs/how-to/general.md
docs/en/docs/how-to/graphql.md
docs/en/docs/how-to/index.md
docs/en/docs/how-to/separate-openapi-schemas.md
docs/en/docs/how-to/testing-database.md
docs/en/docs/index.md
docs/en/docs/learn/index.md
docs/en/docs/project-generation.md
docs/en/docs/python-types.md
docs/en/docs/resources/index.md
docs/en/docs/tutorial/background-tasks.md
docs/en/docs/tutorial/bigger-applications.md
docs/en/docs/tutorial/body-fields.md
docs/en/docs/tutorial/body-multiple-params.md
docs/en/docs/tutorial/body-nested-models.md
docs/en/docs/tutorial/body-updates.md
docs/en/docs/tutorial/body.md
docs/en/docs/tutorial/cookie-param-models.md
docs/en/docs/tutorial/cookie-params.md
docs/en/docs/tutorial/cors.md
docs/en/docs/tutorial/debugging.md
docs/en/docs/tutorial/dependencies/classes-as-dependencies.md
docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
docs/en/docs/tutorial/dependencies/dependencies-with-yield.md
docs/en/docs/tutorial/dependencies/global-dependencies.md
docs/en/docs/tutorial/dependencies/index.md
docs/en/docs/tutorial/dependencies/sub-dependencies.md
docs/en/docs/tutorial/encoder.md
docs/en/docs/tutorial/extra-data-types.md
docs/en/docs/tutorial/extra-models.md
docs/en/docs/tutorial/first-steps.md
docs/en/docs/tutorial/handling-errors.md
docs/en/docs/tutorial/header-param-models.md
docs/en/docs/tutorial/header-params.md
docs/en/docs/tutorial/index.md
docs/en/docs/tutorial/metadata.md
docs/en/docs/tutorial/middleware.md
docs/en/docs/tutorial/path-operation-configuration.md
docs/en/docs/tutorial/path-params-numeric-validations.md
docs/en/docs/tutorial/path-params.md
docs/en/docs/tutorial/query-param-models.md
docs/en/docs/tutorial/query-params-str-validations.md
docs/en/docs/tutorial/query-params.md
docs/en/docs/tutorial/request-files.md
docs/en/docs/tutorial/request-form-models.md
docs/en/docs/tutorial/request-forms-and-files.md
docs/en/docs/tutorial/request-forms.md
docs/en/docs/tutorial/response-model.md
docs/en/docs/tutorial/response-status-code.md
docs/en/docs/tutorial/schema-extra-example.md
docs/en/docs/tutorial/security/first-steps.md
docs/en/docs/tutorial/security/get-current-user.md
docs/en/docs/tutorial/security/index.md
docs/en/docs/tutorial/security/oauth2-jwt.md
docs/en/docs/tutorial/security/simple-oauth2.md
docs/en/docs/tutorial/sql-databases.md
docs/en/docs/tutorial/static-files.md
docs/en/docs/tutorial/testing.md
docs/en/docs/virtual-environments.md

index 0e421c347ae4db7e33f69bdc7168d667bf06ab1d..95d1238191343312243742b7ca348d5e84fb7961 100644 (file)
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ The key features are:
 
 <small>* estimation based on tests on an internal development team, building production applications.</small>
 
-## Sponsors
+## Sponsors { #sponsors }
 
 <!-- sponsors -->
 
@@ -69,7 +69,7 @@ The key features are:
 
 <a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
 
-## Opinions
+## Opinions { #opinions }
 
 "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
 
@@ -115,7 +115,7 @@ The key features are:
 
 ---
 
-## **Typer**, the FastAPI of CLIs
+## **Typer**, the FastAPI of CLIs { #typer-the-fastapi-of-clis }
 
 <a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
 
@@ -123,14 +123,14 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
 
 **Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
 
-## Requirements
+## Requirements { #requirements }
 
 FastAPI stands on the shoulders of giants:
 
 * <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
 * <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> for the data parts.
 
-## Installation
+## Installation { #installation }
 
 Create and activate a <a href="https://fastapi.tiangolo.com/virtual-environments/" class="external-link" target="_blank">virtual environment</a> and then install FastAPI:
 
@@ -146,9 +146,9 @@ $ pip install "fastapi[standard]"
 
 **Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals.
 
-## Example
+## Example { #example }
 
-### Create it
+### Create it { #create-it }
 
 Create a file `main.py` with:
 
@@ -199,7 +199,7 @@ If you don't know, check the _"In a hurry?"_ section about <a href="https://fast
 
 </details>
 
-### Run it
+### Run it { #run-it }
 
 Run the server with:
 
@@ -241,7 +241,7 @@ You can read more about it in the <a href="https://fastapi.tiangolo.com/fastapi-
 
 </details>
 
-### Check it
+### Check it { #check-it }
 
 Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
 
@@ -258,7 +258,7 @@ You already created an API that:
 * The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
 * The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
 
-### Interactive API docs
+### Interactive API docs { #interactive-api-docs }
 
 Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
@@ -266,7 +266,7 @@ You will see the automatic interactive API documentation (provided by <a href="h
 
 ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
 
-### Alternative API docs
+### Alternative API docs { #alternative-api-docs }
 
 And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
 
@@ -274,7 +274,7 @@ You will see the alternative automatic documentation (provided by <a href="https
 
 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
 
-## Example upgrade
+## Example upgrade { #example-upgrade }
 
 Now modify the file `main.py` to receive a body from a `PUT` request.
 
@@ -312,7 +312,7 @@ def update_item(item_id: int, item: Item):
 
 The `fastapi dev` server should reload automatically.
 
-### Interactive API docs upgrade
+### Interactive API docs upgrade { #interactive-api-docs-upgrade }
 
 Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
@@ -328,7 +328,7 @@ Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_bl
 
 ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
 
-### Alternative API docs upgrade
+### Alternative API docs upgrade { #alternative-api-docs-upgrade }
 
 And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
 
@@ -336,7 +336,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
 
 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
 
-### Recap
+### Recap { #recap }
 
 In summary, you declare **once** the types of parameters, body, etc. as function parameters.
 
@@ -448,17 +448,17 @@ For a more complete example including more features, see the <a href="https://fa
     * **Cookie Sessions**
     * ...and more.
 
-## Performance
+## Performance { #performance }
 
 Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
 
 To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
 
-## Dependencies
+## Dependencies { #dependencies }
 
 FastAPI depends on Pydantic and Starlette.
 
-### `standard` Dependencies
+### `standard` Dependencies { #standard-dependencies }
 
 When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies:
 
@@ -478,15 +478,15 @@ Used by FastAPI:
 * `fastapi-cli[standard]` - to provide the `fastapi` command.
     * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
 
-### Without `standard` Dependencies
+### Without `standard` Dependencies { #without-standard-dependencies }
 
 If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`.
 
-### Without `fastapi-cloud-cli`
+### Without `fastapi-cloud-cli` { #without-fastapi-cloud-cli }
 
 If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
 
-### Additional Optional Dependencies
+### Additional Optional Dependencies { #additional-optional-dependencies }
 
 There are some additional dependencies you might want to install.
 
@@ -500,6 +500,6 @@ Additional optional FastAPI dependencies:
 * <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
 * <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
 
-## License
+## License { #license }
 
 This project is licensed under the terms of the MIT license.
index 27b78696b55b0273b4d8265f3970d9515601039a..d178dfec75b23375f1cdca030a3687dcf57a5b71 100644 (file)
@@ -1,3 +1,3 @@
-# About
+# About { #about }
 
 About FastAPI, its design, inspiration and more. 🤓
index 03d48c2a710a7096dacac52ab888db65eac6d148..799532c5b2291b5bfac3c43c324ef6778b2deb70 100644 (file)
@@ -1,4 +1,4 @@
-# Additional Responses in OpenAPI
+# Additional Responses in OpenAPI { #additional-responses-in-openapi }
 
 /// warning
 
@@ -14,7 +14,7 @@ Those additional responses will be included in the OpenAPI schema, so they will
 
 But for those additional responses you have to make sure you return a `Response` like `JSONResponse` directly, with your status code and content.
 
-## Additional Response with `model`
+## Additional Response with `model` { #additional-response-with-model }
 
 You can pass to your *path operation decorators* a parameter `responses`.
 
@@ -169,7 +169,7 @@ The schemas are referenced to another place inside the OpenAPI schema:
 }
 ```
 
-## Additional media types for the main response
+## Additional media types for the main response { #additional-media-types-for-the-main-response }
 
 You can use this same `responses` parameter to add different media types for the same main response.
 
@@ -191,7 +191,7 @@ But if you have specified a custom response class with `None` as its media type,
 
 ///
 
-## Combining information
+## Combining information { #combining-information }
 
 You can also combine response information from multiple places, including the `response_model`, `status_code`, and `responses` parameters.
 
@@ -209,7 +209,7 @@ It will all be combined and included in your OpenAPI, and shown in the API docs:
 
 <img src="/img/tutorial/additional-responses/image01.png">
 
-## Combine predefined responses and custom ones
+## Combine predefined responses and custom ones { #combine-predefined-responses-and-custom-ones }
 
 You might want to have some predefined responses that apply to many *path operations*, but you want to combine them with custom responses needed by each *path operation*.
 
@@ -239,7 +239,7 @@ For example:
 
 {* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
 
-## More information about OpenAPI responses
+## More information about OpenAPI responses { #more-information-about-openapi-responses }
 
 To see what exactly you can include in the responses, you can check these sections in the OpenAPI specification:
 
index 077a00488a0965e2c3b0a6c5dfd2b496e6158400..23bcd13c328dda02ca9d0cbc4ce996b9314a9e7e 100644 (file)
@@ -1,10 +1,10 @@
-# Additional Status Codes
+# Additional Status Codes { #additional-status-codes }
 
 By default, **FastAPI** will return the responses using a `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`.
 
 It will use the default status code or the one you set in your *path operation*.
 
-## Additional status codes
+## Additional status codes { #additional-status-codes_1 }
 
 If you want to return additional status codes apart from the main one, you can do that by returning a `Response` directly, like a `JSONResponse`, and set the additional status code directly.
 
@@ -34,7 +34,7 @@ You could also use `from starlette.responses import JSONResponse`.
 
 ///
 
-## OpenAPI and API docs
+## OpenAPI and API docs { #openapi-and-api-docs }
 
 If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know beforehand what you are going to return.
 
index f933fd264cf7499a69743a521967b733ffb5d9df..c71c114049c184773cad77a149904915c281e55c 100644 (file)
@@ -1,6 +1,6 @@
-# Advanced Dependencies
+# Advanced Dependencies { #advanced-dependencies }
 
-## Parameterized dependencies
+## Parameterized dependencies { #parameterized-dependencies }
 
 All the dependencies we have seen are a fixed function or class.
 
@@ -10,7 +10,7 @@ Let's imagine that we want to have a dependency that checks if the query paramet
 
 But we want to be able to parameterize that fixed content.
 
-## A "callable" instance
+## A "callable" instance { #a-callable-instance }
 
 In Python there's a way to make an instance of a class a "callable".
 
@@ -22,7 +22,7 @@ To do that, we declare a method `__call__`:
 
 In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later.
 
-## Parameterize the instance
+## Parameterize the instance { #parameterize-the-instance }
 
 And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency:
 
@@ -30,7 +30,7 @@ And now, we can use `__init__` to declare the parameters of the instance that we
 
 In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code.
 
-## Create an instance
+## Create an instance { #create-an-instance }
 
 We could create an instance of this class with:
 
@@ -38,7 +38,7 @@ We could create an instance of this class with:
 
 And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`.
 
-## Use the instance as a dependency
+## Use the instance as a dependency { #use-the-instance-as-a-dependency }
 
 Then, we could use this `checker` in a `Depends(checker)`, instead of `Depends(FixedContentQueryChecker)`, because the dependency is the instance, `checker`, not the class itself.
 
index 8d692922204170ee9f6dd30d40c4181061d76674..7b6f083711e0d82cb2bb51c8c39a9a8bda428aa8 100644 (file)
@@ -1,4 +1,4 @@
-# Async Tests
+# Async Tests { #async-tests }
 
 You have already seen how to test your **FastAPI** applications using the provided `TestClient`. Up to now, you have only seen how to write synchronous tests, without using `async` functions.
 
@@ -6,11 +6,11 @@ Being able to use asynchronous functions in your tests could be useful, for exam
 
 Let's look at how we can make that work.
 
-## pytest.mark.anyio
+## pytest.mark.anyio { #pytest-mark-anyio }
 
 If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. AnyIO provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously.
 
-## HTTPX
+## HTTPX { #httpx }
 
 Even if your **FastAPI** application uses normal `def` functions instead of `async def`, it is still an `async` application underneath.
 
@@ -18,7 +18,7 @@ The `TestClient` does some magic inside to call the asynchronous FastAPI applica
 
 The `TestClient` is based on <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, and luckily, we can use it directly to test the API.
 
-## Example
+## Example { #example }
 
 For a simple example, let's consider a file structure similar to the one described in [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} and [Testing](../tutorial/testing.md){.internal-link target=_blank}:
 
@@ -38,7 +38,7 @@ The file `test_main.py` would have the tests for `main.py`, it could look like t
 
 {* ../../docs_src/async_tests/test_main.py *}
 
-## Run it
+## Run it { #run-it }
 
 You can run your tests as usual via:
 
@@ -52,7 +52,7 @@ $ pytest
 
 </div>
 
-## In Detail
+## In Detail { #in-detail }
 
 The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously:
 
@@ -88,7 +88,7 @@ If your application relies on lifespan events, the `AsyncClient` won't trigger t
 
 ///
 
-## Other Asynchronous Function Calls
+## Other Asynchronous Function Calls { #other-asynchronous-function-calls }
 
 As the testing function is now asynchronous, you can now also call (and `await`) other `async` functions apart from sending requests to your FastAPI application in your tests, exactly as you would call them anywhere else in your code.
 
index 1f0d0fd9f97575ea971b54eb914a62a664ab1f2f..0f100306ae8b4d616b18f51aba67697fd79bb724 100644 (file)
@@ -1,4 +1,4 @@
-# Behind a Proxy
+# Behind a Proxy { #behind-a-proxy }
 
 In some situations, you might need to use a **proxy** server like Traefik or Nginx with a configuration that adds an extra path prefix that is not seen by your application.
 
@@ -10,7 +10,7 @@ The `root_path` is used to handle these specific cases.
 
 And it's also used internally when mounting sub-applications.
 
-## Proxy with a stripped path prefix
+## Proxy with a stripped path prefix { #proxy-with-a-stripped-path-prefix }
 
 Having a proxy with a stripped path prefix, in this case, means that you could declare a path at `/app` in your code, but then, you add a layer on top (the proxy) that would put your **FastAPI** application under a path like `/api/v1`.
 
@@ -66,7 +66,7 @@ The docs UI would also need the OpenAPI schema to declare that this API `server`
 
 In this example, the "Proxy" could be something like **Traefik**. And the server would be something like FastAPI CLI with **Uvicorn**, running your FastAPI application.
 
-### Providing the `root_path`
+### Providing the `root_path` { #providing-the-root-path }
 
 To achieve this, you can use the command line option `--root-path` like:
 
@@ -90,7 +90,7 @@ And the `--root-path` command line option provides that `root_path`.
 
 ///
 
-### Checking the current `root_path`
+### Checking the current `root_path` { #checking-the-current-root-path }
 
 You can get the current `root_path` used by your application for each request, it is part of the `scope` dictionary (that's part of the ASGI spec).
 
@@ -119,7 +119,7 @@ The response would be something like:
 }
 ```
 
-### Setting the `root_path` in the FastAPI app
+### Setting the `root_path` in the FastAPI app { #setting-the-root-path-in-the-fastapi-app }
 
 Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app:
 
@@ -127,7 +127,7 @@ Alternatively, if you don't have a way to provide a command line option like `--
 
 Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn.
 
-### About `root_path`
+### About `root_path` { #about-root-path }
 
 Keep in mind that the server (Uvicorn) won't use that `root_path` for anything else than passing it to the app.
 
@@ -144,7 +144,7 @@ So, it won't expect to be accessed at `http://127.0.0.1:8000/api/v1/app`.
 
 Uvicorn will expect the proxy to access Uvicorn at `http://127.0.0.1:8000/app`, and then it would be the proxy's responsibility to add the extra `/api/v1` prefix on top.
 
-## About proxies with a stripped path prefix
+## About proxies with a stripped path prefix { #about-proxies-with-a-stripped-path-prefix }
 
 Keep in mind that a proxy with stripped path prefix is only one of the ways to configure it.
 
@@ -152,7 +152,7 @@ Probably in many cases the default will be that the proxy doesn't have a strippe
 
 In a case like that (without a stripped path prefix), the proxy would listen on something like `https://myawesomeapp.com`, and then if the browser goes to `https://myawesomeapp.com/api/v1/app` and your server (e.g. Uvicorn) listens on `http://127.0.0.1:8000` the proxy (without a stripped path prefix) would access Uvicorn at the same path: `http://127.0.0.1:8000/api/v1/app`.
 
-## Testing locally with Traefik
+## Testing locally with Traefik { #testing-locally-with-traefik }
 
 You can easily run the experiment locally with a stripped path prefix using <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
 
@@ -231,7 +231,7 @@ $ fastapi run main.py --root-path /api/v1
 
 </div>
 
-### Check the responses
+### Check the responses { #check-the-responses }
 
 Now, if you go to the URL with the port for Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, you will see the normal response:
 
@@ -267,7 +267,7 @@ And the version without the path prefix (`http://127.0.0.1:8000/app`), provided
 
 That demonstrates how the Proxy (Traefik) uses the path prefix and how the server (Uvicorn) uses the `root_path` from the option `--root-path`.
 
-### Check the docs UI
+### Check the docs UI { #check-the-docs-ui }
 
 But here's the fun part. ✨
 
@@ -287,7 +287,7 @@ Right as we wanted it. ✔️
 
 This is because FastAPI uses this `root_path` to create the default `server` in OpenAPI with the URL provided by `root_path`.
 
-## Additional servers
+## Additional servers { #additional-servers }
 
 /// warning
 
@@ -346,7 +346,7 @@ The docs UI will interact with the server that you select.
 
 ///
 
-### Disable automatic server from `root_path`
+### Disable automatic server from `root_path` { #disable-automatic-server-from-root-path }
 
 If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`:
 
@@ -354,7 +354,7 @@ If you don't want **FastAPI** to include an automatic server using the `root_pat
 
 and then it won't include it in the OpenAPI schema.
 
-## Mounting a sub-application
+## Mounting a sub-application { #mounting-a-sub-application }
 
 If you need to mount a sub-application (as described in [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}) while also using a proxy with `root_path`, you can do it normally, as you would expect.
 
index 8268dd81a9a4870b233feb1f56f629f2e6568471..5473d939ce5950d3cc4dce37e51892346856b495 100644 (file)
@@ -1,4 +1,4 @@
-# Custom Response - HTML, Stream, File, others
+# Custom Response - HTML, Stream, File, others { #custom-response-html-stream-file-others }
 
 By default, **FastAPI** will return the responses using `JSONResponse`.
 
@@ -18,7 +18,7 @@ If you use a response class with no media type, FastAPI will expect your respons
 
 ///
 
-## Use `ORJSONResponse`
+## Use `ORJSONResponse` { #use-orjsonresponse }
 
 For example, if you are squeezing performance, you can install and use <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> and set the response to be `ORJSONResponse`.
 
@@ -48,7 +48,7 @@ The `ORJSONResponse` is only available in FastAPI, not in Starlette.
 
 ///
 
-## HTML Response
+## HTML Response { #html-response }
 
 To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
 
@@ -67,7 +67,7 @@ And it will be documented as such in OpenAPI.
 
 ///
 
-### Return a `Response`
+### Return a `Response` { #return-a-response }
 
 As seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}, you can also override the response directly in your *path operation*, by returning it.
 
@@ -87,13 +87,13 @@ Of course, the actual `Content-Type` header, status code, etc, will come from th
 
 ///
 
-### Document in OpenAPI and override `Response`
+### Document in OpenAPI and override `Response` { #document-in-openapi-and-override-response }
 
 If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `response_class` parameter AND return a `Response` object.
 
 The `response_class` will then be used only to document the OpenAPI *path operation*, but your `Response` will be used as is.
 
-#### Return an `HTMLResponse` directly
+#### Return an `HTMLResponse` directly { #return-an-htmlresponse-directly }
 
 For example, it could be something like:
 
@@ -107,7 +107,7 @@ But as you passed the `HTMLResponse` in the `response_class` too, **FastAPI** wi
 
 <img src="/img/tutorial/custom-response/image01.png">
 
-## Available responses
+## Available responses { #available-responses }
 
 Here are some of the available responses.
 
@@ -121,7 +121,7 @@ You could also use `from starlette.responses import HTMLResponse`.
 
 ///
 
-### `Response`
+### `Response` { #response }
 
 The main `Response` class, all the other responses inherit from it.
 
@@ -138,23 +138,23 @@ FastAPI (actually Starlette) will automatically include a Content-Length header.
 
 {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
 
-### `HTMLResponse`
+### `HTMLResponse` { #htmlresponse }
 
 Takes some text or bytes and returns an HTML response, as you read above.
 
-### `PlainTextResponse`
+### `PlainTextResponse` { #plaintextresponse }
 
 Takes some text or bytes and returns a plain text response.
 
 {* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
 
-### `JSONResponse`
+### `JSONResponse` { #jsonresponse }
 
 Takes some data and returns an `application/json` encoded response.
 
 This is the default response used in **FastAPI**, as you read above.
 
-### `ORJSONResponse`
+### `ORJSONResponse` { #orjsonresponse }
 
 A fast alternative JSON response using <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, as you read above.
 
@@ -164,7 +164,7 @@ This requires installing `orjson` for example with `pip install orjson`.
 
 ///
 
-### `UJSONResponse`
+### `UJSONResponse` { #ujsonresponse }
 
 An alternative JSON response using <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
 
@@ -188,7 +188,7 @@ It's possible that `ORJSONResponse` might be a faster alternative.
 
 ///
 
-### `RedirectResponse`
+### `RedirectResponse` { #redirectresponse }
 
 Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default.
 
@@ -213,13 +213,13 @@ You can also use the `status_code` parameter combined with the `response_class`
 
 {* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
 
-### `StreamingResponse`
+### `StreamingResponse` { #streamingresponse }
 
 Takes an async generator or a normal generator/iterator and streams the response body.
 
 {* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
 
-#### Using `StreamingResponse` with file-like objects
+#### Using `StreamingResponse` with file-like objects { #using-streamingresponse-with-file-like-objects }
 
 If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object.
 
@@ -243,7 +243,7 @@ Notice that here as we are using standard `open()` that doesn't support `async`
 
 ///
 
-### `FileResponse`
+### `FileResponse` { #fileresponse }
 
 Asynchronously streams a file as the response.
 
@@ -264,7 +264,7 @@ You can also use the `response_class` parameter:
 
 In this case, you can return the file path directly from your *path operation* function.
 
-## Custom response class
+## Custom response class { #custom-response-class }
 
 You can create your own custom response class, inheriting from `Response` and using it.
 
@@ -292,7 +292,7 @@ Now instead of returning:
 
 Of course, you will probably find much better ways to take advantage of this than formatting JSON. 😉
 
-## Default response class
+## Default response class { #default-response-class }
 
 When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
 
@@ -308,6 +308,6 @@ You can still override `response_class` in *path operations* as before.
 
 ///
 
-## Additional documentation
+## Additional documentation { #additional-documentation }
 
 You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
index 2936c6d5dc34c8fe1c9d8df79e8584eb0a1a8334..b7b9b65c52fcef16cdb15a65b325b9eaf38a4aba 100644 (file)
@@ -1,4 +1,4 @@
-# Using Dataclasses
+# Using Dataclasses { #using-dataclasses }
 
 FastAPI is built on top of **Pydantic**, and I have been showing you how to use Pydantic models to declare requests and responses.
 
@@ -28,7 +28,7 @@ But if you have a bunch of dataclasses laying around, this is a nice trick to us
 
 ///
 
-## Dataclasses in `response_model`
+## Dataclasses in `response_model` { #dataclasses-in-response-model }
 
 You can also use `dataclasses` in the `response_model` parameter:
 
@@ -40,7 +40,7 @@ This way, its schema will show up in the API docs user interface:
 
 <img src="/img/tutorial/dataclasses/image01.png">
 
-## Dataclasses in Nested Data Structures
+## Dataclasses in Nested Data Structures { #dataclasses-in-nested-data-structures }
 
 You can also combine `dataclasses` with other type annotations to make nested data structures.
 
@@ -84,12 +84,12 @@ You can combine `dataclasses` with other type annotations in many different comb
 
 Check the in-code annotation tips above to see more specific details.
 
-## Learn More
+## Learn More { #learn-more }
 
 You can also combine `dataclasses` with other Pydantic models, inherit from them, include them in your own models, etc.
 
 To learn more, check the <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">Pydantic docs about dataclasses</a>.
 
-## Version
+## Version { #version }
 
 This is available since FastAPI version `0.67.0`. 🔖
index 19465d891cadce173bfb4f45c23172a27148fbce..c805e81ee94712d1bed6ecb72c9e7967a57f981f 100644 (file)
@@ -1,4 +1,4 @@
-# Lifespan Events
+# Lifespan Events { #lifespan-events }
 
 You can define logic (code) that should be executed before the application **starts up**. This means that this code will be executed **once**, **before** the application **starts receiving requests**.
 
@@ -8,7 +8,7 @@ Because this code is executed before the application **starts** taking requests,
 
 This can be very useful for setting up **resources** that you need to use for the whole app, and that are **shared** among requests, and/or that you need to **clean up** afterwards. For example, a database connection pool, or loading a shared machine learning model.
 
-## Use Case
+## Use Case { #use-case }
 
 Let's start with an example **use case** and then see how to solve it with this.
 
@@ -22,7 +22,7 @@ You could load it at the top level of the module/file, but that would also mean
 
 That's what we'll solve, let's load the model before the requests are handled, but only right before the application starts receiving requests, not while  the code is being loaded.
 
-## Lifespan
+## Lifespan { #lifespan }
 
 You can define this *startup* and *shutdown* logic using the `lifespan` parameter of the `FastAPI` app, and a "context manager" (I'll show you what that is in a second).
 
@@ -44,7 +44,7 @@ Maybe you need to start a new version, or you just got tired of running it. 🤷
 
 ///
 
-### Lifespan function
+### Lifespan function { #lifespan-function }
 
 The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`.
 
@@ -54,7 +54,7 @@ The first part of the function, before the `yield`, will be executed **before**
 
 And the part after the `yield` will be executed **after** the application has finished.
 
-### Async Context Manager
+### Async Context Manager { #async-context-manager }
 
 If you check, the function is decorated with an `@asynccontextmanager`.
 
@@ -84,7 +84,7 @@ The `lifespan` parameter of the `FastAPI` app takes an **async context manager**
 
 {* ../../docs_src/events/tutorial003.py hl[22] *}
 
-## Alternative Events (deprecated)
+## Alternative Events (deprecated) { #alternative-events-deprecated }
 
 /// warning
 
@@ -100,7 +100,7 @@ You can define event handlers (functions) that need to be executed before the ap
 
 These functions can be declared with `async def` or normal `def`.
 
-### `startup` event
+### `startup` event { #startup-event }
 
 To add a function that should be run before the application starts, declare it with the event `"startup"`:
 
@@ -112,7 +112,7 @@ You can add more than one event handler function.
 
 And your application won't start receiving requests until all the `startup` event handlers have completed.
 
-### `shutdown` event
+### `shutdown` event { #shutdown-event }
 
 To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`:
 
@@ -138,7 +138,7 @@ So, we declare the event handler function with standard `def` instead of `async
 
 ///
 
-### `startup` and `shutdown` together
+### `startup` and `shutdown` together { #startup-and-shutdown-together }
 
 There's a high chance that the logic for your *startup* and *shutdown* is connected, you might want to start something and then finish it, acquire a resource and then release it, etc.
 
@@ -146,7 +146,7 @@ Doing that in separated functions that don't share logic or variables together i
 
 Because of that, it's now recommended to instead use the `lifespan` as explained above.
 
-## Technical Details
+## Technical Details { #technical-details }
 
 Just a technical detail for the curious nerds. 🤓
 
@@ -160,6 +160,6 @@ Including how to handle lifespan state that can be used in other areas of your c
 
 ///
 
-## Sub Applications
+## Sub Applications { #sub-applications }
 
 🚨 Keep in mind that these lifespan events (startup and shutdown) will only be executed for the main application, not for [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}.
index e8b2fefbd49c2fa7efb69bf0b7bbe2596cd9979a..897c308086cfa60bec671a87946109d9364a480e 100644 (file)
@@ -1,4 +1,4 @@
-# Generating SDKs
+# Generating SDKs { #generating-sdks }
 
 Because **FastAPI** is based on the **OpenAPI** specification, its APIs can be described in a standard format that many tools understand.
 
@@ -6,7 +6,7 @@ This makes it easy to generate up-to-date **documentation**, client libraries (<
 
 In this guide, you'll learn how to generate a **TypeScript SDK** for your FastAPI backend.
 
-## Open Source SDK Generators
+## Open Source SDK Generators { #open-source-sdk-generators }
 
 A versatile option is the <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>, which supports **many programming languages** and can generate SDKs from your OpenAPI specification.
 
@@ -20,7 +20,7 @@ FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you
 
 ///
 
-## SDK Generators from FastAPI Sponsors
+## SDK Generators from FastAPI Sponsors { #sdk-generators-from-fastapi-sponsors }
 
 This section highlights **venture-backed** and **company-supported** solutions from companies that sponsor FastAPI. These products provide **additional features** and **integrations** on top of high-quality generated SDKs.
 
@@ -36,7 +36,7 @@ For example, you might want to try:
 
 Some of these solutions may also be open source or offer free tiers, so you can try them without a financial commitment. Other commercial SDK generators are available and can be found online. 🤓
 
-## Create a TypeScript SDK
+## Create a TypeScript SDK { #create-a-typescript-sdk }
 
 Let's start with a simple FastAPI application:
 
@@ -44,7 +44,7 @@ Let's start with a simple FastAPI application:
 
 Notice that the *path operations* define the models they use for request payload and response payload, using the models `Item` and `ResponseMessage`.
 
-### API Docs
+### API Docs { #api-docs }
 
 If you go to `/docs`, you will see that it has the **schemas** for the data to be sent in requests and received in responses:
 
@@ -56,7 +56,7 @@ That information is available in the app's **OpenAPI schema**, and then shown in
 
 That same information from the models that is included in OpenAPI is what can be used to **generate the client code**.
 
-### Hey API
+### Hey API { #hey-api }
 
 Once we have a FastAPI app with the models, we can use Hey API to generate a TypeScript client. The fastest way to do that is via npx.
 
@@ -68,7 +68,7 @@ This will generate a TypeScript SDK in `./src/client`.
 
 You can learn how to <a href="https://heyapi.dev/openapi-ts/get-started" class="external-link" target="_blank">install `@hey-api/openapi-ts`</a> and read about the <a href="https://heyapi.dev/openapi-ts/output" class="external-link" target="_blank">generated output</a> on their website.
 
-### Using the SDK
+### Using the SDK { #using-the-sdk }
 
 Now you can import and use the client code. It could look like this, notice that you get autocompletion for the methods:
 
@@ -92,7 +92,7 @@ The response object will also have autocompletion:
 
 <img src="/img/tutorial/generate-clients/image05.png">
 
-## FastAPI App with Tags
+## FastAPI App with Tags { #fastapi-app-with-tags }
 
 In many cases, your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*.
 
@@ -100,7 +100,7 @@ For example, you could have a section for **items** and another section for **us
 
 {* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
 
-### Generate a TypeScript Client with Tags
+### Generate a TypeScript Client with Tags { #generate-a-typescript-client-with-tags }
 
 If you generate a client for a FastAPI app using tags, it will normally also separate the client code based on the tags.
 
@@ -113,7 +113,7 @@ In this case, you have:
 * `ItemsService`
 * `UsersService`
 
-### Client Method Names
+### Client Method Names { #client-method-names }
 
 Right now, the generated method names like `createItemItemsPost` don't look very clean:
 
@@ -127,7 +127,7 @@ OpenAPI requires that each operation ID is unique across all the *path operation
 
 But I'll show you how to improve that next. 🤓
 
-## Custom Operation IDs and Better Method Names
+## Custom Operation IDs and Better Method Names { #custom-operation-ids-and-better-method-names }
 
 You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients.
 
@@ -135,7 +135,7 @@ In this case, you will have to ensure that each operation ID is **unique** in so
 
 For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation* **name** (the function name).
 
-### Custom Generate Unique ID Function
+### Custom Generate Unique ID Function { #custom-generate-unique-id-function }
 
 FastAPI uses a **unique ID** for each *path operation*, which is used for the **operation ID** and also for the names of any needed custom models, for requests or responses.
 
@@ -147,7 +147,7 @@ You can then pass that custom function to **FastAPI** as the `generate_unique_id
 
 {* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
 
-### Generate a TypeScript Client with Custom Operation IDs
+### Generate a TypeScript Client with Custom Operation IDs { #generate-a-typescript-client-with-custom-operation-ids }
 
 Now, if you generate the client again, you will see that it has the improved method names:
 
@@ -155,7 +155,7 @@ Now, if you generate the client again, you will see that it has the improved met
 
 As you see, the method names now have the tag and then the function name, now they don't include information from the URL path and the HTTP operation.
 
-### Preprocess the OpenAPI Specification for the Client Generator
+### Preprocess the OpenAPI Specification for the Client Generator { #preprocess-the-openapi-specification-for-the-client-generator }
 
 The generated code still has some **duplicated information**.
 
@@ -179,7 +179,7 @@ We could download the OpenAPI JSON to a file `openapi.json` and then we could **
 
 With that, the operation IDs would be renamed from things like `items-get_items` to just `get_items`, that way the client generator can generate simpler method names.
 
-### Generate a TypeScript Client with the Preprocessed OpenAPI
+### Generate a TypeScript Client with the Preprocessed OpenAPI { #generate-a-typescript-client-with-the-preprocessed-openapi }
 
 Since the end result is now in an `openapi.json` file, you need to update your input location:
 
@@ -191,7 +191,7 @@ After generating the new client, you would now have **clean method names**, with
 
 <img src="/img/tutorial/generate-clients/image08.png">
 
-## Benefits
+## Benefits { #benefits }
 
 When using the automatically generated clients, you would get **autocompletion** for:
 
index 47385e2c6923f721e0b5c8214d491e6c9e3b7d34..9355516fb4fd4317197ac085e958081879cd6174 100644 (file)
@@ -1,6 +1,6 @@
-# Advanced User Guide
+# Advanced User Guide { #advanced-user-guide }
 
-## Additional Features
+## Additional Features { #additional-features }
 
 The main [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} should be enough to give you a tour through all the main features of **FastAPI**.
 
@@ -14,7 +14,7 @@ And it's possible that for your use case, the solution is in one of them.
 
 ///
 
-## Read the Tutorial first
+## Read the Tutorial first { #read-the-tutorial-first }
 
 You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank}.
 
index 1d40b1c8fc56804702c8a32dbd226158b3d1bbb1..4ca07676b1bdc86dddb1fa19571ac5b6a840882f 100644 (file)
@@ -1,4 +1,4 @@
-# Advanced Middleware
+# Advanced Middleware { #advanced-middleware }
 
 In the main tutorial you read how to add [Custom Middleware](../tutorial/middleware.md){.internal-link target=_blank} to your application.
 
@@ -6,7 +6,7 @@ And then you also read how to handle [CORS with the `CORSMiddleware`](../tutoria
 
 In this section we'll see how to use other middlewares.
 
-## Adding ASGI middlewares
+## Adding ASGI middlewares { #adding-asgi-middlewares }
 
 As **FastAPI** is based on Starlette and implements the <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr> specification, you can use any ASGI middleware.
 
@@ -39,7 +39,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
 
 `app.add_middleware()` receives a middleware class as the first argument and any additional arguments to be passed to the middleware.
 
-## Integrated middlewares
+## Integrated middlewares { #integrated-middlewares }
 
 **FastAPI** includes several middlewares for common use cases, we'll see next how to use them.
 
@@ -51,7 +51,7 @@ For the next examples, you could also use `from starlette.middleware.something i
 
 ///
 
-## `HTTPSRedirectMiddleware`
+## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware }
 
 Enforces that all incoming requests must either be `https` or `wss`.
 
@@ -59,7 +59,7 @@ Any incoming request to `http` or `ws` will be redirected to the secure scheme i
 
 {* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
 
-## `TrustedHostMiddleware`
+## `TrustedHostMiddleware` { #trustedhostmiddleware }
 
 Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks.
 
@@ -71,7 +71,7 @@ The following arguments are supported:
 
 If an incoming request does not validate correctly then a `400` response will be sent.
 
-## `GZipMiddleware`
+## `GZipMiddleware` { #gzipmiddleware }
 
 Handles GZip responses for any request that includes `"gzip"` in the `Accept-Encoding` header.
 
@@ -84,7 +84,7 @@ The following arguments are supported:
 * `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`.
 * `compresslevel` - Used during GZip compression. It is an integer ranging from 1 to 9. Defaults to `9`. Lower value results in faster compression but larger file sizes, while higher value results in slower compression but smaller file sizes.
 
-## Other middlewares
+## Other middlewares { #other-middlewares }
 
 There are many other ASGI middlewares.
 
index ca9065a896d2d338e43d01887798322805b2d1c4..059d893c26cf5cd147d52af28b8fa352a6032eaf 100644 (file)
@@ -1,4 +1,4 @@
-# OpenAPI Callbacks
+# OpenAPI Callbacks { #openapi-callbacks }
 
 You could create an API with a *path operation* that could trigger a request to an *external API* created by someone else (probably the same developer that would be *using* your API).
 
@@ -6,7 +6,7 @@ The process that happens when your API app calls the *external API* is named a "
 
 In this case, you could want to document how that external API *should* look like. What *path operation* it should have, what body it should expect, what response it should return, etc.
 
-## An app with callbacks
+## An app with callbacks { #an-app-with-callbacks }
 
 Let's see all this with an example.
 
@@ -23,7 +23,7 @@ Then your API will (let's imagine):
 * Send a notification back to the API user (the external developer).
     * This will be done by sending a POST request (from *your API*) to some *external API* provided by that external developer (this is the "callback").
 
-## The normal **FastAPI** app
+## The normal **FastAPI** app { #the-normal-fastapi-app }
 
 Let's first see how the normal API app would look like before adding the callback.
 
@@ -41,7 +41,7 @@ The `callback_url` query parameter uses a Pydantic <a href="https://docs.pydanti
 
 The only new thing is the `callbacks=invoices_callback_router.routes` as an argument to the *path operation decorator*. We'll see what that is next.
 
-## Documenting the callback
+## Documenting the callback { #documenting-the-callback }
 
 The actual callback code will depend heavily on your own API app.
 
@@ -70,7 +70,7 @@ When implementing the callback yourself, you could use something like <a href="h
 
 ///
 
-## Write the callback documentation code
+## Write the callback documentation code { #write-the-callback-documentation-code }
 
 This code won't be executed in your app, we only need it to *document* how that *external API* should look like.
 
@@ -86,13 +86,13 @@ Temporarily adopting this point of view (of the *external developer*) can help y
 
 ///
 
-### Create a callback `APIRouter`
+### Create a callback `APIRouter` { #create-a-callback-apirouter }
 
 First create a new `APIRouter` that will contain one or more callbacks.
 
 {* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
 
-### Create the callback *path operation*
+### Create the callback *path operation* { #create-the-callback-path-operation }
 
 To create the callback *path operation* use the same `APIRouter` you created above.
 
@@ -108,7 +108,7 @@ There are 2 main differences from a normal *path operation*:
 * It doesn't need to have any actual code, because your app will never call this code. It's only used to document the *external API*. So, the function could just have `pass`.
 * The *path* can contain an <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 expression</a> (see more below) where it can use variables with parameters and parts of the original request sent to *your API*.
 
-### The callback path expression
+### The callback path expression { #the-callback-path-expression }
 
 The callback *path* can have an <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 expression</a> that can contain parts of the original request sent to *your API*.
 
@@ -163,7 +163,7 @@ Notice how the callback URL used contains the URL received as a query parameter
 
 ///
 
-### Add the callback router
+### Add the callback router { #add-the-callback-router }
 
 At this point you have the *callback path operation(s)* needed (the one(s) that the *external developer*  should implement in the *external API*) in the callback router you created above.
 
@@ -177,7 +177,7 @@ Notice that you are not passing the router itself (`invoices_callback_router`) t
 
 ///
 
-### Check the docs
+### Check the docs { #check-the-docs }
 
 Now you can start your app and go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
index 97aaa41af96f69e74f46f6b716e27a9071f8ebbd..416cf4b75b97ba947bd2ff710449f9ef0770ead6 100644 (file)
@@ -1,4 +1,4 @@
-# OpenAPI Webhooks
+# OpenAPI Webhooks { #openapi-webhooks }
 
 There are cases where you want to tell your API **users** that your app could call *their* app (sending a request) with some data, normally to **notify** of some type of **event**.
 
@@ -6,7 +6,7 @@ This means that instead of the normal process of your users sending requests to
 
 This is normally called a **webhook**.
 
-## Webhooks steps
+## Webhooks steps { #webhooks-steps }
 
 The process normally is that **you define** in your code what is the message that you will send, the **body of the request**.
 
@@ -16,7 +16,7 @@ And **your users** define in some way (for example in a web dashboard somewhere)
 
 All the **logic** about how to register the URLs for webhooks and the code to actually send those requests is up to you. You write it however you want to in **your own code**.
 
-## Documenting webhooks with **FastAPI** and OpenAPI
+## Documenting webhooks with **FastAPI** and OpenAPI { #documenting-webhooks-with-fastapi-and-openapi }
 
 With **FastAPI**, using OpenAPI, you can define the names of these webhooks, the types of HTTP operations that your app can send (e.g. `POST`, `PUT`, etc.) and the request **bodies** that your app would send.
 
@@ -28,7 +28,7 @@ Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0`
 
 ///
 
-## An app with webhooks
+## An app with webhooks { #an-app-with-webhooks }
 
 When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`.
 
@@ -46,7 +46,7 @@ Notice that with webhooks you are actually not declaring a *path* (like `/items/
 
 This is because it is expected that **your users** would define the actual **URL path** where they want to receive the webhook request in some other way (e.g. a web dashboard).
 
-### Check the docs
+### Check the docs { #check-the-docs }
 
 Now you can start your app and go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
index c4814ebd2f368415321ed4f04bfdaa263695f5f2..b9961f9f384f52932e4b220cf6fcdd153cea8b37 100644 (file)
@@ -1,6 +1,6 @@
-# Path Operation Advanced Configuration
+# Path Operation Advanced Configuration { #path-operation-advanced-configuration }
 
-## OpenAPI operationId
+## OpenAPI operationId { #openapi-operationid }
 
 /// warning
 
@@ -14,7 +14,7 @@ You would have to make sure that it is unique for each operation.
 
 {* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
 
-### Using the *path operation function* name as the operationId
+### Using the *path operation function* name as the operationId { #using-the-path-operation-function-name-as-the-operationid }
 
 If you want to use your APIs' function names as `operationId`s, you can iterate over all of them and override each *path operation's* `operation_id` using their `APIRoute.name`.
 
@@ -36,13 +36,13 @@ Even if they are in different modules (Python files).
 
 ///
 
-## Exclude from OpenAPI
+## Exclude from OpenAPI { #exclude-from-openapi }
 
 To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`:
 
 {* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
 
-## Advanced description from docstring
+## Advanced description from docstring { #advanced-description-from-docstring }
 
 You can limit the lines used from the docstring of a *path operation function* for OpenAPI.
 
@@ -52,7 +52,7 @@ It won't show up in the documentation, but other tools (such as Sphinx) will be
 
 {* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
 
-## Additional Responses
+## Additional Responses { #additional-responses }
 
 You probably have seen how to declare the `response_model` and `status_code` for a *path operation*.
 
@@ -62,7 +62,7 @@ You can also declare additional responses with their models, status codes, etc.
 
 There's a whole chapter here in the documentation about it, you can read it at [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
 
-## OpenAPI Extra
+## OpenAPI Extra { #openapi-extra }
 
 When you declare a *path operation* in your application, **FastAPI** automatically generates the relevant metadata about that *path operation* to be included in the OpenAPI schema.
 
@@ -88,7 +88,7 @@ If you only need to declare additional responses, a more convenient way to do it
 
 You can extend the OpenAPI schema for a *path operation* using the parameter `openapi_extra`.
 
-### OpenAPI Extensions
+### OpenAPI Extensions { #openapi-extensions }
 
 This `openapi_extra` can be helpful, for example, to declare [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
 
@@ -129,7 +129,7 @@ And if you see the resulting OpenAPI (at `/openapi.json` in your API), you will
 }
 ```
 
-### Custom OpenAPI *path operation* schema
+### Custom OpenAPI *path operation* schema { #custom-openapi-path-operation-schema }
 
 The dictionary in `openapi_extra` will be deeply merged with the automatically generated OpenAPI schema for the *path operation*.
 
@@ -145,7 +145,7 @@ In this example, we didn't declare any Pydantic model. In fact, the request body
 
 Nevertheless, we can declare the expected schema for the request body.
 
-### Custom OpenAPI content type
+### Custom OpenAPI content type { #custom-openapi-content-type }
 
 Using this same trick, you could use a Pydantic model to define the JSON Schema that is then included in the custom OpenAPI schema section for the *path operation*.
 
index 6d3f9f3e8674d79a4cd96d9848ce7e635f931811..912ed0f1a15987194fe2d01a77f9364f494cdceb 100644 (file)
@@ -1,10 +1,10 @@
-# Response - Change Status Code
+# Response - Change Status Code { #response-change-status-code }
 
 You probably read before that you can set a default [Response Status Code](../tutorial/response-status-code.md){.internal-link target=_blank}.
 
 But in some cases you need to return a different status code than the default.
 
-## Use case
+## Use case { #use-case }
 
 For example, imagine that you want to return an HTTP status code of "OK" `200` by default.
 
@@ -14,7 +14,7 @@ But you still want to be able to filter and convert the data you return with a `
 
 For those cases, you can use a `Response` parameter.
 
-## Use a `Response` parameter
+## Use a `Response` parameter { #use-a-response-parameter }
 
 You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies and headers).
 
index f6d17f35d6e055e3b89ef8fdf60d45ba9bf9af4c..d8f77b56ad3b045515eb28e75b72eec0cc8cc372 100644 (file)
@@ -1,6 +1,6 @@
-# Response Cookies
+# Response Cookies { #response-cookies }
 
-## Use a `Response` parameter
+## Use a `Response` parameter { #use-a-response-parameter }
 
 You can declare a parameter of type `Response` in your *path operation function*.
 
@@ -16,7 +16,7 @@ And if you declared a `response_model`, it will still be used to filter and conv
 
 You can also declare the `Response` parameter in dependencies, and set cookies (and headers) in them.
 
-## Return a `Response` directly
+## Return a `Response` directly { #return-a-response-directly }
 
 You can also create cookies when returning a `Response` directly in your code.
 
@@ -36,7 +36,7 @@ And also that you are not sending any data that should have been filtered by a `
 
 ///
 
-### More info
+### More info { #more-info }
 
 /// note | Technical Details
 
index 759b762b5d1b5c4eebb4b6ad5286546d908715c5..3197e1bd4680b46b3d1791cea1715c4c15d308b5 100644 (file)
@@ -1,4 +1,4 @@
-# Return a Response Directly
+# Return a Response Directly { #return-a-response-directly }
 
 When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc.
 
@@ -10,7 +10,7 @@ But you can return a `JSONResponse` directly from your *path operations*.
 
 It might be useful, for example, to return custom headers or cookies.
 
-## Return a `Response`
+## Return a `Response` { #return-a-response }
 
 In fact, you can return any `Response` or any sub-class of it.
 
@@ -26,7 +26,7 @@ It won't do any data conversion with Pydantic models, it won't convert the conte
 
 This gives you a lot of flexibility. You can return any data type, override any data declaration or validation, etc.
 
-## Using the `jsonable_encoder` in a `Response`
+## Using the `jsonable_encoder` in a `Response` { #using-the-jsonable-encoder-in-a-response }
 
 Because **FastAPI** doesn't make any changes to a `Response` you return, you have to make sure its contents are ready for it.
 
@@ -44,7 +44,7 @@ You could also use `from starlette.responses import JSONResponse`.
 
 ///
 
-## Returning a custom `Response`
+## Returning a custom `Response` { #returning-a-custom-response }
 
 The example above shows all the parts you need, but it's not very useful yet, as you could have just returned the `item` directly, and **FastAPI** would put it in a `JSONResponse` for you, converting it to a `dict`, etc. All that by default.
 
@@ -56,7 +56,7 @@ You could put your XML content in a string, put that in a `Response`, and return
 
 {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
 
-## Notes
+## Notes { #notes }
 
 When you return a `Response` directly its data is not validated, converted (serialized), or documented automatically.
 
index 97e888983b4c314d952de244638fea7ef1a68c6d..98747eabdadfc7e7fa039f2b7b933546df3c9ded 100644 (file)
@@ -1,6 +1,6 @@
-# Response Headers
+# Response Headers { #response-headers }
 
-## Use a `Response` parameter
+## Use a `Response` parameter { #use-a-response-parameter }
 
 You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies).
 
@@ -16,7 +16,7 @@ And if you declared a `response_model`, it will still be used to filter and conv
 
 You can also declare the `Response` parameter in dependencies, and set headers (and cookies) in them.
 
-## Return a `Response` directly
+## Return a `Response` directly { #return-a-response-directly }
 
 You can also add headers when you return a `Response` directly.
 
@@ -34,7 +34,7 @@ And as the `Response` can be used frequently to set headers and cookies, **FastA
 
 ///
 
-## Custom Headers
+## Custom Headers { #custom-headers }
 
 Keep in mind that custom proprietary headers can be added <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">using the 'X-' prefix</a>.
 
index 234e2f940b65bb99ad93fd358a75104ba4a2728e..01b98eeff3d0abdce3ecbe90cbf8bb85a1f38714 100644 (file)
@@ -1,4 +1,4 @@
-# HTTP Basic Auth
+# HTTP Basic Auth { #http-basic-auth }
 
 For the simplest cases, you can use HTTP Basic Auth.
 
@@ -12,7 +12,7 @@ That tells the browser to show the integrated prompt for a username and password
 
 Then, when you type that username and password, the browser sends them in the header automatically.
 
-## Simple HTTP Basic Auth
+## Simple HTTP Basic Auth { #simple-http-basic-auth }
 
 * Import `HTTPBasic` and `HTTPBasicCredentials`.
 * Create a "`security` scheme" using `HTTPBasic`.
@@ -26,7 +26,7 @@ When you try to open the URL for the first time (or click the "Execute" button i
 
 <img src="/img/tutorial/security/image12.png">
 
-## Check the username
+## Check the username { #check-the-username }
 
 Here's a more complete example.
 
@@ -52,7 +52,7 @@ if not (credentials.username == "stanleyjobson") or not (credentials.password ==
 
 But by using the `secrets.compare_digest()` it will be secure against a type of attacks called "timing attacks".
 
-### Timing Attacks
+### Timing Attacks { #timing-attacks }
 
 But what's a "timing attack"?
 
@@ -80,19 +80,19 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
 
 Python will have to compare the whole `stanleyjobso` in both `stanleyjobsox` and `stanleyjobson` before realizing that both strings are not the same. So it will take some extra microseconds to reply back "Incorrect username or password".
 
-#### The time to answer helps the attackers
+#### The time to answer helps the attackers { #the-time-to-answer-helps-the-attackers }
 
 At that point, by noticing that the server took some microseconds longer to send the "Incorrect username or password" response, the attackers will know that they got _something_ right, some of the initial letters were right.
 
 And then they can try again knowing that it's probably something more similar to `stanleyjobsox` than to `johndoe`.
 
-#### A "professional" attack
+#### A "professional" attack { #a-professional-attack }
 
 Of course, the attackers would not try all this by hand, they would write a program to do it, possibly with thousands or millions of tests per second. And they would get just one extra correct letter at a time.
 
 But doing that, in some minutes or hours the attackers would have guessed the correct username and password, with the "help" of our application, just using the time taken to answer.
 
-#### Fix it with `secrets.compare_digest()`
+#### Fix it with `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest }
 
 But in our code we are actually using `secrets.compare_digest()`.
 
@@ -100,7 +100,7 @@ In short, it will take the same time to compare `stanleyjobsox` to `stanleyjobso
 
 That way, using `secrets.compare_digest()` in your application code, it will be safe against this whole range of security attacks.
 
-### Return the error
+### Return the error { #return-the-error }
 
 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:
 
index edb42132e6b74e803a5119b22e450997907922f0..996d716b4c47fc5d8aeec2bcefe544e5d7fda5ac 100644 (file)
@@ -1,6 +1,6 @@
-# Advanced Security
+# Advanced Security { #advanced-security }
 
-## Additional Features
+## Additional Features { #additional-features }
 
 There are some extra features to handle security apart from the ones covered in the [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank}.
 
@@ -12,7 +12,7 @@ And it's possible that for your use case, the solution is in one of them.
 
 ///
 
-## Read the Tutorial first
+## Read the Tutorial first { #read-the-tutorial-first }
 
 The next sections assume you already read the main [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank}.
 
index 4cb0b39bc6ab5db2182944b2bdcbd52b4c809beb..0a84435e6dfa488e2eef73e3e9a064bf28bee86f 100644 (file)
@@ -1,4 +1,4 @@
-# OAuth2 scopes
+# OAuth2 scopes { #oauth2-scopes }
 
 You can use OAuth2 scopes directly with **FastAPI**, they are integrated to work seamlessly.
 
@@ -26,7 +26,7 @@ But if you know you need it, or you are curious, keep reading.
 
 ///
 
-## OAuth2 scopes and OpenAPI
+## OAuth2 scopes and OpenAPI { #oauth2-scopes-and-openapi }
 
 The OAuth2 specification defines "scopes" as a list of strings separated by spaces.
 
@@ -58,7 +58,7 @@ For OAuth2 they are just strings.
 
 ///
 
-## Global view
+## Global view { #global-view }
 
 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:
 
@@ -66,7 +66,7 @@ First, let's quickly see the parts that change from the examples in the main **T
 
 Now let's review those changes step by step.
 
-## OAuth2 Security scheme
+## OAuth2 Security scheme { #oauth2-security-scheme }
 
 The first change is that now we are declaring the OAuth2 security scheme with two available scopes, `me` and `items`.
 
@@ -82,7 +82,7 @@ This is the same mechanism used when you give permissions while logging in with
 
 <img src="/img/tutorial/security/image11.png">
 
-## JWT token with scopes
+## JWT token with scopes { #jwt-token-with-scopes }
 
 Now, modify the token *path operation* to return the scopes requested.
 
@@ -100,7 +100,7 @@ But in your application, for security, you should make sure you only add the sco
 
 {* ../../docs_src/security/tutorial005_an_py310.py hl[156] *}
 
-## Declare scopes in *path operations* and dependencies
+## Declare scopes in *path operations* and dependencies { #declare-scopes-in-path-operations-and-dependencies }
 
 Now we declare that the *path operation* for `/users/me/items/` requires the scope `items`.
 
@@ -136,7 +136,7 @@ But when you import `Query`, `Path`, `Depends`, `Security` and others from `fast
 
 ///
 
-## Use `SecurityScopes`
+## Use `SecurityScopes` { #use-securityscopes }
 
 Now update the dependency `get_current_user`.
 
@@ -152,7 +152,7 @@ This `SecurityScopes` class is similar to `Request` (`Request` was used to get t
 
 {* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *}
 
-## Use the `scopes`
+## Use the `scopes` { #use-the-scopes }
 
 The parameter `security_scopes` will be of type `SecurityScopes`.
 
@@ -166,7 +166,7 @@ In this exception, we include the scopes required (if any) as a string separated
 
 {* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *}
 
-## Verify the `username` and data shape
+## Verify the `username` and data shape { #verify-the-username-and-data-shape }
 
 We verify that we get a `username`, and extract the scopes.
 
@@ -182,7 +182,7 @@ We also verify that we have a user with that username, and if not, we raise that
 
 {* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:128] *}
 
-## Verify the `scopes`
+## Verify the `scopes` { #verify-the-scopes }
 
 We now verify that all the scopes required, by this dependency and all the dependants (including *path operations*), are included in the scopes provided in the token received, otherwise raise an `HTTPException`.
 
@@ -190,7 +190,7 @@ For this, we use `security_scopes.scopes`, that contains a `list` with all these
 
 {* ../../docs_src/security/tutorial005_an_py310.py hl[129:135] *}
 
-## Dependency tree and scopes
+## Dependency tree and scopes { #dependency-tree-and-scopes }
 
 Let's review again this dependency tree and the scopes.
 
@@ -223,7 +223,7 @@ All depending on the `scopes` declared in each *path operation* and each depende
 
 ///
 
-## More details about `SecurityScopes`
+## More details about `SecurityScopes` { #more-details-about-securityscopes }
 
 You can use `SecurityScopes` at any point, and in multiple places, it doesn't have to be at the "root" dependency.
 
@@ -233,7 +233,7 @@ Because the `SecurityScopes` will have all the scopes declared by dependants, yo
 
 They will be checked independently for each *path operation*.
 
-## Check it
+## Check it { #check-it }
 
 If you open the API docs, you can authenticate and specify which scopes you want to authorize.
 
@@ -245,7 +245,7 @@ And if you select the scope `me` but not the scope `items`, you will be able to
 
 That's what would happen to a third party application that tried to access one of these *path operations* with a token provided by a user, depending on how many permissions the user gave the application.
 
-## About third party integrations
+## About third party integrations { #about-third-party-integrations }
 
 In this example we are using the OAuth2 "password" flow.
 
@@ -269,6 +269,6 @@ But in the end, they are implementing the same OAuth2 standard.
 
 **FastAPI** includes utilities for all these OAuth2 authentication flows in `fastapi.security.oauth2`.
 
-## `Security` in decorator `dependencies`
+## `Security` in decorator `dependencies` { #security-in-decorator-dependencies }
 
 The same way you can define a `list` of `Depends` in the decorator's `dependencies` parameter (as explained in [Dependencies in path operation decorators](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), you could also use `Security` with `scopes` there.
index 1af19a0454da7289c835db9fd0e03418738f88e4..a218c3d0167006682d83f3f975c0299921314674 100644 (file)
@@ -1,4 +1,4 @@
-# Settings and Environment Variables
+# Settings and Environment Variables { #settings-and-environment-variables }
 
 In many cases your application could need some external settings or configurations, for example secret keys, database credentials, credentials for email services, etc.
 
@@ -12,17 +12,17 @@ To understand environment variables you can read [Environment Variables](../envi
 
 ///
 
-## Types and validation
+## Types and validation { #types-and-validation }
 
 These environment variables can only handle text strings, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, as Linux, Windows, macOS).
 
 That means that any value read in Python from an environment variable will be a `str`, and any conversion to a different type or any validation has to be done in code.
 
-## Pydantic `Settings`
+## Pydantic `Settings` { #pydantic-settings }
 
 Fortunately, Pydantic provides a great utility to handle these settings coming from environment variables with <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a>.
 
-### Install `pydantic-settings`
+### Install `pydantic-settings` { #install-pydantic-settings }
 
 First, make sure you create your [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and then install the `pydantic-settings` package:
 
@@ -52,7 +52,7 @@ In Pydantic v1 it came included with the main package. Now it is distributed as
 
 ///
 
-### Create the `Settings` object
+### Create the `Settings` object { #create-the-settings-object }
 
 Import `BaseSettings` from Pydantic and create a sub-class, very much like with a Pydantic model.
 
@@ -88,13 +88,13 @@ Then, when you create an instance of that `Settings` class (in this case, in the
 
 Next it will convert and validate the data. So, when you use that `settings` object, you will have data of the types you declared (e.g. `items_per_user` will be an `int`).
 
-### Use the `settings`
+### Use the `settings` { #use-the-settings }
 
 Then you can use the new `settings` object in your application:
 
 {* ../../docs_src/settings/tutorial001.py hl[18:20] *}
 
-### Run the server
+### Run the server { #run-the-server }
 
 Next, you would run the server passing the configurations as environment variables, for example you could set an `ADMIN_EMAIL` and `APP_NAME` with:
 
@@ -120,7 +120,7 @@ The `app_name` would be `"ChimichangApp"`.
 
 And the `items_per_user` would keep its default value of `50`.
 
-## Settings in another module
+## Settings in another module { #settings-in-another-module }
 
 You could put those settings in another module file as you saw in [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}.
 
@@ -138,13 +138,13 @@ You would also need a file `__init__.py` as you saw in [Bigger Applications - Mu
 
 ///
 
-## Settings in a dependency
+## Settings in a dependency { #settings-in-a-dependency }
 
 In some occasions it might be useful to provide the settings from a dependency, instead of having a global object with `settings` that is used everywhere.
 
 This could be especially useful during testing, as it's very easy to override a dependency with your own custom settings.
 
-### The config file
+### The config file { #the-config-file }
 
 Coming from the previous example, your `config.py` file could look like:
 
@@ -152,7 +152,7 @@ Coming from the previous example, your `config.py` file could look like:
 
 Notice that now we don't create a default instance `settings = Settings()`.
 
-### The main app file
+### The main app file { #the-main-app-file }
 
 Now we create a dependency that returns a new `config.Settings()`.
 
@@ -170,7 +170,7 @@ And then we can require it from the *path operation function* as a dependency an
 
 {* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
 
-### Settings and testing
+### Settings and testing { #settings-and-testing }
 
 Then it would be very easy to provide a different settings object during testing by creating a dependency override for `get_settings`:
 
@@ -180,7 +180,7 @@ In the dependency override we set a new value for the `admin_email` when creatin
 
 Then we can test that it is used.
 
-## Reading a `.env` file
+## Reading a `.env` file { #reading-a-env-file }
 
 If you have many settings that possibly change a lot, maybe in different environments, it might be useful to put them on a file and then read them from it as if they were environment variables.
 
@@ -202,7 +202,7 @@ For this to work, you need to `pip install python-dotenv`.
 
 ///
 
-### The `.env` file
+### The `.env` file { #the-env-file }
 
 You could have a `.env` file with:
 
@@ -211,7 +211,7 @@ ADMIN_EMAIL="deadpool@example.com"
 APP_NAME="ChimichangApp"
 ```
 
-### Read settings from `.env`
+### Read settings from `.env` { #read-settings-from-env }
 
 And then update your `config.py` with:
 
@@ -247,7 +247,7 @@ In Pydantic version 1 the configuration was done in an internal class `Config`,
 
 Here we define the config `env_file` inside of your Pydantic `Settings` class, and set the value to the filename with the dotenv file we want to use.
 
-### Creating the `Settings` only once with `lru_cache`
+### Creating the `Settings` only once with `lru_cache` { #creating-the-settings-only-once-with-lru-cache }
 
 Reading a file from disk is normally a costly (slow) operation, so you probably want to do it only once and then reuse the same settings object, instead of reading it for each request.
 
@@ -274,7 +274,7 @@ But as we are using the `@lru_cache` decorator on top, the `Settings` object wil
 
 Then for any subsequent call of `get_settings()` in the dependencies for the next requests, instead of executing the internal code of `get_settings()` and creating a new `Settings` object, it will return the same object that was returned on the first call, again and again.
 
-#### `lru_cache` Technical Details
+#### `lru_cache` Technical Details { #lru-cache-technical-details }
 
 `@lru_cache` modifies the function it decorates to return the same value that was returned the first time, instead of computing it again, executing the code of the function every time.
 
@@ -337,7 +337,7 @@ That way, it behaves almost as if it was just a global variable. But as it uses
 
 `@lru_cache` is part of `functools` which is part of Python's standard library, you can read more about it in the <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python docs for `@lru_cache`</a>.
 
-## Recap
+## Recap { #recap }
 
 You can use Pydantic Settings to handle the settings or configurations for your application, with all the power of Pydantic models.
 
index 48e329fc13d35a20b130782556235d181c1f1bb2..fbd0e1af3922fa0bc409e09848e46c4d65037ecc 100644 (file)
@@ -1,18 +1,18 @@
-# Sub Applications - Mounts
+# Sub Applications - Mounts { #sub-applications-mounts }
 
 If you need to have two independent FastAPI applications, with their own independent OpenAPI and their own docs UIs, you can have a main app and "mount" one (or more) sub-application(s).
 
-## Mounting a **FastAPI** application
+## Mounting a **FastAPI** application { #mounting-a-fastapi-application }
 
 "Mounting" means adding a completely "independent" application in a specific path, that then takes care of handling everything under that path, with the _path operations_ declared in that sub-application.
 
-### Top-level application
+### Top-level application { #top-level-application }
 
 First, create the main, top-level, **FastAPI** application, and its *path operations*:
 
 {* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *}
 
-### Sub-application
+### Sub-application { #sub-application }
 
 Then, create your sub-application, and its *path operations*.
 
@@ -20,7 +20,7 @@ This sub-application is just another standard FastAPI application, but this is t
 
 {* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *}
 
-### Mount the sub-application
+### Mount the sub-application { #mount-the-sub-application }
 
 In your top-level application, `app`, mount the sub-application, `subapi`.
 
@@ -28,7 +28,7 @@ In this case, it will be mounted at the path `/subapi`:
 
 {* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *}
 
-### Check the automatic API docs
+### Check the automatic API docs { #check-the-automatic-api-docs }
 
 Now, run the `fastapi` command with your file:
 
@@ -56,7 +56,7 @@ You will see the automatic API docs for the sub-application, including only its
 
 If you try interacting with any of the two user interfaces, they will work correctly, because the browser will be able to talk to each specific app or sub-app.
 
-### Technical Details: `root_path`
+### Technical Details: `root_path` { #technical-details-root-path }
 
 When you mount a sub-application as described above, FastAPI will take care of communicating the mount path for the sub-application using a mechanism from the ASGI specification called a `root_path`.
 
index d9b0ca6f14fc4b1f8ddd7c931dd130ae6535b417..f41c47fe834a22d684dd12d71a7b11e4963c5ad9 100644 (file)
@@ -1,4 +1,4 @@
-# Templates
+# Templates { #templates }
 
 You can use any template engine you want with **FastAPI**.
 
@@ -6,7 +6,7 @@ A common choice is Jinja2, the same one used by Flask and other tools.
 
 There are utilities to configure it easily that you can use directly in your **FastAPI** application (provided by Starlette).
 
-## Install dependencies
+## Install dependencies { #install-dependencies }
 
 Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `jinja2`:
 
@@ -20,7 +20,7 @@ $ pip install jinja2
 
 </div>
 
-## Using `Jinja2Templates`
+## Using `Jinja2Templates` { #using-jinja2templates }
 
 * Import `Jinja2Templates`.
 * Create a `templates` object that you can reuse later.
@@ -51,7 +51,7 @@ You could also use `from starlette.templating import Jinja2Templates`.
 
 ///
 
-## Writing templates
+## Writing templates { #writing-templates }
 
 Then you can write a template at `templates/item.html` with, for example:
 
@@ -59,7 +59,7 @@ Then you can write a template at `templates/item.html` with, for example:
 {!../../docs_src/templates/templates/item.html!}
 ```
 
-### Template Context Values
+### Template Context Values { #template-context-values }
 
 In the HTML that contains:
 
@@ -83,7 +83,7 @@ For example, with an ID of `42`, this would render:
 Item ID: 42
 ```
 
-### Template `url_for` Arguments
+### Template `url_for` Arguments { #template-url-for-arguments }
 
 You can also use `url_for()` inside of the template, it takes as arguments the same arguments that would be used by your *path operation function*.
 
@@ -105,7 +105,7 @@ For example, with an ID of `42`, this would render:
 <a href="/items/42">
 ```
 
-## Templates and static files
+## Templates and static files { #templates-and-static-files }
 
 You can also use `url_for()` inside of the template, and use it, for example, with the `StaticFiles` you mounted with the `name="static"`.
 
@@ -121,6 +121,6 @@ In this example, it would link to a CSS file at `static/styles.css` with:
 
 And because you are using `StaticFiles`, that CSS file would be served automatically by your **FastAPI** application at the URL `/static/styles.css`.
 
-## More details
+## More details { #more-details }
 
 For more details, including how to test templates, check <a href="https://www.starlette.io/templates/" class="external-link" target="_blank">Starlette's docs on templates</a>.
index 17b4f981456596c4f2d70ac0cfaeb59891d06d02..b52b47c969df80eabeeae3569da9708833757611 100644 (file)
@@ -1,6 +1,6 @@
-# Testing Dependencies with Overrides
+# Testing Dependencies with Overrides { #testing-dependencies-with-overrides }
 
-## Overriding dependencies during testing
+## Overriding dependencies during testing { #overriding-dependencies-during-testing }
 
 There are some scenarios where you might want to override a dependency during testing.
 
@@ -8,7 +8,7 @@ You don't want the original dependency to run (nor any of the sub-dependencies i
 
 Instead, you want to provide a different dependency that will be used only during tests (possibly only some specific tests), and will provide a value that can be used where the value of the original dependency was used.
 
-### Use cases: external service
+### Use cases: external service { #use-cases-external-service }
 
 An example could be that you have an external authentication provider that you need to call.
 
@@ -20,7 +20,7 @@ You probably want to test the external provider once, but not necessarily call i
 
 In this case, you can override the dependency that calls that provider, and use a custom dependency that returns a mock user, only for your tests.
 
-### Use the `app.dependency_overrides` attribute
+### Use the `app.dependency_overrides` attribute { #use-the-app-dependency-overrides-attribute }
 
 For these cases, your **FastAPI** application has an attribute `app.dependency_overrides`, it is a simple `dict`.
 
index 0c554c4ece5e2ea90c0b366c5c9ec35f0c0630c6..d0f2d1a79f4f8b65b50f8dccc7bc1d69372fadd0 100644 (file)
@@ -1,4 +1,4 @@
-# Testing Events: startup - shutdown
+# Testing Events: startup - shutdown { #testing-events-startup-shutdown }
 
 When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement:
 
index 60dfdc3432cb9ff1b164d06ea80772c1cd0889ec..22f9bb4a02258dcf916a2dddc3f6e7ca347610fb 100644 (file)
@@ -1,4 +1,4 @@
-# Testing WebSockets
+# Testing WebSockets { #testing-websockets }
 
 You can use the same `TestClient` to test WebSockets.
 
index 2f88c8f2062e4aebe978f0b80a2918f6ff1e3758..e412ad462440cceb7675574da7c1b72a8d4a6f21 100644 (file)
@@ -1,4 +1,4 @@
-# Using the Request Directly
+# Using the Request Directly { #using-the-request-directly }
 
 Up to now, you have been declaring the parts of the request that you need with their types.
 
@@ -13,7 +13,7 @@ And by doing so, **FastAPI** is validating that data, converting it and generati
 
 But there are situations where you might need to access the `Request` object directly.
 
-## Details about the `Request` object
+## Details about the `Request` object { #details-about-the-request-object }
 
 As **FastAPI** is actually **Starlette** underneath, with a layer of several tools on top, you can use Starlette's <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request`</a> object directly when you need to.
 
@@ -23,7 +23,7 @@ Although any other parameter declared normally (for example, the body with a Pyd
 
 But there are specific cases where it's useful to get the `Request` object.
 
-## Use the `Request` object directly
+## Use the `Request` object directly { #use-the-request-object-directly }
 
 Let's imagine you want to get the client's IP address/host inside of your *path operation function*.
 
@@ -43,7 +43,7 @@ The same way, you can declare any other parameter as normally, and additionally,
 
 ///
 
-## `Request` documentation
+## `Request` documentation { #request-documentation }
 
 You can read more details about the <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request` object in the official Starlette documentation site</a>.
 
index ee8e901dfbc19bb970dd3f7443cc1f2855d83d93..4ba24637fbef8b30975952603a7900faa597c617 100644 (file)
@@ -1,8 +1,8 @@
-# WebSockets
+# WebSockets { #websockets }
 
 You can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" class="external-link" target="_blank">WebSockets</a> with **FastAPI**.
 
-## Install `WebSockets`
+## Install `WebSockets` { #install-websockets }
 
 Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `websockets`:
 
@@ -16,9 +16,9 @@ $ pip install websockets
 
 </div>
 
-## WebSockets client
+## WebSockets client { #websockets-client }
 
-### In production
+### In production { #in-production }
 
 In your production system, you probably have a frontend created with a modern framework like React, Vue.js or Angular.
 
@@ -40,7 +40,7 @@ But it's the simplest way to focus on the server-side of WebSockets and have a w
 
 {* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *}
 
-## Create a `websocket`
+## Create a `websocket` { #create-a-websocket }
 
 In your **FastAPI** application, create a `websocket`:
 
@@ -54,7 +54,7 @@ You could also use `from starlette.websockets import WebSocket`.
 
 ///
 
-## Await for messages and send messages
+## Await for messages and send messages { #await-for-messages-and-send-messages }
 
 In your WebSocket route you can `await` for messages and send messages.
 
@@ -62,7 +62,7 @@ In your WebSocket route you can `await` for messages and send messages.
 
 You can receive and send binary, text, and JSON data.
 
-## Try it
+## Try it { #try-it }
 
 If your file is named `main.py`, run your application with:
 
@@ -96,7 +96,7 @@ You can send (and receive) many messages:
 
 And all of them will use the same WebSocket connection.
 
-## Using `Depends` and others
+## Using `Depends` and others { #using-depends-and-others }
 
 In WebSocket endpoints you can import from `fastapi` and use:
 
@@ -119,7 +119,7 @@ You can use a closing code from the <a href="https://tools.ietf.org/html/rfc6455
 
 ///
 
-### Try the WebSockets with dependencies
+### Try the WebSockets with dependencies { #try-the-websockets-with-dependencies }
 
 If your file is named `main.py`, run your application with:
 
@@ -150,7 +150,7 @@ With that you can connect the WebSocket and then send and receive messages:
 
 <img src="/img/tutorial/websockets/image05.png">
 
-## Handling disconnections and multiple clients
+## Handling disconnections and multiple clients { #handling-disconnections-and-multiple-clients }
 
 When a WebSocket connection is closed, the `await websocket.receive_text()` will raise a `WebSocketDisconnect` exception, which you can then catch and handle like in this example.
 
@@ -178,7 +178,7 @@ If you need something easy to integrate with FastAPI but that is more robust, su
 
 ///
 
-## More info
+## More info { #more-info }
 
 To learn more about the options, check Starlette's documentation for:
 
index 296eb136475dfdeff30e2eb8995e38b3be931ed4..29fd2d359c8e2f27dbe224069f1c1069887acda3 100644 (file)
@@ -1,10 +1,10 @@
-# Including WSGI - Flask, Django, others
+# Including WSGI - Flask, Django, others { #including-wsgi-flask-django-others }
 
 You can mount WSGI applications as you saw with [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank}.
 
 For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc.
 
-## Using `WSGIMiddleware`
+## Using `WSGIMiddleware` { #using-wsgimiddleware }
 
 You need to import `WSGIMiddleware`.
 
@@ -14,7 +14,7 @@ And then mount that under a path.
 
 {* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *}
 
-## Check it
+## Check it { #check-it }
 
 Now, every request under the path `/v1/` will be handled by the Flask application.
 
index 326f0dbe1a718a4f9e5f2d7c0c1c69447016261c..f0576bc47c4ed8523180b4c05fb4fb0b5db3588d 100644 (file)
@@ -1,8 +1,8 @@
-# Alternatives, Inspiration and Comparisons
+# Alternatives, Inspiration and Comparisons { #alternatives-inspiration-and-comparisons }
 
 What inspired **FastAPI**, how it compares to alternatives and what it learned from them.
 
-## Intro
+## Intro { #intro }
 
 **FastAPI** wouldn't exist if not for the previous work of others.
 
@@ -12,9 +12,9 @@ I have been avoiding the creation of a new framework for several years. First I
 
 But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints).
 
-## Previous tools
+## Previous tools { #previous-tools }
 
-### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
+### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> { #django }
 
 It's the most popular Python framework and is widely trusted. It is used to build systems like Instagram.
 
@@ -22,7 +22,7 @@ It's relatively tightly coupled with relational databases (like MySQL or Postgre
 
 It was created to generate the HTML in the backend, not to create APIs used by a modern frontend (like React, Vue.js and Angular) or by other systems (like <abbr title="Internet of Things">IoT</abbr> devices) communicating with it.
 
-### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
+### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> { #django-rest-framework }
 
 Django REST framework was created to be a flexible toolkit for building Web APIs using Django underneath, to improve its API capabilities.
 
@@ -42,7 +42,7 @@ Have an automatic API documentation web user interface.
 
 ///
 
-### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
+### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> { #flask }
 
 Flask is a "microframework", it doesn't include database integrations nor many of the things that come by default in Django.
 
@@ -64,7 +64,7 @@ Have a simple and easy to use routing system.
 
 ///
 
-### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
+### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> { #requests }
 
 **FastAPI** is not actually an alternative to **Requests**. Their scope is very different.
 
@@ -106,7 +106,7 @@ See the similarities in `requests.get(...)` and `@app.get(...)`.
 
 ///
 
-### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
+### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a> { #swagger-openapi }
 
 The main feature I wanted from Django REST Framework was the automatic API documentation.
 
@@ -131,11 +131,11 @@ These two were chosen for being fairly popular and stable, but doing a quick sea
 
 ///
 
-### Flask REST frameworks
+### Flask REST frameworks { #flask-rest-frameworks }
 
 There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit.
 
-### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a>
+### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
 
 One of the main features needed by API systems is data "<abbr title="also called marshalling, conversion">serialization</abbr>" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
 
@@ -153,7 +153,7 @@ Use code to define "schemas" that provide data types and validation, automatical
 
 ///
 
-### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
+### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
 
 Another big feature required by APIs is <abbr title="reading and converting to Python data">parsing</abbr> data from incoming requests.
 
@@ -175,7 +175,7 @@ Have automatic validation of incoming request data.
 
 ///
 
-### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
+### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> { #apispec }
 
 Marshmallow and Webargs provide validation, parsing and serialization as plug-ins.
 
@@ -205,7 +205,7 @@ Support the open standard for APIs, OpenAPI.
 
 ///
 
-### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
+### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> { #flask-apispec }
 
 It's a Flask plug-in, that ties together Webargs, Marshmallow and APISpec.
 
@@ -237,7 +237,7 @@ Generate the OpenAPI schema automatically, from the same code that defines seria
 
 ///
 
-### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (and <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>)
+### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (and <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>) { #nestjs-and-angular }
 
 This isn't even Python, NestJS is a JavaScript (TypeScript) NodeJS framework inspired by Angular.
 
@@ -259,7 +259,7 @@ Have a powerful dependency injection system. Find a way to minimize code repetit
 
 ///
 
-### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
+### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> { #sanic }
 
 It was one of the first extremely fast Python frameworks based on `asyncio`. It was made to be very similar to Flask.
 
@@ -279,7 +279,7 @@ That's why **FastAPI** is based on Starlette, as it is the fastest framework ava
 
 ///
 
-### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
+### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> { #falcon }
 
 Falcon is another high performance Python framework, it is designed to be minimal, and work as the foundation of other frameworks like Hug.
 
@@ -297,7 +297,7 @@ Although in FastAPI it's optional, and is used mainly to set headers, cookies, a
 
 ///
 
-### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
+### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> { #molten }
 
 I discovered Molten in the first stages of building **FastAPI**. And it has quite similar ideas:
 
@@ -321,7 +321,7 @@ This actually inspired updating parts of Pydantic, to support the same validatio
 
 ///
 
-### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
+### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> { #hug }
 
 Hug was one of the first frameworks to implement the declaration of API parameter types using Python type hints. This was a great idea that inspired other tools to do the same.
 
@@ -351,7 +351,7 @@ Hug inspired **FastAPI** to declare a `response` parameter in functions to set h
 
 ///
 
-### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5)
+### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5) { #apistar-0-5 }
 
 Right before deciding to build **FastAPI** I found **APIStar** server. It had almost everything I was looking for and had a great design.
 
@@ -399,9 +399,9 @@ I consider **FastAPI** a "spiritual successor" to APIStar, while improving and i
 
 ///
 
-## Used by **FastAPI**
+## Used by **FastAPI** { #used-by-fastapi }
 
-### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>
+### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> { #pydantic }
 
 Pydantic is a library to define data validation, serialization and documentation (using JSON Schema) based on Python type hints.
 
@@ -417,7 +417,7 @@ Handle all the data validation, data serialization and automatic model documenta
 
 ///
 
-### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
+### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> { #starlette }
 
 Starlette is a lightweight <abbr title="The new standard for building asynchronous Python web applications">ASGI</abbr> framework/toolkit, which is ideal for building high-performance asyncio services.
 
@@ -462,7 +462,7 @@ So, anything that you can do with Starlette, you can do it directly with **FastA
 
 ///
 
-### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>
+### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a> { #uvicorn }
 
 Uvicorn is a lightning-fast ASGI server, built on uvloop and httptools.
 
@@ -480,6 +480,6 @@ Check more details in the [Deployment](deployment/index.md){.internal-link targe
 
 ///
 
-## Benchmarks and speed
+## Benchmarks and speed { #benchmarks-and-speed }
 
 To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](benchmarks.md){.internal-link target=_blank}.
index 8207ec4807bb38dec9f9976bc305b479016962bc..1d2be0bb69522e389c8ab3a949798b0895636e10 100644 (file)
@@ -1,8 +1,8 @@
-# Concurrency and async / await
+# Concurrency and async / await { #concurrency-and-async-await }
 
 Details about the `async def` syntax for *path operation functions* and some background about asynchronous code, concurrency, and parallelism.
 
-## In a hurry?
+## In a hurry? { #in-a-hurry }
 
 <abbr title="too long; didn't read"><strong>TL;DR:</strong></abbr>
 
@@ -54,7 +54,7 @@ Anyway, in any of the cases above, FastAPI will still work asynchronously and be
 
 But by following the steps above, it will be able to do some performance optimizations.
 
-## Technical Details
+## Technical Details { #technical-details }
 
 Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax.
 
@@ -64,7 +64,7 @@ Let's see that phrase by parts in the sections below:
 * **`async` and `await`**
 * **Coroutines**
 
-## Asynchronous Code
+## Asynchronous Code { #asynchronous-code }
 
 Asynchronous code just means that the language 💬 has a way to tell the computer / program 🤖 that at some point in the code, it 🤖 will have to wait for *something else* to finish somewhere else. Let's say that *something else* is called "slow-file" 📝.
 
@@ -93,7 +93,7 @@ Instead of that, by being an "asynchronous" system, once finished, the task can
 
 For "synchronous" (contrary to "asynchronous") they commonly also use the term "sequential", because the computer / program follows all the steps in sequence before switching to a different task, even if those steps involve waiting.
 
-### Concurrency and Burgers
+### Concurrency and Burgers { #concurrency-and-burgers }
 
 This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**.
 
@@ -103,7 +103,7 @@ But the details between *concurrency* and *parallelism* are quite different.
 
 To see the difference, imagine the following story about burgers:
 
-### Concurrent Burgers
+### Concurrent Burgers { #concurrent-burgers }
 
 You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you. 😍
 
@@ -163,7 +163,7 @@ So you wait for your crush to finish the story (finish the current work ⏯ / ta
 
 Then you go to the counter 🔀, to the initial task that is now finished ⏯, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter ⏹. That in turn, creates a new task, of "eating burgers" 🔀 ⏯, but the previous one of "getting burgers" is finished ⏹.
 
-### Parallel Burgers
+### Parallel Burgers { #parallel-burgers }
 
 Now let's imagine these aren't "Concurrent Burgers", but "Parallel Burgers".
 
@@ -233,7 +233,7 @@ And you have to wait 🕙 in the line for a long time or you lose your turn.
 
 You probably wouldn't want to take your crush 😍 with you to run errands at the bank 🏦.
 
-### Burger Conclusion
+### Burger Conclusion { #burger-conclusion }
 
 In this scenario of "fast food burgers with your crush", as there is a lot of waiting 🕙, it makes a lot more sense to have a concurrent system ⏸🔀⏯.
 
@@ -253,7 +253,7 @@ And that's the same level of performance you get with **FastAPI**.
 
 And as you can have parallelism and asynchronicity at the same time, you get higher performance than most of the tested NodeJS frameworks and on par with Go, which is a compiled language closer to C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(all thanks to Starlette)</a>.
 
-### Is concurrency better than parallelism?
+### Is concurrency better than parallelism? { #is-concurrency-better-than-parallelism }
 
 Nope! That's not the moral of the story.
 
@@ -290,7 +290,7 @@ For example:
 * **Machine Learning**: it normally requires lots of "matrix" and "vector" multiplications. Think of a huge spreadsheet with numbers and multiplying all of them together at the same time.
 * **Deep Learning**: this is a sub-field of Machine Learning, so, the same applies. It's just that there is not a single spreadsheet of numbers to multiply, but a huge set of them, and in many cases, you use a special processor to build and / or use those models.
 
-### Concurrency + Parallelism: Web + Machine Learning
+### Concurrency + Parallelism: Web + Machine Learning { #concurrency-parallelism-web-machine-learning }
 
 With **FastAPI** you can take advantage of concurrency that is very common for web development (the same main attraction of NodeJS).
 
@@ -300,7 +300,7 @@ That, plus the simple fact that Python is the main language for **Data Science**
 
 To see how to achieve this parallelism in production see the section about [Deployment](deployment/index.md){.internal-link target=_blank}.
 
-## `async` and `await`
+## `async` and `await` { #async-and-await }
 
 Modern versions of Python have a very intuitive way to define asynchronous code. This makes it look just like normal "sequential" code and do the "awaiting" for you at the right moments.
 
@@ -349,7 +349,7 @@ async def read_burgers():
     return burgers
 ```
 
-### More technical details
+### More technical details { #more-technical-details }
 
 You might have noticed that `await` can only be used inside of functions defined with `async def`.
 
@@ -361,7 +361,7 @@ If you are working with **FastAPI** you don't have to worry about that, because
 
 But if you want to use `async` / `await` without FastAPI, you can do it as well.
 
-### Write your own async code
+### Write your own async code { #write-your-own-async-code }
 
 Starlette (and **FastAPI**) are based on <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, which makes it compatible with both Python's standard library <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> and <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
 
@@ -371,7 +371,7 @@ And even if you were not using FastAPI, you could also write your own async appl
 
 I created another library on top of AnyIO, as a thin layer on top, to improve a bit the type annotations and get better **autocompletion**, **inline errors**, etc. It also has a friendly introduction and tutorial to help you **understand** and write **your own async code**: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>. It would be particularly useful if you need to **combine async code with regular** (blocking/synchronous) code.
 
-### Other forms of asynchronous code
+### Other forms of asynchronous code { #other-forms-of-asynchronous-code }
 
 This style of using `async` and `await` is relatively new in the language.
 
@@ -385,13 +385,13 @@ In previous versions of Python, you could have used threads or <a href="https://
 
 In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which leads to <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
 
-## Coroutines
+## Coroutines { #coroutines }
 
 **Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function, that it can start and that it will end at some point, but that it might be paused ⏸ internally too, whenever there is an `await` inside of it.
 
 But all this functionality of using asynchronous code with `async` and `await` is many times summarized as using "coroutines". It is comparable to the main key feature of Go, the "Goroutines".
 
-## Conclusion
+## Conclusion { #conclusion }
 
 Let's see the same phrase from above:
 
@@ -401,7 +401,7 @@ That should make more sense now. ✨
 
 All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance.
 
-## Very Technical Details
+## Very Technical Details { #very-technical-details }
 
 /// warning
 
@@ -413,7 +413,7 @@ If you have quite some technical knowledge (coroutines, threads, blocking, etc.)
 
 ///
 
-### Path operation functions
+### Path operation functions { #path-operation-functions }
 
 When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
 
@@ -421,15 +421,15 @@ If you are coming from another async framework that does not work in the way des
 
 Still, in both situations, chances are that **FastAPI** will [still be faster](index.md#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework.
 
-### Dependencies
+### Dependencies { #dependencies }
 
 The same applies for [dependencies](tutorial/dependencies/index.md){.internal-link target=_blank}. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
 
-### Sub-dependencies
+### Sub-dependencies { #sub-dependencies }
 
 You can have multiple dependencies and [sub-dependencies](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
 
-### Other utility functions
+### Other utility functions { #other-utility-functions }
 
 Any other utility function that you call directly can be created with normal `def` or `async def` and FastAPI won't affect the way you call it.
 
index 62266c449b0bd412911e8697e4a598102260a72c..551f6316d3fb2a7983eafeea17532f014508be80 100644 (file)
@@ -1,10 +1,10 @@
-# Benchmarks
+# Benchmarks { #benchmarks }
 
 Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI).
 
 But when checking benchmarks and comparisons you should keep the following in mind.
 
-## Benchmarks and speed
+## Benchmarks and speed { #benchmarks-and-speed }
 
 When you check the benchmarks, it is common to see several tools of different types compared as equivalent.
 
index c6d408f8cca59bac0570eba0aa5b6976c15d9315..cb723dd13f82122b9748c5e37158cbdefb180575 100644 (file)
@@ -1,10 +1,10 @@
-# Deploy FastAPI on Cloud Providers
+# Deploy FastAPI on Cloud Providers { #deploy-fastapi-on-cloud-providers }
 
 You can use virtually **any cloud provider** to deploy your FastAPI application.
 
 In most of the cases, the main cloud providers have guides to deploy FastAPI with them.
 
-## Cloud Providers - Sponsors
+## Cloud Providers - Sponsors { #cloud-providers-sponsors }
 
 Some cloud providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**.
 
index ed635a9206d7c2869ebc5674bcc670d2ee5241f4..2174443f0f81127bc704f4349b83dce7f8f6e531 100644 (file)
@@ -1,4 +1,4 @@
-# Deployments Concepts
+# Deployments Concepts { #deployments-concepts }
 
 When deploying a **FastAPI** application, or actually, any type of web API, there are several concepts that you probably care about, and using them you can find the **most appropriate** way to **deploy your application**.
 
@@ -23,7 +23,7 @@ In the next chapters, I'll give you more **concrete recipes** to deploy FastAPI
 
 But for now, let's check these important **conceptual ideas**. These concepts also apply to any other type of web API. 💡
 
-## Security - HTTPS
+## Security - HTTPS { #security-https }
 
 In the [previous chapter about HTTPS](https.md){.internal-link target=_blank} we learned about how HTTPS provides encryption for your API.
 
@@ -31,7 +31,7 @@ We also saw that HTTPS is normally provided by a component **external** to your
 
 And there has to be something in charge of **renewing the HTTPS certificates**, it could be the same component or it could be something different.
 
-### Example Tools for HTTPS
+### Example Tools for HTTPS { #example-tools-for-https }
 
 Some of the tools you could use as a TLS Termination Proxy are:
 
@@ -55,11 +55,11 @@ I'll show you some concrete examples in the next chapters.
 
 Then the next concepts to consider are all about the program running your actual API (e.g. Uvicorn).
 
-## Program and Process
+## Program and Process { #program-and-process }
 
 We will talk a lot about the running "**process**", so it's useful to have clarity about what it means, and what's the difference with the word "**program**".
 
-### What is a Program
+### What is a Program { #what-is-a-program }
 
 The word **program** is commonly used to describe many things:
 
@@ -67,7 +67,7 @@ The word **program** is commonly used to describe many things:
 * The **file** that can be **executed** by the operating system, for example: `python`, `python.exe` or `uvicorn`.
 * A particular program while it is **running** on the operating system, using the CPU, and storing things in memory. This is also called a **process**.
 
-### What is a Process
+### What is a Process { #what-is-a-process }
 
 The word **process** is normally used in a more specific way, only referring to the thing that is running in the operating system (like in the last point above):
 
@@ -88,11 +88,11 @@ And, for example, you will probably see that there are multiple processes runnin
 
 Now that we know the difference between the terms **process** and **program**, let's continue talking about deployments.
 
-## Running on Startup
+## Running on Startup { #running-on-startup }
 
 In most cases, when you create a web API, you want it to be **always running**, uninterrupted, so that your clients can always access it. This is of course, unless you have a specific reason why you want it to run only in certain situations, but most of the time you want it constantly running and **available**.
 
-### In a Remote Server
+### In a Remote Server { #in-a-remote-server }
 
 When you set up a remote server (a cloud server, a virtual machine, etc.) the simplest thing you can do is use `fastapi run` (which uses Uvicorn) or something  similar, manually, the same way you do when developing locally.
 
@@ -102,15 +102,15 @@ But if your connection to the server is lost, the **running process** will proba
 
 And if the server is restarted (for example after updates, or migrations from the cloud provider) you probably **won't notice it**. And because of that, you won't even know that you have to restart the process manually. So, your API will just stay dead. 😱
 
-### Run Automatically on Startup
+### Run Automatically on Startup { #run-automatically-on-startup }
 
 In general, you will probably want the server program (e.g. Uvicorn) to be started automatically on server startup, and without needing any **human intervention**, to have a process always running with your API (e.g. Uvicorn running your FastAPI app).
 
-### Separate Program
+### Separate Program { #separate-program }
 
 To achieve this, you will normally have a **separate program** that would make sure your application is run on startup. And in many cases, it would also make sure other components or applications are also run, for example, a database.
 
-### Example Tools to Run at Startup
+### Example Tools to Run at Startup { #example-tools-to-run-at-startup }
 
 Some examples of the tools that can do this job are:
 
@@ -125,29 +125,29 @@ Some examples of the tools that can do this job are:
 
 I'll give you more concrete examples in the next chapters.
 
-## Restarts
+## Restarts { #restarts }
 
 Similar to making sure your application is run on startup, you probably also want to make sure it is **restarted** after failures.
 
-### We Make Mistakes
+### We Make Mistakes { #we-make-mistakes }
 
 We, as humans, make **mistakes**, all the time. Software almost *always* has **bugs** hidden in different places. 🐛
 
 And we as developers keep improving the code as we find those bugs and as we implement new features (possibly adding new bugs too 😅).
 
-### Small Errors Automatically Handled
+### Small Errors Automatically Handled { #small-errors-automatically-handled }
 
 When building web APIs with FastAPI, if there's an error in our code, FastAPI will normally contain it to the single request that triggered the error. 🛡
 
 The client will get a **500 Internal Server Error** for that request, but the application will continue working for the next requests instead of just crashing completely.
 
-### Bigger Errors - Crashes
+### Bigger Errors - Crashes { #bigger-errors-crashes }
 
 Nevertheless, there might be cases where we write some code that **crashes the entire application** making Uvicorn and Python crash. 💥
 
 And still, you would probably not want the application to stay dead because there was an error in one place, you probably want it to **continue running** at least for the *path operations* that are not broken.
 
-### Restart After Crash
+### Restart After Crash { #restart-after-crash }
 
 But in those cases with really bad errors that crash the running **process**, you would want an external component that is in charge of **restarting** the process, at least a couple of times...
 
@@ -161,7 +161,7 @@ So let's focus on the main cases, where it could crash entirely in some particul
 
 You would probably want to have the thing in charge of restarting your application as an **external component**, because by that point, the same application with Uvicorn and Python already crashed, so there's nothing in the same code of the same app that could do anything about it.
 
-### Example Tools to Restart Automatically
+### Example Tools to Restart Automatically { #example-tools-to-restart-automatically }
 
 In most cases, the same tool that is used to **run the program on startup** is also used to handle automatic **restarts**.
 
@@ -176,19 +176,19 @@ For example, this could be handled by:
 * Handled internally by a cloud provider as part of their services
 * Others...
 
-## Replication - Processes and Memory
+## Replication - Processes and Memory { #replication-processes-and-memory }
 
 With a FastAPI application, using a server program like the `fastapi` command that runs Uvicorn, running it once in **one process** can serve multiple clients concurrently.
 
 But in many cases, you will want to run several worker processes at the same time.
 
-### Multiple Processes - Workers
+### Multiple Processes - Workers { #multiple-processes-workers }
 
 If you have more clients than what a single process can handle (for example if the virtual machine is not too big) and you have **multiple cores** in the server's CPU, then you could have **multiple processes** running with the same application at the same time, and distribute all the requests among them.
 
 When you run **multiple processes** of the same API program, they are commonly called **workers**.
 
-### Worker Processes and Ports
+### Worker Processes and Ports { #worker-processes-and-ports }
 
 Remember from the docs [About HTTPS](https.md){.internal-link target=_blank} that only one process can be listening on one combination of port and IP address in a server?
 
@@ -196,19 +196,19 @@ This is still true.
 
 So, to be able to have **multiple processes** at the same time, there has to be a **single process listening on a port** that then transmits the communication to each worker process in some way.
 
-### Memory per Process
+### Memory per Process { #memory-per-process }
 
 Now, when the program loads things in memory, for example, a machine learning model in a variable, or the contents of a large file in a variable, all that **consumes a bit of the memory (RAM)** of the server.
 
 And multiple processes normally **don't share any memory**. This means that each running process has its own things, variables, and memory. And if you are consuming a large amount of memory in your code, **each process** will consume an equivalent amount of memory.
 
-### Server Memory
+### Server Memory { #server-memory }
 
 For example, if your code loads a Machine Learning model with **1 GB in size**, when you run one process with your API, it will consume at least 1 GB of RAM. And if you start **4 processes** (4 workers), each will consume 1 GB of RAM. So in total, your API will consume **4 GB of RAM**.
 
 And if your remote server or virtual machine only has 3 GB of RAM, trying to load more than 4 GB of RAM will cause problems. 🚨
 
-### Multiple Processes - An Example
+### Multiple Processes - An Example { #multiple-processes-an-example }
 
 In this example, there's a **Manager Process** that starts and controls two **Worker Processes**.
 
@@ -224,7 +224,7 @@ An interesting detail is that the percentage of the **CPU used** by each process
 
 If you have an API that does a comparable amount of computations every time and you have a lot of clients, then the **CPU utilization** will probably *also be stable* (instead of constantly going up and down quickly).
 
-### Examples of Replication Tools and Strategies
+### Examples of Replication Tools and Strategies { #examples-of-replication-tools-and-strategies }
 
 There can be several approaches to achieve this, and I'll tell you more about specific strategies in the next chapters, for example when talking about Docker and containers.
 
@@ -247,7 +247,7 @@ I'll tell you more about container images, Docker, Kubernetes, etc. in a future
 
 ///
 
-## Previous Steps Before Starting
+## Previous Steps Before Starting { #previous-steps-before-starting }
 
 There are many cases where you want to perform some steps **before starting** your application.
 
@@ -269,7 +269,7 @@ In that case, you wouldn't have to worry about any of this. 🤷
 
 ///
 
-### Examples of Previous Steps Strategies
+### Examples of Previous Steps Strategies { #examples-of-previous-steps-strategies }
 
 This will **depend heavily** on the way you **deploy your system**, and it would probably be connected to the way you start programs, handling restarts, etc.
 
@@ -285,7 +285,7 @@ I'll give you more concrete examples for doing this with containers in a future
 
 ///
 
-## Resource Utilization
+## Resource Utilization { #resource-utilization }
 
 Your server(s) is (are) a **resource**, you can consume or **utilize**, with your programs, the computation time on the CPUs, and the RAM memory available.
 
@@ -305,7 +305,7 @@ You could put an **arbitrary number** to target, for example, something **betwee
 
 You can use simple tools like `htop` to see the CPU and RAM used in your server or the amount used by each process. Or you can use more complex monitoring tools, which may be distributed across servers, etc.
 
-## Recap
+## Recap { #recap }
 
 You have been reading here some of the main concepts that you would probably need to keep in mind when deciding how to deploy your application:
 
index b106f7ac33a5ba09b8736a1a94b048335b4f10b8..a1de2dc46bd65445fd712a7af2a073eb297a295e 100644 (file)
@@ -1,4 +1,4 @@
-# FastAPI in Containers - Docker
+# FastAPI in Containers - Docker { #fastapi-in-containers-docker }
 
 When deploying FastAPI applications a common approach is to build a **Linux container image**. It's normally done using <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. You can then deploy that container image in one of a few possible ways.
 
@@ -32,7 +32,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"]
 
 </details>
 
-## What is a Container
+## What is a Container { #what-is-a-container }
 
 Containers (mainly Linux containers) are a very **lightweight** way to package applications including all their dependencies and necessary files while keeping them isolated from other containers (other applications or components) in the same system.
 
@@ -42,7 +42,7 @@ This way, containers consume **little resources**, an amount comparable to runni
 
 Containers also have their own **isolated** running processes (commonly just one process), file system, and network, simplifying deployment, security, development, etc.
 
-## What is a Container Image
+## What is a Container Image { #what-is-a-container-image }
 
 A **container** is run from a **container image**.
 
@@ -56,7 +56,7 @@ A container image is comparable to the **program** file and contents, e.g. `pyth
 
 And the **container** itself (in contrast to the **container image**) is the actual running instance of the image, comparable to a **process**. In fact, a container is running only when it has a **process running** (and normally it's only a single process). The container stops when there's no process running in it.
 
-## Container Images
+## Container Images { #container-images }
 
 Docker has been one of the main tools to create and manage **container images** and **containers**.
 
@@ -79,7 +79,7 @@ So, you would run **multiple containers** with different things, like a database
 
 All the container management systems (like Docker or Kubernetes) have these networking features integrated into them.
 
-## Containers and Processes
+## Containers and Processes { #containers-and-processes }
 
 A **container image** normally includes in its metadata the default program or command that should be run when the **container** is started and the parameters to be passed to that program. Very similar to what would be if it was in the command line.
 
@@ -91,7 +91,7 @@ A container normally has a **single process**, but it's also possible to start s
 
 But it's not possible to have a running container without **at least one running process**. If the main process stops, the container stops.
 
-## Build a Docker Image for FastAPI
+## Build a Docker Image for FastAPI { #build-a-docker-image-for-fastapi }
 
 Okay, let's build something now! 🚀
 
@@ -103,7 +103,7 @@ This is what you would want to do in **most cases**, for example:
 * When running on a **Raspberry Pi**
 * Using a cloud service that would run a container image for you, etc.
 
-### Package Requirements
+### Package Requirements { #package-requirements }
 
 You would normally have the **package requirements** for your application in some file.
 
@@ -138,7 +138,7 @@ There are other formats and tools to define and install package dependencies.
 
 ///
 
-### Create the **FastAPI** Code
+### Create the **FastAPI** Code { #create-the-fastapi-code }
 
 * Create an `app` directory and enter it.
 * Create an empty file `__init__.py`.
@@ -162,7 +162,7 @@ def read_item(item_id: int, q: Union[str, None] = None):
     return {"item_id": item_id, "q": q}
 ```
 
-### Dockerfile
+### Dockerfile { #dockerfile }
 
 Now in the same project directory create a file `Dockerfile` with:
 
@@ -238,7 +238,7 @@ Make sure to **always** use the **exec form** of the `CMD` instruction, as expla
 
 ///
 
-#### Use `CMD` - Exec Form
+#### Use `CMD` - Exec Form { #use-cmd-exec-form }
 
 The <a href="https://docs.docker.com/reference/dockerfile/#cmd" class="external-link" target="_blank">`CMD`</a> Docker instruction can be written using two forms:
 
@@ -262,7 +262,7 @@ You can read more about it in the <a href="https://docs.docker.com/reference/doc
 
 This can be quite noticeable when using `docker compose`. See this Docker Compose FAQ section for more technical details: <a href="https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop" class="external-link" target="_blank">Why do my services take 10 seconds to recreate or stop?</a>.
 
-#### Directory Structure
+#### Directory Structure { #directory-structure }
 
 You should now have a directory structure like:
 
@@ -275,7 +275,7 @@ You should now have a directory structure like:
 └── requirements.txt
 ```
 
-#### Behind a TLS Termination Proxy
+#### Behind a TLS Termination Proxy { #behind-a-tls-termination-proxy }
 
 If you are running your container behind a TLS Termination Proxy (load balancer) like Nginx or Traefik, add the option `--proxy-headers`, this will tell Uvicorn (through the FastAPI CLI) to trust the headers sent by that proxy telling it that the application is running behind HTTPS, etc.
 
@@ -283,7 +283,7 @@ If you are running your container behind a TLS Termination Proxy (load balancer)
 CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
 ```
 
-#### Docker Cache
+#### Docker Cache { #docker-cache }
 
 There's an important trick in this `Dockerfile`, we first copy the **file with the dependencies alone**, not the rest of the code. Let me tell you why is that.
 
@@ -315,7 +315,7 @@ Then, near the end of the `Dockerfile`, we copy all the code. As this is what **
 COPY ./app /code/app
 ```
 
-### Build the Docker Image
+### Build the Docker Image { #build-the-docker-image }
 
 Now that all the files are in place, let's build the container image.
 
@@ -340,7 +340,7 @@ In this case, it's the same current directory (`.`).
 
 ///
 
-### Start the Docker Container
+### Start the Docker Container { #start-the-docker-container }
 
 * Run a container based on your image:
 
@@ -352,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage
 
 </div>
 
-## Check it
+## Check it { #check-it }
 
 You should be able to check it in your Docker container's URL, for example: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> or <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (or equivalent, using your Docker host).
 
@@ -362,7 +362,7 @@ You will see something like:
 {"item_id": 5, "q": "somequery"}
 ```
 
-## Interactive API docs
+## Interactive API docs { #interactive-api-docs }
 
 Now you can go to <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> or <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (or equivalent, using your Docker host).
 
@@ -370,7 +370,7 @@ You will see the automatic interactive API documentation (provided by <a href="h
 
 ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
 
-## Alternative API docs
+## Alternative API docs { #alternative-api-docs }
 
 And you can also go to <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> or <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (or equivalent, using your Docker host).
 
@@ -378,7 +378,7 @@ You will see the alternative automatic documentation (provided by <a href="https
 
 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
 
-## Build a Docker Image with a Single-File FastAPI
+## Build a Docker Image with a Single-File FastAPI { #build-a-docker-image-with-a-single-file-fastapi }
 
 If your FastAPI is a single file, for example, `main.py` without an `./app` directory, your file structure could look like this:
 
@@ -413,7 +413,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"]
 
 When you pass the file to `fastapi run` it will detect automatically that it is a single file and not part of a package and will know how to import it and serve your FastAPI app. 😎
 
-## Deployment Concepts
+## Deployment Concepts { #deployment-concepts }
 
 Let's talk again about some of the same [Deployment Concepts](concepts.md){.internal-link target=_blank} in terms of containers.
 
@@ -430,7 +430,7 @@ Let's review these **deployment concepts** in terms of containers:
 * Memory
 * Previous steps before starting
 
-## HTTPS
+## HTTPS { #https }
 
 If we focus just on the **container image** for a FastAPI application (and later the running **container**), HTTPS normally would be handled **externally** by another tool.
 
@@ -444,7 +444,7 @@ Traefik has integrations with Docker, Kubernetes, and others, so it's very easy
 
 Alternatively, HTTPS could be handled by a cloud provider as one of their services (while still running the application in a container).
 
-## Running on Startup and Restarts
+## Running on Startup and Restarts { #running-on-startup-and-restarts }
 
 There is normally another tool in charge of **starting and running** your container.
 
@@ -454,7 +454,7 @@ In most (or all) cases, there's a simple option to enable running the container
 
 Without using containers, making applications run on startup and with restarts can be cumbersome and difficult. But when **working with containers** in most cases that functionality is included by default. ✨
 
-## Replication - Number of Processes
+## Replication - Number of Processes { #replication-number-of-processes }
 
 If you have a <abbr title="A group of machines that are configured to be connected and work together in some way.">cluster</abbr> of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Uvicorn with workers) in each container.
 
@@ -462,7 +462,7 @@ One of those distributed container management systems like Kubernetes normally h
 
 In those cases, you would probably want to build a **Docker image from scratch** as [explained above](#dockerfile), installing your dependencies, and running **a single Uvicorn process** instead of using multiple Uvicorn workers.
 
-### Load Balancer
+### Load Balancer { #load-balancer }
 
 When using containers, you would normally have some component **listening on the main port**. It could possibly be another container that is also a **TLS Termination Proxy** to handle **HTTPS** or some similar tool.
 
@@ -476,7 +476,7 @@ The same **TLS Termination Proxy** component used for HTTPS would probably also
 
 And when working with containers, the same system you use to start and manage them would already have internal tools to transmit the **network communication** (e.g. HTTP requests) from that **load balancer** (that could also be a **TLS Termination Proxy**) to the container(s) with your app.
 
-### One Load Balancer - Multiple Worker Containers
+### One Load Balancer - Multiple Worker Containers { #one-load-balancer-multiple-worker-containers }
 
 When working with **Kubernetes** or similar distributed container management systems, using their internal networking mechanisms would allow the single **load balancer** that is listening on the main **port** to transmit communication (requests) to possibly **multiple containers** running your app.
 
@@ -486,7 +486,7 @@ And the distributed container system with the **load balancer** would **distribu
 
 And normally this **load balancer** would be able to handle requests that go to *other* apps in your cluster (e.g. to a different domain, or under a different URL path prefix), and would transmit that communication to the right containers for *that other* application running in your cluster.
 
-### One Process per Container
+### One Process per Container { #one-process-per-container }
 
 In this type of scenario, you probably would want to have **a single (Uvicorn) process per container**, as you would already be handling replication at the cluster level.
 
@@ -494,7 +494,7 @@ So, in this case, you **would not** want to have a multiple workers in the conta
 
 Having another process manager inside the container (as would be with multiple workers) would only add **unnecessary complexity** that you are most probably already taking care of with your cluster system.
 
-### Containers with Multiple Processes and Special Cases
+### Containers with Multiple Processes and Special Cases { #containers-with-multiple-processes-and-special-cases }
 
 Of course, there are **special cases** where you could want to have **a container** with several **Uvicorn worker processes** inside.
 
@@ -519,11 +519,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"]
 
 Here are some examples of when that could make sense:
 
-#### A Simple App
+#### A Simple App { #a-simple-app }
 
 You could want a process manager in the container if your application is **simple enough** that can run it on a **single server**, not a cluster.
 
-#### Docker Compose
+#### Docker Compose { #docker-compose }
 
 You could be deploying to a **single server** (not a cluster) with **Docker Compose**, so you wouldn't have an easy way to manage replication of containers (with Docker Compose) while preserving the shared network and **load balancing**.
 
@@ -540,7 +540,7 @@ The main point is, **none** of these are **rules written in stone** that you hav
 * Memory
 * Previous steps before starting
 
-## Memory
+## Memory { #memory }
 
 If you run **a single process per container** you will have a more or less well-defined, stable, and limited amount of memory consumed by each of those containers (more than one if they are replicated).
 
@@ -550,11 +550,11 @@ If your application is **simple**, this will probably **not be a problem**, and
 
 If you run **multiple processes per container** you will have to make sure that the number of processes started doesn't **consume more memory** than what is available.
 
-## Previous Steps Before Starting and Containers
+## Previous Steps Before Starting and Containers { #previous-steps-before-starting-and-containers }
 
 If you are using containers (e.g. Docker, Kubernetes), then there are two main approaches you can use.
 
-### Multiple Containers
+### Multiple Containers { #multiple-containers }
 
 If you have **multiple containers**, probably each one running a **single process** (for example, in a **Kubernetes** cluster), then you would probably want to have a **separate container** doing the work of the **previous steps** in a single container, running a single process, **before** running the replicated worker containers.
 
@@ -566,11 +566,11 @@ If you are using Kubernetes, this would probably be an <a href="https://kubernet
 
 If in your use case there's no problem in running those previous steps **multiple times in parallel** (for example if you are not running database migrations, but just checking if the database is ready yet), then you could also just put them in each container right before starting the main process.
 
-### Single Container
+### Single Container { #single-container }
 
 If you have a simple setup, with a **single container** that then starts multiple **worker processes** (or also just one process), then you could run those previous steps in the same container, right before starting the process with the app.
 
-### Base Docker Image
+### Base Docker Image { #base-docker-image }
 
 There used to be an official FastAPI Docker image: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. But it is now deprecated. ⛔️
 
@@ -588,7 +588,7 @@ But now that Uvicorn (and the `fastapi` command) support using `--workers`, ther
 
 ///
 
-## Deploy the Container Image
+## Deploy the Container Image { #deploy-the-container-image }
 
 After having a Container (Docker) Image there are several ways to deploy it.
 
@@ -600,11 +600,11 @@ For example:
 * With another tool like Nomad
 * With a cloud service that takes your container image and deploys it
 
-## Docker Image with `uv`
+## Docker Image with `uv` { #docker-image-with-uv }
 
 If you are using <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a> to install and manage your project, you can follow their <a href="https://docs.astral.sh/uv/guides/integration/docker/" class="external-link" target="_blank">uv Docker guide</a>.
 
-## Recap
+## Recap { #recap }
 
 Using container systems (e.g. with **Docker** and **Kubernetes**) it becomes fairly straightforward to handle all the **deployment concepts**:
 
index 8b4a08dbefa17de3daaf888e642453c49922f8c3..b52ed40c8d210a2c26bc40c89f5601ca6c611ed8 100644 (file)
@@ -1,4 +1,4 @@
-# About HTTPS
+# About HTTPS { #about-https }
 
 It is easy to assume that HTTPS is something that is just "enabled" or not.
 
@@ -43,7 +43,7 @@ Some of the options you could use as a TLS Termination Proxy are:
 * Nginx
 * HAProxy
 
-## Let's Encrypt
+## Let's Encrypt { #lets-encrypt }
 
 Before Let's Encrypt, these **HTTPS certificates** were sold by trusted third parties.
 
@@ -57,11 +57,11 @@ The domains are securely verified and the certificates are generated automatical
 
 The idea is to automate the acquisition and renewal of these certificates so that you can have **secure HTTPS, for free, forever**.
 
-## HTTPS for Developers
+## HTTPS for Developers { #https-for-developers }
 
 Here's an example of how an HTTPS API could look like, step by step, paying attention mainly to the ideas important for developers.
 
-### Domain Name
+### Domain Name { #domain-name }
 
 It would probably all start by you **acquiring** some **domain name**. Then, you would configure it in a DNS server (possibly your same cloud provider).
 
@@ -77,7 +77,7 @@ This Domain Name part is way before HTTPS, but as everything depends on the doma
 
 ///
 
-### DNS
+### DNS { #dns }
 
 Now let's focus on all the actual HTTPS parts.
 
@@ -87,7 +87,7 @@ The DNS servers would tell the browser to use some specific **IP address**. That
 
 <img src="/img/deployment/https/https01.drawio.svg">
 
-### TLS Handshake Start
+### TLS Handshake Start { #tls-handshake-start }
 
 The browser would then communicate with that IP address on **port 443** (the HTTPS port).
 
@@ -97,7 +97,7 @@ The first part of the communication is just to establish the connection between
 
 This interaction between the client and the server to establish the TLS connection is called the **TLS handshake**.
 
-### TLS with SNI Extension
+### TLS with SNI Extension { #tls-with-sni-extension }
 
 **Only one process** in the server can be listening on a specific **port** in a specific **IP address**. There could be other processes listening on other ports in the same IP address, but only one for each combination of IP address and port.
 
@@ -127,7 +127,7 @@ Notice that the encryption of the communication happens at the **TCP level**, no
 
 ///
 
-### HTTPS Request
+### HTTPS Request { #https-request }
 
 Now that the client and server (specifically the browser and the TLS Termination Proxy) have an **encrypted TCP connection**, they can start the **HTTP communication**.
 
@@ -135,19 +135,19 @@ So, the client sends an **HTTPS request**. This is just an HTTP request through
 
 <img src="/img/deployment/https/https04.drawio.svg">
 
-### Decrypt the Request
+### Decrypt the Request { #decrypt-the-request }
 
 The TLS Termination Proxy would use the encryption agreed to **decrypt the request**, and would transmit the **plain (decrypted) HTTP request** to the process running the application (for example a process with Uvicorn running the FastAPI application).
 
 <img src="/img/deployment/https/https05.drawio.svg">
 
-### HTTP Response
+### HTTP Response { #http-response }
 
 The application would process the request and send a **plain (unencrypted) HTTP response** to the TLS Termination Proxy.
 
 <img src="/img/deployment/https/https06.drawio.svg">
 
-### HTTPS Response
+### HTTPS Response { #https-response }
 
 The TLS Termination Proxy would then **encrypt the response** using the cryptography agreed before (that started with the certificate for `someapp.example.com`), and send it back to the browser.
 
@@ -157,7 +157,7 @@ Next, the browser would verify that the response is valid and encrypted with the
 
 The client (browser) will know that the response comes from the correct server because it is using the cryptography they agreed using the **HTTPS certificate** before.
 
-### Multiple Applications
+### Multiple Applications { #multiple-applications }
 
 In the same server (or servers), there could be **multiple applications**, for example, other API programs or a database.
 
@@ -167,7 +167,7 @@ Only one process can be handling the specific IP and port (the TLS Termination P
 
 That way, the TLS Termination Proxy could handle HTTPS and certificates for **multiple domains**, for multiple applications, and then transmit the requests to the right application in each case.
 
-### Certificate Renewal
+### Certificate Renewal { #certificate-renewal }
 
 At some point in the future, each certificate would **expire** (about 3 months after acquiring it).
 
@@ -190,7 +190,7 @@ To do that, and to accommodate different application needs, there are several wa
 
 All this renewal process, while still serving the app, is one of the main reasons why you would want to have a **separate system to handle HTTPS** with a TLS Termination Proxy instead of just using the TLS certificates with the application server directly (e.g. Uvicorn).
 
-## Recap
+## Recap { #recap }
 
 Having **HTTPS** is very important, and quite **critical** in most cases. Most of the effort you as a developer have to put around HTTPS is just about **understanding these concepts** and how they work.
 
index b43bd050a37ab2bc7c53f9e4e9f4a56c69e7518b..2364791a7e3da9fbba980ede91782342aae5619b 100644 (file)
@@ -1,8 +1,8 @@
-# Deployment
+# Deployment { #deployment }
 
 Deploying a **FastAPI** application is relatively easy.
 
-## What Does Deployment Mean
+## What Does Deployment Mean { #what-does-deployment-mean }
 
 To **deploy** an application means to perform the necessary steps to make it **available to the users**.
 
@@ -10,7 +10,7 @@ For a **web API**, it normally involves putting it in a **remote machine**, with
 
 This is in contrast to the **development** stages, where you are constantly changing the code, breaking it and fixing it, stopping and restarting the development server, etc.
 
-## Deployment Strategies
+## Deployment Strategies { #deployment-strategies }
 
 There are several ways to do it depending on your specific use case and the tools that you use.
 
index 19ba98075371f174cacb08fb8d038f894ed48d29..8bb3945bce5dd6e8be0503a0f7631d1fb24db928 100644 (file)
@@ -1,6 +1,6 @@
-# Run a Server Manually
+# Run a Server Manually { #run-a-server-manually }
 
-## Use the `fastapi run` Command
+## Use the `fastapi run` Command { #use-the-fastapi-run-command }
 
 In short, use `fastapi run` to serve your FastAPI application:
 
@@ -42,7 +42,7 @@ That would work for most of the cases. 😎
 
 You could use that command for example to start your **FastAPI** app in a container, in a server, etc.
 
-## ASGI Servers
+## ASGI Servers { #asgi-servers }
 
 Let's go a little deeper into the details.
 
@@ -58,7 +58,7 @@ There are several alternatives, including:
 * <a href="https://github.com/emmett-framework/granian" class="external-link" target="_blank">Granian</a>: A Rust HTTP server for Python applications.
 * <a href="https://unit.nginx.org/howto/fastapi/" class="external-link" target="_blank">NGINX Unit</a>: NGINX Unit is a lightweight and versatile web application runtime.
 
-## Server Machine and Server Program
+## Server Machine and Server Program { #server-machine-and-server-program }
 
 There's a small detail about names to keep in mind. 💡
 
@@ -68,7 +68,7 @@ Just keep in mind that when you read "server" in general, it could refer to one
 
 When referring to the remote machine, it's common to call it **server**, but also **machine**, **VM** (virtual machine), **node**. Those all refer to some type of remote machine, normally running Linux, where you run programs.
 
-## Install the Server Program
+## Install the Server Program { #install-the-server-program }
 
 When you install FastAPI, it comes with a production server, Uvicorn, and you can start it with the `fastapi run` command.
 
@@ -100,7 +100,7 @@ When you install FastAPI with something like `pip install "fastapi[standard]"` y
 
 ///
 
-## Run the Server Program
+## Run the Server Program { #run-the-server-program }
 
 If you installed an ASGI server manually, you would normally need to pass an import string in a special format for it to import your FastAPI application:
 
@@ -141,7 +141,7 @@ It helps a lot during **development**, but you **shouldn't** use it in **product
 
 ///
 
-## Deployment Concepts
+## Deployment Concepts { #deployment-concepts }
 
 These examples run the server program (e.g Uvicorn), starting **a single process**, listening on all the IPs (`0.0.0.0`) on a predefined port (e.g. `80`).
 
index 5d6b0d00a429d67098bddc1bcfada2f251dcabb4..0351e8b5e556441e54c2469663d6f1a06c729ba6 100644 (file)
@@ -1,4 +1,4 @@
-# Server Workers - Uvicorn with Workers
+# Server Workers - Uvicorn with Workers { #server-workers-uvicorn-with-workers }
 
 Let's check back those deployment concepts from before:
 
@@ -25,7 +25,7 @@ In particular, when running on **Kubernetes** you will probably **not** want to
 
 ///
 
-## Multiple Workers
+## Multiple Workers { #multiple-workers }
 
 You can start multiple workers with the `--workers` command line option:
 
@@ -111,7 +111,7 @@ The only new option here is `--workers` telling Uvicorn to start 4 worker proces
 
 You can also see that it shows the **PID** of each process, `27365` for the parent process (this is the **process manager**) and one for each worker process: `27368`, `27369`, `27370`, and `27367`.
 
-## Deployment Concepts
+## Deployment Concepts { #deployment-concepts }
 
 Here you saw how to use multiple **workers** to **parallelize** the execution of the application, take advantage of **multiple cores** in the CPU, and be able to serve **more requests**.
 
@@ -124,13 +124,13 @@ From the list of deployment concepts from above, using workers would mainly help
 * **Memory**
 * **Previous steps before starting**
 
-## Containers and Docker
+## Containers and Docker { #containers-and-docker }
 
 In the next chapter about [FastAPI in Containers - Docker](docker.md){.internal-link target=_blank} I'll explain some strategies you could use to handle the other **deployment concepts**.
 
 I'll show you how to **build your own image from scratch** to run a single Uvicorn process. It is a simple process and is probably what you would want to do when using a distributed container management system like **Kubernetes**.
 
-## Recap
+## Recap { #recap }
 
 You can use multiple worker processes with the `--workers` CLI option with the `fastapi` or `uvicorn` commands to take advantage of **multi-core CPUs**, to run **multiple processes in parallel**.
 
index 23f49cf99433a31fa882464fb2e174ee7159e48c..15b449184470de9e63d78d7df113035fa1bc68d8 100644 (file)
@@ -1,4 +1,4 @@
-# About FastAPI versions
+# About FastAPI versions { #about-fastapi-versions }
 
 **FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly.
 
@@ -8,7 +8,7 @@ That's why the current versions are still `0.x.x`, this reflects that each versi
 
 You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code.
 
-## Pin your `fastapi` version
+## Pin your `fastapi` version { #pin-your-fastapi-version }
 
 The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application.
 
@@ -32,11 +32,11 @@ that would mean that you would use the versions `0.112.0` or above, but less tha
 
 If you use any other tool to manage your installations, like `uv`, Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages.
 
-## Available versions
+## Available versions { #available-versions }
 
 You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](../release-notes.md){.internal-link target=_blank}.
 
-## About versions
+## About versions { #about-versions }
 
 Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes.
 
@@ -62,7 +62,7 @@ The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR vers
 
 ///
 
-## Upgrading the FastAPI versions
+## Upgrading the FastAPI versions { #upgrading-the-fastapi-versions }
 
 You should add tests for your app.
 
@@ -72,7 +72,7 @@ After you have tests, then you can upgrade the **FastAPI** version to a more rec
 
 If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version.
 
-## About Starlette
+## About Starlette { #about-starlette }
 
 You shouldn't pin the version of `starlette`.
 
@@ -80,7 +80,7 @@ Different versions of **FastAPI** will use a specific newer version of Starlette
 
 So, you can just let **FastAPI** use the correct Starlette version.
 
-## About Pydantic
+## About Pydantic { #about-pydantic }
 
 Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI.
 
index 43dd06add3d56ae241ed8d25111cb6bebcd19d47..1dbd93570e9e5934b95d7db74aeb7c9a7e29fd3c 100644 (file)
@@ -1,4 +1,4 @@
-# Environment Variables
+# Environment Variables { #environment-variables }
 
 /// tip
 
@@ -10,7 +10,7 @@ An environment variable (also known as "**env var**") is a variable that lives *
 
 Environment variables could be useful for handling application **settings**, as part of the **installation** of Python, etc.
 
-## Create and Use Env Vars
+## Create and Use Env Vars { #create-and-use-env-vars }
 
 You can **create** and use environment variables in the **shell (terminal)**, without needing Python:
 
@@ -50,7 +50,7 @@ Hello Wade Wilson
 
 ////
 
-## Read env vars in Python
+## Read env vars in Python { #read-env-vars-in-python }
 
 You could also create environment variables **outside** of Python, in the terminal (or with any other method), and then **read them in Python**.
 
@@ -157,7 +157,7 @@ You can read more about it at <a href="https://12factor.net/config" class="exter
 
 ///
 
-## Types and Validation
+## Types and Validation { #types-and-validation }
 
 These environment variables can only handle **text strings**, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, as Linux, Windows, macOS).
 
@@ -165,7 +165,7 @@ That means that **any value** read in Python from an environment variable **will
 
 You will learn more about using environment variables for handling **application settings** in the [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank}.
 
-## `PATH` Environment Variable
+## `PATH` Environment Variable { #path-environment-variable }
 
 There is a **special** environment variable called **`PATH`** that is used by the operating systems (Linux, macOS, Windows) to find programs to run.
 
@@ -209,7 +209,7 @@ For example, when you type `python` in the terminal, the operating system looks
 
 If it finds it, then it will **use it**. Otherwise it keeps looking in the **other directories**.
 
-### Installing Python and Updating the `PATH`
+### Installing Python and Updating the `PATH` { #installing-python-and-updating-the-path }
 
 When you install Python, you might be asked if you want to update the `PATH` environment variable.
 
@@ -287,7 +287,7 @@ $ C:\opt\custompython\bin\python
 
 This information will be useful when learning about [Virtual Environments](virtual-environments.md){.internal-link target=_blank}.
 
-## Conclusion
+## Conclusion { #conclusion }
 
 With this you should have a basic understanding of what **environment variables** are and how to use them in Python.
 
index 654d2fe912b63bf2fca38f7da8185e92d20aa167..0fb7789dbe50ebe7c23fbbab01bec1f9243d1cc5 100644 (file)
@@ -1,4 +1,4 @@
-# FastAPI CLI
+# FastAPI CLI { #fastapi-cli }
 
 **FastAPI CLI** is a command line program that you can use to serve your FastAPI app, manage your FastAPI project, and more.
 
@@ -54,13 +54,13 @@ For production you would use `fastapi run` instead. 🚀
 
 Internally, **FastAPI CLI** uses <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>, a high-performance, production-ready, ASGI server. 😎
 
-## `fastapi dev`
+## `fastapi dev` { #fastapi-dev }
 
 Running `fastapi dev` initiates development mode.
 
 By default, **auto-reload** is enabled, automatically reloading the server when you make changes to your code. This is resource-intensive and could be less stable than when it's disabled. You should only use it for development. It also listens on the IP address `127.0.0.1`, which is the IP for your machine to communicate with itself alone (`localhost`).
 
-## `fastapi run`
+## `fastapi run` { #fastapi-run }
 
 Executing `fastapi run` starts FastAPI in production mode by default.
 
index 9c38a4bd2f6dd1a9ebf69ad77bb47a529e1b4a62..681caac35fd4a66db22b22f735a13e91cc7efa84 100644 (file)
@@ -1,17 +1,17 @@
-# Features
+# Features { #features }
 
-## FastAPI features
+## FastAPI features { #fastapi-features }
 
 **FastAPI** gives you the following:
 
-### Based on open standards
+### Based on open standards { #based-on-open-standards }
 
 * <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> for API creation, including declarations of <abbr title="also known as: endpoints, routes">path</abbr> <abbr title="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</abbr>, parameters, request bodies, security, etc.
 * Automatic data model documentation with <a href="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.
 
-### Automatic docs
+### Automatic docs { #automatic-docs }
 
 Interactive API documentation and exploration web user interfaces. As the framework is based on OpenAPI, there are multiple options, 2 included by default.
 
@@ -23,7 +23,7 @@ Interactive API documentation and exploration web user interfaces. As the framew
 
 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
 
-### Just Modern Python
+### Just Modern Python { #just-modern-python }
 
 It's all based on standard **Python type** declarations (thanks to Pydantic). No new syntax to learn. Just standard modern Python.
 
@@ -71,7 +71,7 @@ Pass the keys and values of the `second_user_data` dict directly as key-value ar
 
 ///
 
-### Editor support
+### Editor support { #editor-support }
 
 All the framework was designed to be easy and intuitive to use, all the decisions were tested on multiple editors even before starting development, to ensure the best development experience.
 
@@ -95,13 +95,13 @@ You will get completion in code you might even consider impossible before. As fo
 
 No more typing the wrong key names, coming back and forth between docs, or scrolling up and down to find if you finally used `username` or `user_name`.
 
-### Short
+### Short { #short }
 
 It has sensible **defaults** for everything, with optional configurations everywhere. All the parameters can be fine-tuned to do what you need and to define the API you need.
 
 But by default, it all **"just works"**.
 
-### Validation
+### Validation { #validation }
 
 * Validation for most (or all?) Python **data types**, including:
     * JSON objects (`dict`).
@@ -117,7 +117,7 @@ But by default, it all **"just works"**.
 
 All the validation is handled by the well-established and robust **Pydantic**.
 
-### Security and authentication
+### Security and authentication { #security-and-authentication }
 
 Security and authentication integrated. Without any compromise with databases or data models.
 
@@ -134,7 +134,7 @@ Plus all the security features from Starlette (including **session cookies**).
 
 All built as reusable tools and components that are easy to integrate with your systems, data stores, relational and NoSQL databases, etc.
 
-### Dependency Injection
+### Dependency Injection { #dependency-injection }
 
 FastAPI includes an extremely easy to use, but extremely powerful <abbr title='also known as "components", "resources", "services", "providers"'><strong>Dependency Injection</strong></abbr> system.
 
@@ -145,19 +145,19 @@ FastAPI includes an extremely easy to use, but extremely powerful <abbr title='a
 * Support for complex user authentication systems, **database connections**, etc.
 * **No compromise** with databases, frontends, etc. But easy integration with all of them.
 
-### Unlimited "plug-ins"
+### Unlimited "plug-ins" { #unlimited-plug-ins }
 
 Or in other way, no need for them, import and use the code you need.
 
 Any integration is designed to be so simple to use (with dependencies) that you can create a "plug-in" for your application in 2 lines of code using the same structure and syntax used for your *path operations*.
 
-### Tested
+### Tested { #tested }
 
 * 100% <abbr title="The amount of code that is automatically tested">test coverage</abbr>.
 * 100% <abbr title="Python type annotations, with this your editor and external tools can give you better support">type annotated</abbr> code base.
 * Used in production applications.
 
-## Starlette features
+## Starlette features { #starlette-features }
 
 **FastAPI** is fully compatible with (and based on) <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a>. So, any additional Starlette code you have, will also work.
 
@@ -175,7 +175,7 @@ With **FastAPI** you get all of **Starlette**'s features (as FastAPI is just Sta
 * 100% test coverage.
 * 100% type annotated codebase.
 
-## Pydantic features
+## Pydantic features { #pydantic-features }
 
 **FastAPI** is fully compatible with (and based on) <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>. So, any additional Pydantic code you have, will also work.
 
index 35d2e7b84dc017e838049885824437a7dfa6296f..0b9ac4f0b8212cc7f0a49f44ac49bfbce87e8316 100644 (file)
@@ -1,4 +1,4 @@
-# Help FastAPI - Get Help
+# Help FastAPI - Get Help { #help-fastapi-get-help }
 
 Do you like **FastAPI**?
 
@@ -10,7 +10,7 @@ There are very simple ways to help (several involve just one or two clicks).
 
 And there are several ways to get help too.
 
-## Subscribe to the newsletter
+## Subscribe to the newsletter { #subscribe-to-the-newsletter }
 
 You can subscribe to the (infrequent) [**FastAPI and friends** newsletter](newsletter.md){.internal-link target=_blank} to stay updated about:
 
@@ -20,17 +20,17 @@ You can subscribe to the (infrequent) [**FastAPI and friends** newsletter](newsl
 * Breaking changes 🚨
 * Tips and tricks ✅
 
-## Follow FastAPI on Twitter
+## Follow FastAPI on Twitter { #follow-fastapi-on-twitter }
 
 <a href="https://twitter.com/fastapi" class="external-link" target="_blank">Follow @fastapi on **Twitter**</a> to get the latest news about **FastAPI**. 🐦
 
-## Star **FastAPI** in GitHub
+## Star **FastAPI** in GitHub { #star-fastapi-in-github }
 
 You can "star" FastAPI in GitHub (clicking the star button at the top right): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. ⭐️
 
 By adding a star, other users will be able to find it more easily and see that it has been already useful for others.
 
-## Watch the GitHub repository for releases
+## Watch the GitHub repository for releases { #watch-the-github-repository-for-releases }
 
 You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
 
@@ -38,7 +38,7 @@ There you can select "Releases only".
 
 By doing it, you will receive notifications (in your email) whenever there's a new release (a new version) of **FastAPI** with bug fixes and new features.
 
-## Connect with the author
+## Connect with the author { #connect-with-the-author }
 
 You can connect with <a href="https://tiangolo.com" class="external-link" target="_blank">me (Sebastián Ramírez / `tiangolo`)</a>, the author.
 
@@ -57,19 +57,19 @@ You can:
     * Read other ideas, articles, and read about tools I have created.
     * Follow me to read when I publish something new.
 
-## Tweet about **FastAPI**
+## Tweet about **FastAPI** { #tweet-about-fastapi }
 
 <a href="https://twitter.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">Tweet about **FastAPI**</a> and let me and others know why you like it. 🎉
 
 I love to hear about how **FastAPI** is being used, what you have liked in it, in which project/company are you using it, etc.
 
-## Vote for FastAPI
+## Vote for FastAPI { #vote-for-fastapi }
 
 * <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Vote for **FastAPI** in Slant</a>.
 * <a href="https://alternativeto.net/software/fastapi/about/" class="external-link" target="_blank">Vote for **FastAPI** in AlternativeTo</a>.
 * <a href="https://stackshare.io/pypi-fastapi" class="external-link" target="_blank">Say you use **FastAPI** on StackShare</a>.
 
-## Help others with questions in GitHub
+## Help others with questions in GitHub { #help-others-with-questions-in-github }
 
 You can try and help others with their questions in:
 
@@ -88,7 +88,7 @@ The idea is for the **FastAPI** community to be kind and welcoming. At the same
 
 Here's how to help others with questions (in discussions or issues):
 
-### Understand the question
+### Understand the question { #understand-the-question }
 
 * Check if you can understand what is the **purpose** and use case of the person asking.
 
@@ -98,7 +98,7 @@ Here's how to help others with questions (in discussions or issues):
 
 * If you can't understand the question, ask for more **details**.
 
-### Reproduce the problem
+### Reproduce the problem { #reproduce-the-problem }
 
 For most of the cases and most of the questions there's something related to the person's **original code**.
 
@@ -108,13 +108,13 @@ In many cases they will only copy a fragment of the code, but that's not enough
 
 * If you are feeling too generous, you can try to **create an example** like that yourself, just based on the description of the problem. Just keep in mind that this might take a lot of time and it might be better to ask them to clarify the problem first.
 
-### Suggest solutions
+### Suggest solutions { #suggest-solutions }
 
 * After being able to understand the question, you can give them a possible **answer**.
 
 * In many cases, it's better to understand their **underlying problem or use case**, because there might be a better way to solve it than what they are trying to do.
 
-### Ask to close
+### Ask to close { #ask-to-close }
 
 If they reply, there's a high chance you would have solved their problem, congrats, **you're a hero**! 🦸
 
@@ -123,7 +123,7 @@ If they reply, there's a high chance you would have solved their problem, congra
     * In GitHub Discussions: mark the comment as the **answer**.
     * In GitHub Issues: **close** the issue.
 
-## Watch the GitHub repository
+## Watch the GitHub repository { #watch-the-github-repository }
 
 You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
 
@@ -131,7 +131,7 @@ If you select "Watching" instead of "Releases only" you will receive notificatio
 
 Then you can try and help them solve those questions.
 
-## Ask Questions
+## Ask Questions { #ask-questions }
 
 You can <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">create a new question</a> in the GitHub repository, for example to:
 
@@ -140,7 +140,7 @@ You can <a href="https://github.com/fastapi/fastapi/discussions/new?category=que
 
 **Note**: if you do it, then I'm going to ask you to also help others. 😉
 
-## Review Pull Requests
+## Review Pull Requests { #review-pull-requests }
 
 You can help me review pull requests from others.
 
@@ -150,13 +150,13 @@ Again, please try your best to be kind. 🤗
 
 Here's what to keep in mind and how to review a pull request:
 
-### Understand the problem
+### Understand the problem { #understand-the-problem }
 
 * First, make sure you **understand the problem** that the pull request is trying to solve. It might have a longer discussion in a GitHub Discussion or issue.
 
 * There's also a good chance that the pull request is not actually needed because the problem can be solved in a **different way**. Then you can suggest or ask about that.
 
-### Don't worry about style
+### Don't worry about style { #dont-worry-about-style }
 
 * Don't worry too much about things like commit message styles, I will squash and merge customizing the commit manually.
 
@@ -164,7 +164,7 @@ Here's what to keep in mind and how to review a pull request:
 
 And if there's any other style or consistency need, I'll ask directly for that, or I'll add commits on top with the needed changes.
 
-### Check the code
+### Check the code { #check-the-code }
 
 * Check and read the code, see if it makes sense, **run it locally** and see if it actually solves the problem.
 
@@ -182,7 +182,7 @@ So, it's really important that you actually read and run the code, and let me kn
 
 * If the PR can be simplified in a way, you can ask for that, but there's no need to be too picky, there might be a lot of subjective points of view (and I will have my own as well 🙈), so it's better if you can focus on the fundamental things.
 
-### Tests
+### Tests { #tests }
 
 * Help me check that the PR has **tests**.
 
@@ -194,7 +194,7 @@ So, it's really important that you actually read and run the code, and let me kn
 
 * Then also comment what you tried, that way I'll know that you checked it. 🤓
 
-## Create a Pull Request
+## Create a Pull Request { #create-a-pull-request }
 
 You can [contribute](contributing.md){.internal-link target=_blank} to the source code with Pull Requests, for example:
 
@@ -210,7 +210,7 @@ You can [contribute](contributing.md){.internal-link target=_blank} to the sourc
     * Make sure to add tests.
     * Make sure to add documentation if it's relevant.
 
-## Help Maintain FastAPI
+## Help Maintain FastAPI { #help-maintain-fastapi }
 
 Help me maintain **FastAPI**! 🤓
 
@@ -225,7 +225,7 @@ Those two tasks are what **consume time the most**. That's the main work of main
 
 If you can help me with that, **you are helping me maintain FastAPI** and making sure it keeps **advancing faster and better**. 🚀
 
-## Join the chat
+## Join the chat { #join-the-chat }
 
 Join the 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">Discord chat server</a> 👥 and hang out with others in the FastAPI community.
 
@@ -237,7 +237,7 @@ Use the chat only for other general conversations.
 
 ///
 
-### Don't use the chat for questions
+### Don't use the chat for questions { #dont-use-the-chat-for-questions }
 
 Keep in mind that as chats allow more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers.
 
@@ -247,7 +247,7 @@ Conversations in the chat systems are also not as easily searchable as in GitHub
 
 On the other side, there are thousands of users in the chat systems, so there's a high chance you'll find someone to talk to there, almost all the time. 😄
 
-## Sponsor the author
+## Sponsor the author { #sponsor-the-author }
 
 If your **product/company** depends on or is related to **FastAPI** and you want to reach its users, you can sponsor the author (me) through <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>. Depending on the tier, you could get some extra benefits, like a badge in the docs. 🎁
 
index b4a744d64b8bc6fc1d200897cdfaeff37574364d..2182c415c07ad260734b10f8e5df4aabe865a469 100644 (file)
@@ -1,4 +1,4 @@
-# History, Design and Future
+# History, Design and Future { #history-design-and-future }
 
 Some time ago, <a href="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920" class="external-link" target="_blank">a **FastAPI** user asked</a>:
 
@@ -6,7 +6,7 @@ Some time ago, <a href="https://github.com/fastapi/fastapi/issues/3#issuecomment
 
 Here's a little bit of that history.
 
-## Alternatives
+## Alternatives { #alternatives }
 
 I have been creating APIs with complex requirements for several years (Machine Learning, distributed systems, asynchronous jobs, NoSQL databases, etc), leading several teams of developers.
 
@@ -28,7 +28,7 @@ But at some point, there was no other option than creating something that provid
 
 </blockquote>
 
-## Investigation
+## Investigation { #investigation }
 
 By using all the previous alternatives I had the chance to learn from all of them, take ideas, and combine them in the best way I could find for myself and the teams of developers I have worked with.
 
@@ -38,7 +38,7 @@ Also, the best approach was to use already existing standards.
 
 So, before even starting to code **FastAPI**, I spent several months studying the specs for OpenAPI, JSON Schema, OAuth2, etc. Understanding their relationship, overlap, and differences.
 
-## Design
+## Design { #design }
 
 Then I spent some time designing the developer "API" I wanted to have as a user (as a developer using FastAPI).
 
@@ -52,7 +52,7 @@ That way I could find the best ways to reduce code duplication as much as possib
 
 All in a way that provided the best development experience for all the developers.
 
-## Requirements
+## Requirements { #requirements }
 
 After testing several alternatives, I decided that I was going to use <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">**Pydantic**</a> for its advantages.
 
@@ -60,11 +60,11 @@ Then I contributed to it, to make it fully compliant with JSON Schema, to suppor
 
 During the development, I also contributed to <a href="https://www.starlette.io/" class="external-link" target="_blank">**Starlette**</a>, the other key requirement.
 
-## Development
+## Development { #development }
 
 By the time I started creating **FastAPI** itself, most of the pieces were already in place, the design was defined, the requirements and tools were ready, and the knowledge about the standards and specifications was clear and fresh.
 
-## Future
+## Future { #future }
 
 By this point, it's already clear that **FastAPI** with its ideas is being useful for many people.
 
index bd6cad9a89ca87916cbc54814cd17ed4595405a4..833123e6a7cba35f3b403a642ff33270699e6b40 100644 (file)
@@ -1,8 +1,8 @@
-# Conditional OpenAPI
+# Conditional OpenAPI { #conditional-openapi }
 
 If you needed to, you could use settings and environment variables to configure OpenAPI conditionally depending on the environment, and even disable it entirely.
 
-## About security, APIs, and docs
+## About security, APIs, and docs { #about-security-apis-and-docs }
 
 Hiding your documentation user interfaces in production *shouldn't* be the way to protect your API.
 
@@ -23,7 +23,7 @@ If you want to secure your API, there are several better things you can do, for
 
 Nevertheless, you might have a very specific use case where you really need to disable the API docs for some environment (e.g. for production) or depending on configurations from environment variables.
 
-## Conditional OpenAPI from settings and env vars
+## Conditional OpenAPI from settings and env vars { #conditional-openapi-from-settings-and-env-vars }
 
 You can easily use the same Pydantic settings to configure your generated OpenAPI and the docs UIs.
 
index a8a8de48fb5ffec1b40a4997a5b626e0cbc597b6..2d7b99f8faf83b9a8a3208eded83e26bd0e01794 100644 (file)
@@ -1,4 +1,4 @@
-# Configure Swagger UI
+# Configure Swagger UI { #configure-swagger-ui }
 
 You can configure some extra <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">Swagger UI parameters</a>.
 
@@ -8,7 +8,7 @@ To configure them, pass the `swagger_ui_parameters` argument when creating the `
 
 FastAPI converts the configurations to **JSON** to make them compatible with JavaScript, as that's what Swagger UI needs.
 
-## Disable Syntax Highlighting
+## Disable Syntax Highlighting { #disable-syntax-highlighting }
 
 For example, you could disable syntax highlighting in Swagger UI.
 
@@ -24,7 +24,7 @@ But you can disable it by setting `syntaxHighlight` to `False`:
 
 <img src="/img/tutorial/extending-openapi/image03.png">
 
-## Change the Theme
+## Change the Theme { #change-the-theme }
 
 The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle):
 
@@ -34,7 +34,7 @@ That configuration would change the syntax highlighting color theme:
 
 <img src="/img/tutorial/extending-openapi/image04.png">
 
-## Change Default Swagger UI Parameters
+## Change Default Swagger UI Parameters { #change-default-swagger-ui-parameters }
 
 FastAPI includes some default configuration parameters appropriate for most of the use cases.
 
@@ -48,11 +48,11 @@ For example, to disable `deepLinking` you could pass these settings to `swagger_
 
 {* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *}
 
-## Other Swagger UI Parameters
+## Other Swagger UI Parameters { #other-swagger-ui-parameters }
 
 To see all the other possible configurations you can use, read the official <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">docs for Swagger UI parameters</a>.
 
-## JavaScript-only settings
+## JavaScript-only settings { #javascript-only-settings }
 
 Swagger UI also allows other configurations to be **JavaScript-only** objects (for example, JavaScript functions).
 
index 9d2238e4f9189bb7424867027cf4fd695ae1aa03..b38c4ec02e977f6a39d308845ac88260ab102d83 100644 (file)
@@ -1,4 +1,4 @@
-# Custom Docs UI Static Assets (Self-Hosting)
+# Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting }
 
 The API docs use **Swagger UI** and **ReDoc**, and each of those need some JavaScript and CSS files.
 
@@ -6,13 +6,13 @@ By default, those files are served from a <abbr title="Content Delivery Network:
 
 But it's possible to customize it, you can set a specific CDN, or serve the files yourself.
 
-## Custom CDN for JavaScript and CSS
+## Custom CDN for JavaScript and CSS { #custom-cdn-for-javascript-and-css }
 
 Let's say that you want to use a different <abbr title="Content Delivery Network">CDN</abbr>, for example you want to use `https://unpkg.com/`.
 
 This could be useful if for example you live in a country that restricts some URLs.
 
-### Disable the automatic docs
+### Disable the automatic docs { #disable-the-automatic-docs }
 
 The first step is to disable the automatic docs, as by default, those use the default CDN.
 
@@ -20,7 +20,7 @@ To disable them, set their URLs to `None` when creating your `FastAPI` app:
 
 {* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *}
 
-### Include the custom docs
+### Include the custom docs { #include-the-custom-docs }
 
 Now you can create the *path operations* for the custom docs.
 
@@ -46,23 +46,23 @@ Swagger UI will handle it behind the scenes for you, but it needs this "redirect
 
 ///
 
-### Create a *path operation* to test it
+### Create a *path operation* to test it { #create-a-path-operation-to-test-it }
 
 Now, to be able to test that everything works, create a *path operation*:
 
 {* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *}
 
-### Test it
+### Test it { #test-it }
 
 Now, you should be able to go to your docs at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, and reload the page, it will load those assets from the new CDN.
 
-## Self-hosting JavaScript and CSS for docs
+## Self-hosting JavaScript and CSS for docs { #self-hosting-javascript-and-css-for-docs }
 
 Self-hosting the JavaScript and CSS could be useful if, for example, you need your app to keep working even while offline, without open Internet access, or in a local network.
 
 Here you'll see how to serve those files yourself, in the same FastAPI app, and configure the docs to use them.
 
-### Project file structure
+### Project file structure { #project-file-structure }
 
 Let's say your project file structure looks like this:
 
@@ -85,7 +85,7 @@ Your new file structure could look like this:
 └── static/
 ```
 
-### Download the files
+### Download the files { #download-the-files }
 
 Download the static files needed for the docs and put them on that `static/` directory.
 
@@ -113,14 +113,14 @@ After that, your file structure could look like:
     └── swagger-ui.css
 ```
 
-### Serve the static files
+### Serve the static files { #serve-the-static-files }
 
 * Import `StaticFiles`.
 * "Mount" a `StaticFiles()` instance in a specific path.
 
 {* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *}
 
-### Test the static files
+### Test the static files { #test-the-static-files }
 
 Start your application and go to <a href="http://127.0.0.1:8000/static/redoc.standalone.js" class="external-link" target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js</a>.
 
@@ -138,7 +138,7 @@ That confirms that you are being able to serve static files from your app, and t
 
 Now we can configure the app to use those static files for the docs.
 
-### Disable the automatic docs for static files
+### Disable the automatic docs for static files { #disable-the-automatic-docs-for-static-files }
 
 The same as when using a custom CDN, the first step is to disable the automatic docs, as those use the CDN by default.
 
@@ -146,7 +146,7 @@ To disable them, set their URLs to `None` when creating your `FastAPI` app:
 
 {* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *}
 
-### Include the custom docs for static files
+### Include the custom docs for static files { #include-the-custom-docs-for-static-files }
 
 And the same way as with a custom CDN, now you can create the *path operations* for the custom docs.
 
@@ -172,13 +172,13 @@ Swagger UI will handle it behind the scenes for you, but it needs this "redirect
 
 ///
 
-### Create a *path operation* to test static files
+### Create a *path operation* to test static files { #create-a-path-operation-to-test-static-files }
 
 Now, to be able to test that everything works, create a *path operation*:
 
 {* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *}
 
-### Test Static Files UI
+### Test Static Files UI { #test-static-files-ui }
 
 Now, you should be able to disconnect your WiFi, go to your docs at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, and reload the page.
 
index 9b4160d758c9d77754116fb5bc283803a7ca589c..6df24a080c58109d6634e2f151c5588299fabceb 100644 (file)
@@ -1,4 +1,4 @@
-# Custom Request and APIRoute class
+# Custom Request and APIRoute class { #custom-request-and-apiroute-class }
 
 In some cases, you may want to override the logic used by the `Request` and `APIRoute` classes.
 
@@ -14,7 +14,7 @@ If you are just starting with **FastAPI** you might want to skip this section.
 
 ///
 
-## Use cases
+## Use cases { #use-cases }
 
 Some use cases include:
 
@@ -22,13 +22,13 @@ Some use cases include:
 * Decompressing gzip-compressed request bodies.
 * Automatically logging all request bodies.
 
-## Handling custom request body encodings
+## Handling custom request body encodings { #handling-custom-request-body-encodings }
 
 Let's see how to make use of a custom `Request` subclass to decompress gzip requests.
 
 And an `APIRoute` subclass to use that custom request class.
 
-### Create a custom `GzipRequest` class
+### Create a custom `GzipRequest` class { #create-a-custom-gziprequest-class }
 
 /// tip
 
@@ -44,7 +44,7 @@ That way, the same route class can handle gzip compressed or uncompressed reques
 
 {* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *}
 
-### Create a custom `GzipRoute` class
+### Create a custom `GzipRoute` class { #create-a-custom-gziproute-class }
 
 Next, we create a custom subclass of `fastapi.routing.APIRoute` that will make use of the `GzipRequest`.
 
@@ -78,7 +78,7 @@ After that, all of the processing logic is the same.
 
 But because of our changes in `GzipRequest.body`, the request body will be automatically decompressed when it is loaded by **FastAPI** when needed.
 
-## Accessing the request body in an exception handler
+## Accessing the request body in an exception handler { #accessing-the-request-body-in-an-exception-handler }
 
 /// tip
 
@@ -98,7 +98,7 @@ If an exception occurs, the`Request` instance will still be in scope, so we can
 
 {* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *}
 
-## Custom `APIRoute` class in a router
+## Custom `APIRoute` class in a router { #custom-apiroute-class-in-a-router }
 
 You can also set the `route_class` parameter of an `APIRouter`:
 
index 26c742c203cecaad3c5fcdda577888ef2358bc6b..5e672665ef1fe9f03c746d9f25f9e165c55e08d3 100644 (file)
@@ -1,10 +1,10 @@
-# Extending OpenAPI
+# Extending OpenAPI { #extending-openapi }
 
 There are some cases where you might need to modify the generated OpenAPI schema.
 
 In this section you will see how.
 
-## The normal process
+## The normal process { #the-normal-process }
 
 The normal (default) process, is as follows.
 
@@ -33,31 +33,31 @@ The parameter `summary` is available in OpenAPI 3.1.0 and above, supported by Fa
 
 ///
 
-## Overriding the defaults
+## Overriding the defaults { #overriding-the-defaults }
 
 Using the information above, you can use the same utility function to generate the OpenAPI schema and override each part that you need.
 
 For example, let's add <a href="https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo" class="external-link" target="_blank">ReDoc's OpenAPI extension to include a custom logo</a>.
 
-### Normal **FastAPI**
+### Normal **FastAPI** { #normal-fastapi }
 
 First, write all your **FastAPI** application as normally:
 
 {* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *}
 
-### Generate the OpenAPI schema
+### Generate the OpenAPI schema { #generate-the-openapi-schema }
 
 Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
 
 {* ../../docs_src/extending_openapi/tutorial001.py hl[2,15:21] *}
 
-### Modify the OpenAPI schema
+### Modify the OpenAPI schema { #modify-the-openapi-schema }
 
 Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
 
 {* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *}
 
-### Cache the OpenAPI schema
+### Cache the OpenAPI schema { #cache-the-openapi-schema }
 
 You can use the property `.openapi_schema` as a "cache", to store your generated schema.
 
@@ -67,13 +67,13 @@ It will be generated only once, and then the same cached schema will be used for
 
 {* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *}
 
-### Override the method
+### Override the method { #override-the-method }
 
 Now you can replace the `.openapi()` method with your new function.
 
 {* ../../docs_src/extending_openapi/tutorial001.py hl[29] *}
 
-### Check it
+### Check it { #check-it }
 
 Once you go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> you will see that you are using your custom logo (in this example, **FastAPI**'s logo):
 
index 04367c6b76353255d8eb435289299ada4108b133..9347192607a986fe210a16aba1beb95dbe1d74cd 100644 (file)
@@ -1,39 +1,39 @@
-# General - How To - Recipes
+# General - How To - Recipes { #general-how-to-recipes }
 
 Here are several pointers to other places in the docs, for general or frequent questions.
 
-## Filter Data - Security
+## Filter Data - Security { #filter-data-security }
 
 To ensure that you don't return more data than you should, read the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md){.internal-link target=_blank}.
 
-## Documentation Tags - OpenAPI
+## Documentation Tags - OpenAPI { #documentation-tags-openapi }
 
 To add tags to your *path operations*, and group them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}.
 
-## Documentation Summary and Description - OpenAPI
+## Documentation Summary and Description - OpenAPI { #documentation-summary-and-description-openapi }
 
 To add a summary and description to your *path operations*, and show them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}.
 
-## Documentation Response description - OpenAPI
+## Documentation Response description - OpenAPI { #documentation-response-description-openapi }
 
 To define the description of the response, shown in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}.
 
-## Documentation Deprecate a *Path Operation* - OpenAPI
+## Documentation Deprecate a *Path Operation* - OpenAPI { #documentation-deprecate-a-path-operation-openapi }
 
 To deprecate a *path operation*, and show it in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}.
 
-## Convert any Data to JSON-compatible
+## Convert any Data to JSON-compatible { #convert-any-data-to-json-compatible }
 
 To convert any data to JSON-compatible, read the docs for [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
 
-## OpenAPI Metadata - Docs
+## OpenAPI Metadata - Docs { #openapi-metadata-docs }
 
 To add metadata to your OpenAPI schema, including a license, version, contact, etc, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md){.internal-link target=_blank}.
 
-## OpenAPI Custom URL
+## OpenAPI Custom URL { #openapi-custom-url }
 
 To customize the OpenAPI URL (or remove it), read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}.
 
-## OpenAPI Docs URLs
+## OpenAPI Docs URLs { #openapi-docs-urls }
 
 To update the URLs used for the automatically generated docs user interfaces, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}.
index 3610107360acb774c600b83bd9edf0fdf60ddab1..99b024d39b3d0ca60e8f2aae0dc94413f3319bdd 100644 (file)
@@ -1,4 +1,4 @@
-# GraphQL
+# GraphQL { #graphql }
 
 As **FastAPI** is based on the **ASGI** standard, it's very easy to integrate any **GraphQL** library also compatible with ASGI.
 
@@ -14,7 +14,7 @@ Make sure you evaluate if the **benefits** for your use case compensate the **dr
 
 ///
 
-## GraphQL Libraries
+## GraphQL Libraries { #graphql-libraries }
 
 Here are some of the **GraphQL** libraries that have **ASGI** support. You could use them with **FastAPI**:
 
@@ -27,7 +27,7 @@ Here are some of the **GraphQL** libraries that have **ASGI** support. You could
 * <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a>
     * With <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a>
 
-## GraphQL with Strawberry
+## GraphQL with Strawberry { #graphql-with-strawberry }
 
 If you need or want to work with **GraphQL**, <a href="https://strawberry.rocks/" class="external-link" target="_blank">**Strawberry**</a> is the **recommended** library as it has the design closest to **FastAPI's** design, it's all based on **type annotations**.
 
@@ -41,7 +41,7 @@ You can learn more about Strawberry in the <a href="https://strawberry.rocks/" c
 
 And also the docs about <a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">Strawberry with FastAPI</a>.
 
-## Older `GraphQLApp` from Starlette
+## Older `GraphQLApp` from Starlette { #older-graphqlapp-from-starlette }
 
 Previous versions of Starlette included a `GraphQLApp` class to integrate with <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a>.
 
@@ -53,7 +53,7 @@ If you need GraphQL, I still would recommend you check out <a href="https://stra
 
 ///
 
-## Learn More
+## Learn More { #learn-more }
 
 You can learn more about **GraphQL** in the <a href="https://graphql.org/" class="external-link" target="_blank">official GraphQL documentation</a>.
 
index 730dce5d559a2b07217019c425552cbfc8a7d22d..5a8ce08de7854fe5cabb30a933aa96ec8c40d922 100644 (file)
@@ -1,4 +1,4 @@
-# How To - Recipes
+# How To - Recipes { #how-to-recipes }
 
 Here you will see different recipes or "how to" guides for **several topics**.
 
index 9a27638fe687b21af750ea7d577466d778230320..3c78a56d36888543e0a3b46b8bf5e5807545ec2a 100644 (file)
@@ -1,4 +1,4 @@
-# Separate OpenAPI Schemas for Input and Output or Not
+# Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not }
 
 When using **Pydantic v2**, the generated OpenAPI is a bit more exact and **correct** than before. 😎
 
@@ -6,13 +6,13 @@ In fact, in some cases, it will even have **two JSON Schemas** in OpenAPI for th
 
 Let's see how that works and how to change it if you need to do that.
 
-## Pydantic Models for Input and Output
+## Pydantic Models for Input and Output { #pydantic-models-for-input-and-output }
 
 Let's say you have a Pydantic model with default values, like this one:
 
 {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *}
 
-### Model for Input
+### Model for Input { #model-for-input }
 
 If you use this model as an input like here:
 
@@ -20,7 +20,7 @@ If you use this model as an input like here:
 
 ...then the `description` field will **not be required**. Because it has a default value of `None`.
 
-### Input Model in Docs
+### Input Model in Docs { #input-model-in-docs }
 
 You can confirm that in the docs, the `description` field doesn't have a **red asterisk**, it's not marked as required:
 
@@ -28,7 +28,7 @@ You can confirm that in the docs, the `description` field doesn't have a **red a
 <img src="/img/tutorial/separate-openapi-schemas/image01.png">
 </div>
 
-### Model for Output
+### Model for Output { #model-for-output }
 
 But if you use the same model as an output, like here:
 
@@ -36,7 +36,7 @@ But if you use the same model as an output, like here:
 
 ...then because `description` has a default value, if you **don't return anything** for that field, it will still have that **default value**.
 
-### Model for Output Response Data
+### Model for Output Response Data { #model-for-output-response-data }
 
 If you interact with the docs and check the response, even though the code didn't add anything in one of the `description` fields, the JSON response contains the default value (`null`):
 
@@ -55,7 +55,7 @@ Because of that, the JSON Schema for a model can be different depending on if it
 * for **input** the `description` will **not be required**
 * for **output** it will be **required** (and possibly `None`, or in JSON terms, `null`)
 
-### Model for Output in Docs
+### Model for Output in Docs { #model-for-output-in-docs }
 
 You can check the output model in the docs too, **both** `name` and `description` are marked as **required** with a **red asterisk**:
 
@@ -63,7 +63,7 @@ You can check the output model in the docs too, **both** `name` and `description
 <img src="/img/tutorial/separate-openapi-schemas/image03.png">
 </div>
 
-### Model for Input and Output in Docs
+### Model for Input and Output in Docs { #model-for-input-and-output-in-docs }
 
 And if you check all the available Schemas (JSON Schemas) in OpenAPI, you will see that there are two, one `Item-Input` and one `Item-Output`.
 
@@ -77,7 +77,7 @@ But for `Item-Output`, `description` is **required**, it has a red asterisk.
 
 With this feature from **Pydantic v2**, your API documentation is more **precise**, and if you have autogenerated clients and SDKs, they will be more precise too, with a better **developer experience** and consistency. 🎉
 
-## Do not Separate Schemas
+## Do not Separate Schemas { #do-not-separate-schemas }
 
 Now, there are some cases where you might want to have the **same schema for input and output**.
 
@@ -93,7 +93,7 @@ Support for `separate_input_output_schemas` was added in FastAPI `0.102.0`. 🤓
 
 {* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *}
 
-### Same Schema for Input and Output Models in Docs
+### Same Schema for Input and Output Models in Docs { #same-schema-for-input-and-output-models-in-docs }
 
 And now there will be one single schema for input and output for the model, only `Item`, and it will have `description` as **not required**:
 
index d0ed15bca7db8be7b9499733884127078fd98ba0..400fdcfc646bd4e96280e37484f26dceb32069cf 100644 (file)
@@ -1,4 +1,4 @@
-# Testing a Database
+# Testing a Database { #testing-a-database }
 
 You can study about databases, SQL, and SQLModel in the <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel docs</a>. 🤓
 
index 938882d7d6ec537b29f92d603331b807c97fc7c1..db22ea0f9b18058eb6d16bc9bc36cab1d274332d 100644 (file)
@@ -1,4 +1,4 @@
-# FastAPI
+# FastAPI { #fastapi }
 
 <style>
 .md-content .md-typeset h1 { display: none; }
@@ -48,7 +48,7 @@ The key features are:
 
 <small>* estimation based on tests on an internal development team, building production applications.</small>
 
-## Sponsors
+## Sponsors { #sponsors }
 
 <!-- sponsors -->
 
@@ -65,7 +65,7 @@ The key features are:
 
 <a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
 
-## Opinions
+## Opinions { #opinions }
 
 "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
 
@@ -111,7 +111,7 @@ The key features are:
 
 ---
 
-## **Typer**, the FastAPI of CLIs
+## **Typer**, the FastAPI of CLIs { #typer-the-fastapi-of-clis }
 
 <a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
 
@@ -119,14 +119,14 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
 
 **Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
 
-## Requirements
+## Requirements { #requirements }
 
 FastAPI stands on the shoulders of giants:
 
 * <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
 * <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> for the data parts.
 
-## Installation
+## Installation { #installation }
 
 Create and activate a <a href="https://fastapi.tiangolo.com/virtual-environments/" class="external-link" target="_blank">virtual environment</a> and then install FastAPI:
 
@@ -142,9 +142,9 @@ $ pip install "fastapi[standard]"
 
 **Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals.
 
-## Example
+## Example { #example }
 
-### Create it
+### Create it { #create-it }
 
 Create a file `main.py` with:
 
@@ -195,7 +195,7 @@ If you don't know, check the _"In a hurry?"_ section about <a href="https://fast
 
 </details>
 
-### Run it
+### Run it { #run-it }
 
 Run the server with:
 
@@ -237,7 +237,7 @@ You can read more about it in the <a href="https://fastapi.tiangolo.com/fastapi-
 
 </details>
 
-### Check it
+### Check it { #check-it }
 
 Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
 
@@ -254,7 +254,7 @@ You already created an API that:
 * The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
 * The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
 
-### Interactive API docs
+### Interactive API docs { #interactive-api-docs }
 
 Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
@@ -262,7 +262,7 @@ You will see the automatic interactive API documentation (provided by <a href="h
 
 ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
 
-### Alternative API docs
+### Alternative API docs { #alternative-api-docs }
 
 And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
 
@@ -270,7 +270,7 @@ You will see the alternative automatic documentation (provided by <a href="https
 
 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
 
-## Example upgrade
+## Example upgrade { #example-upgrade }
 
 Now modify the file `main.py` to receive a body from a `PUT` request.
 
@@ -308,7 +308,7 @@ def update_item(item_id: int, item: Item):
 
 The `fastapi dev` server should reload automatically.
 
-### Interactive API docs upgrade
+### Interactive API docs upgrade { #interactive-api-docs-upgrade }
 
 Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
@@ -324,7 +324,7 @@ Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_bl
 
 ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
 
-### Alternative API docs upgrade
+### Alternative API docs upgrade { #alternative-api-docs-upgrade }
 
 And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
 
@@ -332,7 +332,7 @@ And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" targe
 
 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
 
-### Recap
+### Recap { #recap }
 
 In summary, you declare **once** the types of parameters, body, etc. as function parameters.
 
@@ -444,17 +444,17 @@ For a more complete example including more features, see the <a href="https://fa
     * **Cookie Sessions**
     * ...and more.
 
-## Performance
+## Performance { #performance }
 
 Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
 
 To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
 
-## Dependencies
+## Dependencies { #dependencies }
 
 FastAPI depends on Pydantic and Starlette.
 
-### `standard` Dependencies
+### `standard` Dependencies { #standard-dependencies }
 
 When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies:
 
@@ -474,15 +474,15 @@ Used by FastAPI:
 * `fastapi-cli[standard]` - to provide the `fastapi` command.
     * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
 
-### Without `standard` Dependencies
+### Without `standard` Dependencies { #without-standard-dependencies }
 
 If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`.
 
-### Without `fastapi-cloud-cli`
+### Without `fastapi-cloud-cli` { #without-fastapi-cloud-cli }
 
 If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
 
-### Additional Optional Dependencies
+### Additional Optional Dependencies { #additional-optional-dependencies }
 
 There are some additional dependencies you might want to install.
 
@@ -496,6 +496,6 @@ Additional optional FastAPI dependencies:
 * <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
 * <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
 
-## License
+## License { #license }
 
 This project is licensed under the terms of the MIT license.
index d056fb320072c328327025704b69febd6b2fcf01..21e54009b6af6d300d55e2f57dbe9d8a0a60baa3 100644 (file)
@@ -1,4 +1,4 @@
-# Learn
+# Learn { #learn }
 
 Here are the introductory sections and the tutorials to learn **FastAPI**.
 
index 665bc54f9cdf9edc2694be2664777a2e11d60267..44f058b90213801b15de41292fd13df1c0ee5bf8 100644 (file)
@@ -1,4 +1,4 @@
-# Full Stack FastAPI Template
+# Full Stack FastAPI Template { #full-stack-fastapi-template }
 
 Templates, while typically come with a specific setup, are designed to be flexible and customizable. This allows you to modify and adapt them to your project's requirements, making them an excellent starting point. 🏁
 
@@ -6,7 +6,7 @@ You can use this template to get started, as it includes a lot of the initial se
 
 GitHub Repository: <a href="https://github.com/tiangolo/full-stack-fastapi-template" class="external-link" target="_blank">Full Stack FastAPI Template</a>
 
-## Full Stack FastAPI Template - Technology Stack and Features
+## Full Stack FastAPI Template - Technology Stack and Features { #full-stack-fastapi-template-technology-stack-and-features }
 
 - ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API.
     - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) for the Python SQL database interactions (ORM).
index 6c28577cc22c93e1d964a7ac540e06e9440ba798..e4bd2a87493e1fd1e822d81674b449c7ec92bc85 100644 (file)
@@ -1,4 +1,4 @@
-# Python Types Intro
+# Python Types Intro { #python-types-intro }
 
 Python has support for optional "type hints" (also called "type annotations").
 
@@ -18,7 +18,7 @@ If you are a Python expert, and you already know everything about type hints, sk
 
 ///
 
-## Motivation
+## Motivation { #motivation }
 
 Let's start with a simple example:
 
@@ -38,7 +38,7 @@ The function does the following:
 
 {* ../../docs_src/python_types/tutorial001.py hl[2] *}
 
-### Edit it
+### Edit it { #edit-it }
 
 It's a very simple program.
 
@@ -58,7 +58,7 @@ But, sadly, you get nothing useful:
 
 <img src="/img/python-types/image01.png">
 
-### Add types
+### Add types { #add-types }
 
 Let's modify a single line from the previous version.
 
@@ -102,7 +102,7 @@ With that, you can scroll, seeing the options, until you find the one that "ring
 
 <img src="/img/python-types/image03.png">
 
-## More motivation
+## More motivation { #more-motivation }
 
 Check this function, it already has type hints:
 
@@ -116,13 +116,13 @@ Now you know that you have to fix it, convert `age` to a string with `str(age)`:
 
 {* ../../docs_src/python_types/tutorial004.py hl[2] *}
 
-## Declaring types
+## Declaring types { #declaring-types }
 
 You just saw the main place to declare type hints. As function parameters.
 
 This is also the main place you would use them with **FastAPI**.
 
-### Simple types
+### Simple types { #simple-types }
 
 You can declare all the standard Python types, not only `str`.
 
@@ -135,7 +135,7 @@ You can use, for example:
 
 {* ../../docs_src/python_types/tutorial005.py hl[1] *}
 
-### Generic types with type parameters
+### Generic types with type parameters { #generic-types-with-type-parameters }
 
 There are some data structures that can contain other values, like `dict`, `list`, `set` and `tuple`. And the internal values can have their own type too.
 
@@ -143,7 +143,7 @@ These types that have internal types are called "**generic**" types. And it's po
 
 To declare those types and the internal types, you can use the standard Python module `typing`. It exists specifically to support these type hints.
 
-#### Newer versions of Python
+#### Newer versions of Python { #newer-versions-of-python }
 
 The syntax using `typing` is **compatible** with all versions, from Python 3.6 to the latest ones, including Python 3.9, Python 3.10, etc.
 
@@ -157,7 +157,7 @@ For example "**Python 3.6+**" means it's compatible with Python 3.6 or above (in
 
 If you can use the **latest versions of Python**, use the examples for the latest version, those will have the **best and simplest syntax**, for example, "**Python 3.10+**".
 
-#### List
+#### List { #list }
 
 For example, let's define a variable to be a `list` of `str`.
 
@@ -221,7 +221,7 @@ Notice that the variable `item` is one of the elements in the list `items`.
 
 And still, the editor knows it is a `str`, and provides support for that.
 
-#### Tuple and Set
+#### Tuple and Set { #tuple-and-set }
 
 You would do the same to declare `tuple`s and `set`s:
 
@@ -246,7 +246,7 @@ This means:
 * The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
 * The variable `items_s` is a `set`, and each of its items is of type `bytes`.
 
-#### Dict
+#### Dict { #dict }
 
 To define a `dict`, you pass 2 type parameters, separated by commas.
 
@@ -276,7 +276,7 @@ This means:
     * The keys of this `dict` are of type `str` (let's say, the name of each item).
     * The values of this `dict` are of type `float` (let's say, the price of each item).
 
-#### Union
+#### Union { #union }
 
 You can declare that a variable can be any of **several types**, for example, an `int` or a `str`.
 
@@ -302,7 +302,7 @@ In Python 3.10 there's also a **new syntax** where you can put the possible type
 
 In both cases this means that `item` could be an `int` or a `str`.
 
-#### Possibly `None`
+#### Possibly `None` { #possibly-none }
 
 You can declare that a value could have a type, like `str`, but that it could also be `None`.
 
@@ -342,7 +342,7 @@ This also means that in Python 3.10, you can use `Something | None`:
 
 ////
 
-#### Using `Union` or `Optional`
+#### Using `Union` or `Optional` { #using-union-or-optional }
 
 If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:
 
@@ -377,7 +377,7 @@ The good news is, once you are on Python 3.10 you won't have to worry about that
 
 And then you won't have to worry about names like `Optional` and `Union`. 😎
 
-#### Generic types
+#### Generic types { #generic-types }
 
 These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
 
@@ -429,7 +429,7 @@ And the same as with Python 3.8, from the `typing` module:
 
 ////
 
-### Classes as types
+### Classes as types { #classes-as-types }
 
 You can also declare a class as the type of a variable.
 
@@ -449,7 +449,7 @@ Notice that this means "`one_person` is an **instance** of the class `Person`".
 
 It doesn't mean "`one_person` is the **class** called `Person`".
 
-## Pydantic models
+## Pydantic models { #pydantic-models }
 
 <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> is a Python library to perform data validation.
 
@@ -503,7 +503,7 @@ Pydantic has a special behavior when you use `Optional` or `Union[Something, Non
 
 ///
 
-## Type Hints with Metadata Annotations
+## Type Hints with Metadata Annotations { #type-hints-with-metadata-annotations }
 
 Python also has a feature that allows putting **additional <abbr title="Data about the data, in this case, information about the type, e.g. a description.">metadata</abbr>** in these type hints using `Annotated`.
 
@@ -547,7 +547,7 @@ And also that your code will be very compatible with many other Python tools and
 
 ///
 
-## Type hints in **FastAPI**
+## Type hints in **FastAPI** { #type-hints-in-fastapi }
 
 **FastAPI** takes advantage of these type hints to do several things.
 
index 8c7cac43bd825384c5a575162886619896f6bfec..caefdf125469c87ce21945267d77a29a1abdc1e4 100644 (file)
@@ -1,3 +1,3 @@
-# Resources
+# Resources { #resources }
 
 Additional resources, external links, articles and more. ✈️
index 34685fcc40416a2a35bef3a3e2ed9d074cdec12a..6e16410a3eca10001234f4c515c51fa0f97b6eed 100644 (file)
@@ -1,4 +1,4 @@
-# Background Tasks
+# Background Tasks { #background-tasks }
 
 You can define background tasks to be run *after* returning a response.
 
@@ -11,7 +11,7 @@ This includes, for example:
 * 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 the file in the background.
 
-## Using `BackgroundTasks`
+## Using `BackgroundTasks` { #using-backgroundtasks }
 
 First, import `BackgroundTasks` and define a parameter in your *path operation function* with a type declaration of `BackgroundTasks`:
 
@@ -19,7 +19,7 @@ First, import `BackgroundTasks` and define a parameter in your *path operation f
 
 **FastAPI** will create the object of type `BackgroundTasks` for you and pass it as that parameter.
 
-## Create a task function
+## Create a task function { #create-a-task-function }
 
 Create a function to be run as the background task.
 
@@ -33,7 +33,7 @@ And as the write operation doesn't use `async` and `await`, we define the functi
 
 {* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
 
-## Add the background task
+## Add the background task { #add-the-background-task }
 
 Inside of your *path operation function*, pass your task function to the *background tasks* object with the method `.add_task()`:
 
@@ -45,7 +45,7 @@ Inside of your *path operation function*, pass your task function to the *backgr
 * Any sequence of arguments that should be passed to the task function in order (`email`).
 * Any keyword arguments that should be passed to the task function (`message="some notification"`).
 
-## Dependency Injection
+## Dependency Injection { #dependency-injection }
 
 Using `BackgroundTasks` also works with the dependency injection system, you can declare a parameter of type `BackgroundTasks` at multiple levels: in a *path operation function*, in a dependency (dependable), in a sub-dependency, etc.
 
@@ -61,7 +61,7 @@ If there was a query in the request, it will be written to the log in a backgrou
 
 And then another background task generated at the *path operation function* will write a message using the `email` path parameter.
 
-## Technical Details
+## Technical Details { #technical-details }
 
 The class `BackgroundTasks` comes directly from <a href="https://www.starlette.io/background/" class="external-link" target="_blank">`starlette.background`</a>.
 
@@ -73,7 +73,7 @@ It's still possible to use `BackgroundTask` alone in FastAPI, but you have to cr
 
 You can see more details in <a href="https://www.starlette.io/background/" class="external-link" target="_blank">Starlette's official docs for Background Tasks</a>.
 
-## Caveat
+## Caveat { #caveat }
 
 If you need to perform heavy background computation and you don't necessarily need it to be run by the same process (for example, you don't need to share memory, variables, etc), you might benefit from using other bigger tools like <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>.
 
@@ -81,6 +81,6 @@ They tend to require more complex configurations, a message/job queue manager, l
 
 But if you need to access variables and objects from the same **FastAPI** app, or you need to perform small background tasks (like sending an email notification), you can simply just use `BackgroundTasks`.
 
-## Recap
+## Recap { #recap }
 
 Import and use `BackgroundTasks` with parameters in *path operation functions* and dependencies to add background tasks.
index f5f29a173760881565ccf367b881f85d1a6ddc03..74daa54835f055634b11a660bfae5a0a018267cf 100644 (file)
@@ -1,4 +1,4 @@
-# Bigger Applications - Multiple Files
+# Bigger Applications - Multiple Files { #bigger-applications-multiple-files }
 
 If you are building an application or a web API, it's rarely the case that you can put everything in a single file.
 
@@ -10,7 +10,7 @@ If you come from Flask, this would be the equivalent of Flask's Blueprints.
 
 ///
 
-## An example file structure
+## An example file structure { #an-example-file-structure }
 
 Let's say you have a file structure like this:
 
@@ -71,7 +71,7 @@ The same file structure with comments:
 │       └── admin.py     # "admin" submodule, e.g. import app.internal.admin
 ```
 
-## `APIRouter`
+## `APIRouter` { #apirouter }
 
 Let's say the file dedicated to handling just users is the submodule at `/app/routers/users.py`.
 
@@ -81,7 +81,7 @@ But it's still part of the same **FastAPI** application/web API (it's part of th
 
 You can create the *path operations* for that module using `APIRouter`.
 
-### Import `APIRouter`
+### Import `APIRouter` { #import-apirouter }
 
 You import it and create an "instance" the same way you would with the class `FastAPI`:
 
@@ -89,7 +89,7 @@ You import it and create an "instance" the same way you would with the class `Fa
 {!../../docs_src/bigger_applications/app/routers/users.py!}
 ```
 
-### *Path operations* with `APIRouter`
+### *Path operations* with `APIRouter` { #path-operations-with-apirouter }
 
 And then you use it to declare your *path operations*.
 
@@ -113,7 +113,7 @@ In this example, the variable is called `router`, but you can name it however yo
 
 We are going to include this `APIRouter` in the main `FastAPI` app, but first, let's check the dependencies and another `APIRouter`.
 
-## Dependencies
+## Dependencies { #dependencies }
 
 We see that we are going to need some dependencies used in several places of the application.
 
@@ -159,7 +159,7 @@ But in real cases you will get better results using the integrated [Security uti
 
 ///
 
-## Another module with `APIRouter`
+## Another module with `APIRouter` { #another-module-with-apirouter }
 
 Let's say you also have the endpoints dedicated to handling "items" from your application in the module at `app/routers/items.py`.
 
@@ -234,7 +234,7 @@ The `prefix`, `tags`, `responses`, and `dependencies` parameters are (as in many
 
 ///
 
-### Import the dependencies
+### Import the dependencies { #import-the-dependencies }
 
 This code lives in the module `app.routers.items`, the file `app/routers/items.py`.
 
@@ -246,7 +246,7 @@ So we use a relative import with `..` for the dependencies:
 {!../../docs_src/bigger_applications/app/routers/items.py!}
 ```
 
-#### How relative imports work
+#### How relative imports work { #how-relative-imports-work }
 
 /// tip
 
@@ -309,7 +309,7 @@ That would refer to some package above `app/`, with its own file `__init__.py`,
 
 But now you know how it works, so you can use relative imports in your own apps no matter how complex they are. 🤓
 
-### Add some custom `tags`, `responses`, and `dependencies`
+### Add some custom `tags`, `responses`, and `dependencies` { #add-some-custom-tags-responses-and-dependencies }
 
 We are not adding the prefix `/items` nor the `tags=["items"]` to each *path operation* because we added them to the `APIRouter`.
 
@@ -327,7 +327,7 @@ And it will also have both responses in the documentation, one for `404` and one
 
 ///
 
-## The main `FastAPI`
+## The main `FastAPI` { #the-main-fastapi }
 
 Now, let's see the module at `app/main.py`.
 
@@ -337,7 +337,7 @@ This will be the main file in your application that ties everything together.
 
 And as most of your logic will now live in its own specific module, the main file will be quite simple.
 
-### Import `FastAPI`
+### Import `FastAPI` { #import-fastapi }
 
 You import and create a `FastAPI` class as normally.
 
@@ -347,7 +347,7 @@ And we can even declare [global dependencies](dependencies/global-dependencies.m
 {!../../docs_src/bigger_applications/app/main.py!}
 ```
 
-### Import the `APIRouter`
+### Import the `APIRouter` { #import-the-apirouter }
 
 Now we import the other submodules that have `APIRouter`s:
 
@@ -357,7 +357,7 @@ Now we import the other submodules that have `APIRouter`s:
 
 As the files `app/routers/users.py` and `app/routers/items.py` are submodules that are part of the same Python package `app`, we can use a single dot `.` to import them using "relative imports".
 
-### How the importing works
+### How the importing works { #how-the-importing-works }
 
 The section:
 
@@ -399,7 +399,7 @@ To learn more about Python Packages and Modules, read <a href="https://docs.pyth
 
 ///
 
-### Avoid name collisions
+### Avoid name collisions { #avoid-name-collisions }
 
 We are importing the submodule `items` directly, instead of importing just its variable `router`.
 
@@ -420,7 +420,7 @@ So, to be able to use both of them in the same file, we import the submodules di
 {!../../docs_src/bigger_applications/app/main.py!}
 ```
 
-### Include the `APIRouter`s for `users` and `items`
+### Include the `APIRouter`s for `users` and `items` { #include-the-apirouters-for-users-and-items }
 
 Now, let's include the `router`s from the submodules `users` and `items`:
 
@@ -458,7 +458,7 @@ So it won't affect performance. ⚡
 
 ///
 
-### Include an `APIRouter` with a custom `prefix`, `tags`, `responses`, and `dependencies`
+### Include an `APIRouter` with a custom `prefix`, `tags`, `responses`, and `dependencies` { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies }
 
 Now, let's imagine your organization gave you the `app/internal/admin.py` file.
 
@@ -491,7 +491,7 @@ But that will only affect that `APIRouter` in our app, not in any other code tha
 
 So, for example, other projects could use the same `APIRouter` with a different authentication method.
 
-### Include a *path operation*
+### Include a *path operation* { #include-a-path-operation }
 
 We can also add *path operations* directly to the `FastAPI` app.
 
@@ -517,7 +517,7 @@ As we cannot just isolate them and "mount" them independently of the rest, the *
 
 ///
 
-## Check the automatic API docs
+## Check the automatic API docs { #check-the-automatic-api-docs }
 
 Now, run your app:
 
@@ -537,7 +537,7 @@ You will see the automatic API docs, including the paths from all the submodules
 
 <img src="/img/tutorial/bigger-applications/image01.png">
 
-## Include the same router multiple times with different `prefix`
+## Include the same router multiple times with different `prefix` { #include-the-same-router-multiple-times-with-different-prefix }
 
 You can also use `.include_router()` multiple times with the *same* router using different prefixes.
 
@@ -545,7 +545,7 @@ This could be useful, for example, to expose the same API under different prefix
 
 This is an advanced usage that you might not really need, but it's there in case you do.
 
-## Include an `APIRouter` in another
+## Include an `APIRouter` in another { #include-an-apirouter-in-another }
 
 The same way you can include an `APIRouter` in a `FastAPI` application, you can include an `APIRouter` in another `APIRouter` using:
 
index 3ce30cbf6119c95b39dfdd8041416a9fe1228b6e..11d4068480a8bae1bd062b1ef7d62c3f1c113eb5 100644 (file)
@@ -1,8 +1,8 @@
-# Body - Fields
+# Body - Fields { #body-fields }
 
 The same way you can declare additional validation and metadata in *path operation function* parameters with `Query`, `Path` and `Body`, you can declare validation and metadata inside of Pydantic models using Pydantic's `Field`.
 
-## Import `Field`
+## Import `Field` { #import-field }
 
 First, you have to import it:
 
@@ -15,7 +15,7 @@ Notice that `Field` is imported directly from `pydantic`, not from `fastapi` as
 
 ///
 
-## Declare model attributes
+## Declare model attributes { #declare-model-attributes }
 
 You can then use `Field` with model attributes:
 
@@ -41,7 +41,7 @@ Notice how each model's attribute with a type, default value and `Field` has the
 
 ///
 
-## Add extra information
+## Add extra information { #add-extra-information }
 
 You can declare extra information in `Field`, `Query`, `Body`, etc. And it will be included in the generated JSON Schema.
 
@@ -54,7 +54,7 @@ As these keys may not necessarily be part of the OpenAPI specification, some Ope
 
 ///
 
-## Recap
+## Recap { #recap }
 
 You can use Pydantic's `Field` to declare extra validations and metadata for model attributes.
 
index 71b308bb4ae2d891e462214bb12efa349fd232d9..ab6d7461a7d5cf5c10500043a7d6d5ca97bb036e 100644 (file)
@@ -1,8 +1,8 @@
-# Body - Multiple Parameters
+# Body - Multiple Parameters { #body-multiple-parameters }
 
 Now that we have seen how to use `Path` and `Query`, let's see more advanced uses of request body declarations.
 
-## Mix `Path`, `Query` and body parameters
+## Mix `Path`, `Query` and body parameters { #mix-path-query-and-body-parameters }
 
 First, of course, you can mix `Path`, `Query` and request body parameter declarations freely and **FastAPI** will know what to do.
 
@@ -16,7 +16,7 @@ Notice that, in this case, the `item` that would be taken from the body is optio
 
 ///
 
-## Multiple body parameters
+## Multiple body parameters { #multiple-body-parameters }
 
 In the previous example, the *path operations* would expect a JSON body with the attributes of an `Item`, like:
 
@@ -63,7 +63,7 @@ Notice that even though the `item` was declared the same way as before, it is no
 
 It will perform the validation of the compound data, and will document it like that for the OpenAPI schema and automatic docs.
 
-## Singular values in body
+## Singular values in body { #singular-values-in-body }
 
 The same way there is a `Query` and `Path` to define extra data for query and path parameters, **FastAPI** provides an equivalent `Body`.
 
@@ -96,7 +96,7 @@ In this case, **FastAPI** will expect a body like:
 
 Again, it will convert the data types, validate, document, etc.
 
-## Multiple body params and query
+## Multiple body params and query { #multiple-body-params-and-query }
 
 Of course, you can also declare additional query parameters whenever you need, additional to any body parameters.
 
@@ -123,7 +123,7 @@ For example:
 
 ///
 
-## Embed a single body parameter
+## Embed a single body parameter { #embed-a-single-body-parameter }
 
 Let's say you only have a single `item` body parameter from a Pydantic model `Item`.
 
@@ -164,7 +164,7 @@ instead of:
 }
 ```
 
-## Recap
+## Recap { #recap }
 
 You can add multiple body parameters to your *path operation function*, even though a request can only have a single body.
 
index b473062de6633b3f60e72b321d1b24e85dea4f73..445235a42030baf8d4932355ab3662ad8b4f4006 100644 (file)
@@ -1,8 +1,8 @@
-# Body - Nested Models
+# Body - Nested Models { #body-nested-models }
 
 With **FastAPI**, you can define, validate, document, and use arbitrarily deeply nested models (thanks to Pydantic).
 
-## List fields
+## List fields { #list-fields }
 
 You can define an attribute to be a subtype. For example, a Python `list`:
 
@@ -10,11 +10,11 @@ You can define an attribute to be a subtype. For example, a Python `list`:
 
 This will make `tags` be a list, although it doesn't declare the type of the elements of the list.
 
-## List fields with type parameter
+## List fields with type parameter { #list-fields-with-type-parameter }
 
 But Python has a specific way to declare lists with internal types, or "type parameters":
 
-### Import typing's `List`
+### Import typing's `List` { #import-typings-list }
 
 In Python 3.9 and above you can use the standard `list` to declare these type annotations as we'll see below. 💡
 
@@ -22,7 +22,7 @@ But in Python versions before 3.9 (3.6 and above), you first need to import `Lis
 
 {* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
 
-### Declare a `list` with a type parameter
+### Declare a `list` with a type parameter { #declare-a-list-with-a-type-parameter }
 
 To declare types that have type parameters (internal types), like `list`, `dict`, `tuple`:
 
@@ -51,7 +51,7 @@ So, in our example, we can make `tags` be specifically a "list of strings":
 
 {* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *}
 
-## Set types
+## Set types { #set-types }
 
 But then we think about it, and realize that tags shouldn't repeat, they would probably be unique strings.
 
@@ -67,7 +67,7 @@ And whenever you output that data, even if the source had duplicates, it will be
 
 And it will be annotated / documented accordingly too.
 
-## Nested Models
+## Nested Models { #nested-models }
 
 Each attribute of a Pydantic model has a type.
 
@@ -77,13 +77,13 @@ So, you can declare deeply nested JSON "objects" with specific attribute names,
 
 All that, arbitrarily nested.
 
-### Define a submodel
+### Define a submodel { #define-a-submodel }
 
 For example, we can define an `Image` model:
 
 {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *}
 
-### Use the submodel as a type
+### Use the submodel as a type { #use-the-submodel-as-a-type }
 
 And then we can use it as the type of an attribute:
 
@@ -112,7 +112,7 @@ Again, doing just that declaration, with **FastAPI** you get:
 * Data validation
 * Automatic documentation
 
-## Special types and validation
+## Special types and validation { #special-types-and-validation }
 
 Apart from normal singular types like `str`, `int`, `float`, etc. you can use more complex singular types that inherit from `str`.
 
@@ -124,7 +124,7 @@ For example, as in the `Image` model we have a `url` field, we can declare it to
 
 The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
 
-## Attributes with lists of submodels
+## Attributes with lists of submodels { #attributes-with-lists-of-submodels }
 
 You can also use Pydantic models as subtypes of `list`, `set`, etc.:
 
@@ -162,7 +162,7 @@ Notice how the `images` key now has a list of image objects.
 
 ///
 
-## Deeply nested models
+## Deeply nested models { #deeply-nested-models }
 
 You can define arbitrarily deeply nested models:
 
@@ -174,7 +174,7 @@ Notice how `Offer` has a list of `Item`s, which in turn have an optional list of
 
 ///
 
-## Bodies of pure lists
+## Bodies of pure lists { #bodies-of-pure-lists }
 
 If the top level value of the JSON body you expect is a JSON `array` (a Python `list`), you can declare the type in the parameter of the function, the same as in Pydantic models:
 
@@ -192,7 +192,7 @@ as in:
 
 {* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
 
-## Editor support everywhere
+## Editor support everywhere { #editor-support-everywhere }
 
 And you get editor support everywhere.
 
@@ -204,7 +204,7 @@ You couldn't get this kind of editor support if you were working directly with `
 
 But you don't have to worry about them either, incoming dicts are converted automatically and your output is converted automatically to JSON too.
 
-## Bodies of arbitrary `dict`s
+## Bodies of arbitrary `dict`s { #bodies-of-arbitrary-dicts }
 
 You can also declare a body as a `dict` with keys of some type and values of some other type.
 
@@ -234,7 +234,7 @@ And the `dict` you receive as `weights` will actually have `int` keys and `float
 
 ///
 
-## Recap
+## Recap { #recap }
 
 With **FastAPI** you have the maximum flexibility provided by Pydantic models, while keeping your code simple, short and elegant.
 
index df5b960db6f3344c72385a7dadea32aceecd0d01..baeb53ec6f4d1a95a71db0be58453781cc7792d1 100644 (file)
@@ -1,6 +1,6 @@
-# Body - Updates
+# Body - Updates { #body-updates }
 
-## Update replacing with `PUT`
+## Update replacing with `PUT` { #update-replacing-with-put }
 
 To update an item you can use the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a> operation.
 
@@ -10,7 +10,7 @@ You can use the `jsonable_encoder` to convert the input data to data that can be
 
 `PUT` is used to receive data that should replace the existing data.
 
-### Warning about replacing
+### Warning about replacing { #warning-about-replacing }
 
 That means that if you want to update the item `bar` using `PUT` with a body containing:
 
@@ -26,7 +26,7 @@ because it doesn't include the already stored attribute `"tax": 20.2`, the input
 
 And the data would be saved with that "new" `tax` of `10.5`.
 
-## Partial updates with `PATCH`
+## Partial updates with `PATCH` { #partial-updates-with-patch }
 
 You can also use the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> operation to *partially* update data.
 
@@ -44,7 +44,7 @@ But this guide shows you, more or less, how they are intended to be used.
 
 ///
 
-### Using Pydantic's `exclude_unset` parameter
+### Using Pydantic's `exclude_unset` parameter { #using-pydantics-exclude-unset-parameter }
 
 If you want to receive partial updates, it's very useful to use the parameter `exclude_unset` in Pydantic's model's `.model_dump()`.
 
@@ -64,7 +64,7 @@ Then you can use this to generate a `dict` with only the data that was set (sent
 
 {* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
 
-### Using Pydantic's `update` parameter
+### Using Pydantic's `update` parameter { #using-pydantics-update-parameter }
 
 Now, you can create a copy of the existing model using `.model_copy()`, and pass the `update` parameter with a `dict` containing the data to update.
 
@@ -80,7 +80,7 @@ Like `stored_item_model.model_copy(update=update_data)`:
 
 {* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
 
-### Partial updates recap
+### Partial updates recap { #partial-updates-recap }
 
 In summary, to apply partial updates you would:
 
index aba5593a5943a77fa32ea47cff557bbaa5431c5f..58e20f4c96f2202c9d5d22bf7757993e8b9c2c00 100644 (file)
@@ -1,4 +1,4 @@
-# Request Body
+# Request Body { #request-body }
 
 When you need to send data from a client (let's say, a browser) to your API, you send it as a **request body**.
 
@@ -18,13 +18,13 @@ As it is discouraged, the interactive docs with Swagger UI won't show the docume
 
 ///
 
-## Import Pydantic's `BaseModel`
+## Import Pydantic's `BaseModel` { #import-pydantics-basemodel }
 
 First, you need to import `BaseModel` from `pydantic`:
 
 {* ../../docs_src/body/tutorial001_py310.py hl[2] *}
 
-## Create your data model
+## Create your data model { #create-your-data-model }
 
 Then you declare your data model as a class that inherits from `BaseModel`.
 
@@ -55,7 +55,7 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
 }
 ```
 
-## Declare it as a parameter
+## Declare it as a parameter { #declare-it-as-a-parameter }
 
 To add it to your *path operation*, declare it the same way you declared path and query parameters:
 
@@ -63,7 +63,7 @@ To add it to your *path operation*, declare it the same way you declared path an
 
 ...and declare its type as the model you created, `Item`.
 
-## Results
+## Results { #results }
 
 With just that Python type declaration, **FastAPI** will:
 
@@ -76,7 +76,7 @@ With just that Python type declaration, **FastAPI** will:
 * Generate <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> definitions for your model, you can also use them anywhere else you like if it makes sense for your project.
 * Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentation <abbr title="User Interfaces">UIs</abbr>.
 
-## Automatic docs
+## Automatic docs { #automatic-docs }
 
 The JSON Schemas of your models will be part of your OpenAPI generated schema, and will be shown in the interactive API docs:
 
@@ -86,7 +86,7 @@ And will also be used in the API docs inside each *path operation* that needs th
 
 <img src="/img/tutorial/body/image02.png">
 
-## Editor support
+## Editor support { #editor-support }
 
 In your editor, inside your function you will get type hints and completion everywhere (this wouldn't happen if you received a `dict` instead of a Pydantic model):
 
@@ -122,13 +122,13 @@ It improves editor support for Pydantic models, with:
 
 ///
 
-## Use the model
+## Use the model { #use-the-model }
 
 Inside of the function, you can access all the attributes of the model object directly:
 
 {* ../../docs_src/body/tutorial002_py310.py *}
 
-## Request body + path parameters
+## Request body + path parameters { #request-body-path-parameters }
 
 You can declare path parameters and request body at the same time.
 
@@ -137,7 +137,7 @@ You can declare path parameters and request body at the same time.
 {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
 
 
-## Request body + path + query parameters
+## Request body + path + query parameters { #request-body-path-query-parameters }
 
 You can also declare **body**, **path** and **query** parameters, all at the same time.
 
@@ -161,6 +161,6 @@ But adding the type annotations will allow your editor to give you better suppor
 
 ///
 
-## Without Pydantic
+## Without Pydantic { #without-pydantic }
 
 If you don't want to use Pydantic models, you can also use **Body** parameters. See the docs for [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
index 55a812852ed0ec9b25216decc871fecf55aa7e3b..96dc5cf3d877d24229be086c618f92baebfba456 100644 (file)
@@ -1,4 +1,4 @@
-# Cookie Parameter Models
+# Cookie Parameter Models { #cookie-parameter-models }
 
 If you have a group of **cookies** that are related, you can create a **Pydantic model** to declare them. 🍪
 
@@ -16,7 +16,7 @@ This same technique applies to `Query`, `Cookie`, and `Header`. 😎
 
 ///
 
-## Cookies with a Pydantic Model
+## Cookies with a Pydantic Model { #cookies-with-a-pydantic-model }
 
 Declare the **cookie** parameters that you need in a **Pydantic model**, and then declare the parameter as `Cookie`:
 
@@ -24,7 +24,7 @@ Declare the **cookie** parameters that you need in a **Pydantic model**, and the
 
 **FastAPI** will **extract** the data for **each field** from the **cookies** received in the request and give you the Pydantic model you defined.
 
-## Check the Docs
+## Check the Docs { #check-the-docs }
 
 You can see the defined cookies in the docs UI at `/docs`:
 
@@ -42,7 +42,7 @@ But even if you **fill the data** and click "Execute", because the docs UI works
 
 ///
 
-## Forbid Extra Cookies
+## Forbid Extra Cookies { #forbid-extra-cookies }
 
 In some special use cases (probably not very common), you might want to **restrict** the cookies that you want to receive.
 
@@ -71,6 +71,6 @@ For example, if the client tries to send a `santa_tracker` cookie with a value o
 }
 ```
 
-## Summary
+## Summary { #summary }
 
 You can use **Pydantic models** to declare <abbr title="Have a last cookie before you go. 🍪">**cookies**</abbr> in **FastAPI**. 😎
index 5341406d51cf186091b02edaf83ff152f971cb36..7680f21f494ff8b826498c16c053f30c5cc91deb 100644 (file)
@@ -1,14 +1,14 @@
-# Cookie Parameters
+# Cookie Parameters { #cookie-parameters }
 
 You can define Cookie parameters the same way you define `Query` and `Path` parameters.
 
-## Import `Cookie`
+## Import `Cookie` { #import-cookie }
 
 First import `Cookie`:
 
 {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *}
 
-## Declare `Cookie` parameters
+## Declare `Cookie` parameters { #declare-cookie-parameters }
 
 Then declare the cookie parameters using the same structure as with `Path` and `Query`.
 
@@ -30,6 +30,6 @@ To declare cookies, you need to use `Cookie`, because otherwise the parameters w
 
 ///
 
-## Recap
+## Recap { #recap }
 
 Declare cookies with `Cookie`, using the same common pattern as `Query` and `Path`.
index 5ca4437b34ba1deb2631b0398e434bbc298aac14..e3de37b43c0a94673d9c2e2f9c1438f7c8d18e5d 100644 (file)
@@ -1,8 +1,8 @@
-# CORS (Cross-Origin Resource Sharing)
+# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing }
 
 <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORS or "Cross-Origin Resource Sharing"</a> refers to the situations when a frontend running in a browser has JavaScript code that communicates with a backend, and the backend is in a different "origin" than the frontend.
 
-## Origin
+## Origin { #origin }
 
 An origin is the combination of protocol (`http`, `https`), domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`), and port (`80`, `443`, `8080`).
 
@@ -14,7 +14,7 @@ So, all these are different origins:
 
 Even if they are all in `localhost`, they use different protocols or ports, so, they are different "origins".
 
-## Steps
+## Steps { #steps }
 
 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`).
 
@@ -24,7 +24,7 @@ To achieve this, the `:80`-backend must have a list of "allowed origins".
 
 In this case, the list would have to include `http://localhost:8080` for the `:8080`-frontend to work correctly.
 
-## Wildcards
+## Wildcards { #wildcards }
 
 It's also possible to declare the list as `"*"` (a "wildcard") to say that all are allowed.
 
@@ -32,7 +32,7 @@ But that will only allow certain types of communication, excluding everything th
 
 So, for everything to work correctly, it's better to specify explicitly the allowed origins.
 
-## Use `CORSMiddleware`
+## Use `CORSMiddleware` { #use-corsmiddleware }
 
 You can configure it in your **FastAPI** application using the `CORSMiddleware`.
 
@@ -66,17 +66,17 @@ The following arguments are supported:
 
 The middleware responds to two particular types of HTTP request...
 
-### CORS preflight requests
+### CORS preflight requests { #cors-preflight-requests }
 
 These are any `OPTIONS` request with `Origin` and `Access-Control-Request-Method` headers.
 
 In this case the middleware will intercept the incoming request and respond with appropriate CORS headers, and either a `200` or `400` response for informational purposes.
 
-### Simple requests
+### Simple requests { #simple-requests }
 
 Any request with an `Origin` header. In this case the middleware will pass the request through as normal, but will include appropriate CORS headers on the response.
 
-## More info
+## More info { #more-info }
 
 For more info about <abbr title="Cross-Origin Resource Sharing">CORS</abbr>, check the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS documentation</a>.
 
index 90dd908f783bb28b2976435d1622a4a8cd3f51b2..a096763f05b1e33f35ebc0cd3c610ecfbb529d0c 100644 (file)
@@ -1,14 +1,14 @@
-# Debugging
+# Debugging { #debugging }
 
 You can connect the debugger in your editor, for example with Visual Studio Code or PyCharm.
 
-## Call `uvicorn`
+## Call `uvicorn` { #call-uvicorn }
 
 In your FastAPI application, import and run `uvicorn` directly:
 
 {* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
 
-### About `__name__ == "__main__"`
+### About `__name__ == "__main__"` { #about-name-main }
 
 The main purpose of the `__name__ == "__main__"` is to have some code that is executed when your file is called with:
 
@@ -26,7 +26,7 @@ but is not called when another file imports it, like in:
 from myapp import app
 ```
 
-#### More details
+#### More details { #more-details }
 
 Let's say your file is named `myapp.py`.
 
@@ -78,7 +78,7 @@ For more information, check <a href="https://docs.python.org/3/library/__main__.
 
 ///
 
-## Run your code with your debugger
+## Run your code with your debugger { #run-your-code-with-your-debugger }
 
 Because you are running the Uvicorn server directly from your code, you can call your Python program (your FastAPI application) directly from the debugger.
 
index 9c7bb1fd3818fdbd74edcce9700f40db0e55200c..686a5632e2f74130dc66b72a137f4f8d5220d6e1 100644 (file)
@@ -1,8 +1,8 @@
-# Classes as Dependencies
+# Classes as Dependencies { #classes-as-dependencies }
 
 Before diving deeper into the **Dependency Injection** system, let's upgrade the previous example.
 
-## A `dict` from the previous example
+## A `dict` from the previous example { #a-dict-from-the-previous-example }
 
 In the previous example, we were returning a `dict` from our dependency ("dependable"):
 
@@ -14,7 +14,7 @@ And we know that editors can't provide a lot of support (like completion) for `d
 
 We can do better...
 
-## What makes a dependency
+## What makes a dependency { #what-makes-a-dependency }
 
 Up to now you have seen dependencies declared as functions.
 
@@ -38,7 +38,7 @@ something(some_argument, some_keyword_argument="foo")
 
 then it is a "callable".
 
-## Classes as dependencies
+## Classes as dependencies { #classes-as-dependencies_1 }
 
 You might notice that to create an instance of a Python class, you use that same syntax.
 
@@ -89,7 +89,7 @@ In both cases, it will have:
 
 In both cases the data will be converted, validated, documented on the OpenAPI schema, etc.
 
-## Use it
+## Use it { #use-it }
 
 Now you can declare your dependency using this class.
 
@@ -97,7 +97,7 @@ Now you can declare your dependency using this class.
 
 **FastAPI** calls the `CommonQueryParams` class. This creates an "instance" of that class and the instance will be passed as the parameter `commons` to your function.
 
-## Type annotation vs `Depends`
+## Type annotation vs `Depends` { #type-annotation-vs-depends }
 
 Notice how we write `CommonQueryParams` twice in the above code:
 
@@ -193,7 +193,7 @@ But declaring the type is encouraged as that way your editor will know what will
 
 <img src="/img/tutorial/dependencies/image02.png">
 
-## Shortcut
+## Shortcut { #shortcut }
 
 But you see that we are having some code repetition here, writing `CommonQueryParams` twice:
 
index 88ad99403db857997f4e6d19d345df7ca7720428..2e3f04dff089a3a661236b1769789be8636570e7 100644 (file)
@@ -1,4 +1,4 @@
-# Dependencies in path operation decorators
+# Dependencies in path operation decorators { #dependencies-in-path-operation-decorators }
 
 In some cases you don't really need the return value of a dependency inside your *path operation function*.
 
@@ -8,7 +8,7 @@ But you still need it to be executed/solved.
 
 For those cases, instead of declaring a *path operation function* parameter with `Depends`, you can add a `list` of `dependencies` to the *path operation decorator*.
 
-## Add `dependencies` to the *path operation decorator*
+## Add `dependencies` to the *path operation decorator* { #add-dependencies-to-the-path-operation-decorator }
 
 The *path operation decorator* receives an optional argument `dependencies`.
 
@@ -36,23 +36,23 @@ But in real cases, when implementing security, you would get more benefits from
 
 ///
 
-## Dependencies errors and return values
+## Dependencies errors and return values { #dependencies-errors-and-return-values }
 
 You can use the same dependency *functions* you use normally.
 
-### Dependency requirements
+### Dependency requirements { #dependency-requirements }
 
 They can declare request requirements (like headers) or other sub-dependencies:
 
 {* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
 
-### Raise exceptions
+### Raise exceptions { #raise-exceptions }
 
 These dependencies can `raise` exceptions, the same as normal dependencies:
 
 {* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
 
-### Return values
+### Return values { #return-values }
 
 And they can return values or not, the values won't be used.
 
@@ -60,10 +60,10 @@ So, you can reuse a normal dependency (that returns a value) you already use som
 
 {* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
 
-## Dependencies for a group of *path operations*
+## Dependencies for a group of *path operations* { #dependencies-for-a-group-of-path-operations }
 
 Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
 
-## Global Dependencies
+## Global Dependencies { #global-dependencies }
 
 Next we will see how to add dependencies to the whole `FastAPI` application, so that they apply to each *path operation*.
index 2b97ba39ea501466d9ef2e54c3c46c6e5bf72ef0..2e2a6a8e3b8e1448040ededba1fc04d10f893658 100644 (file)
@@ -1,4 +1,4 @@
-# Dependencies with yield
+# Dependencies with yield { #dependencies-with-yield }
 
 FastAPI supports dependencies that do some <abbr title='sometimes also called "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code", etc.'>extra steps after finishing</abbr>.
 
@@ -23,7 +23,7 @@ In fact, FastAPI uses those two decorators internally.
 
 ///
 
-## A database dependency with `yield`
+## A database dependency with `yield` { #a-database-dependency-with-yield }
 
 For example, you could use this to create a database session and close it after finishing.
 
@@ -47,7 +47,7 @@ You can use `async` or regular functions.
 
 ///
 
-## A dependency with `yield` and `try`
+## A dependency with `yield` and `try` { #a-dependency-with-yield-and-try }
 
 If you use a `try` block in a dependency with `yield`, you'll receive any exception that was thrown when using the dependency.
 
@@ -59,7 +59,7 @@ In the same way, you can use `finally` to make sure the exit steps are executed,
 
 {* ../../docs_src/dependencies/tutorial007.py hl[3,5] *}
 
-## Sub-dependencies with `yield`
+## Sub-dependencies with `yield` { #sub-dependencies-with-yield }
 
 You can have sub-dependencies and "trees" of sub-dependencies of any size and shape, and any or all of them can use `yield`.
 
@@ -93,7 +93,7 @@ This works thanks to Python's <a href="https://docs.python.org/3/library/context
 
 ///
 
-## Dependencies with `yield` and `HTTPException`
+## Dependencies with `yield` and `HTTPException` { #dependencies-with-yield-and-httpexception }
 
 You saw that you can use dependencies with `yield` and have `try` blocks that catch exceptions.
 
@@ -111,7 +111,7 @@ But it's there for you if you need it. 🤓
 
 An alternative you could use to catch exceptions (and possibly also raise another `HTTPException`) is to create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
 
-## Dependencies with `yield` and `except`
+## Dependencies with `yield` and `except` { #dependencies-with-yield-and-except }
 
 If you catch an exception using `except` in a dependency with `yield` and you don't raise it again (or raise a new exception), FastAPI won't be able to notice there was an exception, the same way that would happen with regular Python:
 
@@ -119,7 +119,7 @@ If you catch an exception using `except` in a dependency with `yield` and you do
 
 In this case, the client will see an *HTTP 500 Internal Server Error* response as it should, given that we are not raising an `HTTPException` or similar, but the server will **not have any logs** or any other indication of what was the error. 😱
 
-### Always `raise` in Dependencies with `yield` and `except`
+### Always `raise` in Dependencies with `yield` and `except` { #always-raise-in-dependencies-with-yield-and-except }
 
 If you catch an exception in a dependency with `yield`, unless you are raising another `HTTPException` or similar, you should re-raise the original exception.
 
@@ -129,7 +129,7 @@ You can re-raise the same exception using `raise`:
 
 Now the client will get the same *HTTP 500 Internal Server Error* response, but the server will have our custom `InternalError` in the logs. 😎
 
-## Execution of dependencies with `yield`
+## Execution of dependencies with `yield` { #execution-of-dependencies-with-yield }
 
 The sequence of execution is more or less like this diagram. Time flows from top to bottom. And each column is one of the parts interacting or executing code.
 
@@ -184,7 +184,7 @@ If you raise any exception, it will be passed to the dependencies with yield, in
 
 ///
 
-## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks
+## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
 
 /// warning
 
@@ -194,13 +194,13 @@ These details are useful mainly if you were using a version of FastAPI prior to
 
 ///
 
-### Dependencies with `yield` and `except`, Technical Details
+### Dependencies with `yield` and `except`, Technical Details { #dependencies-with-yield-and-except-technical-details }
 
 Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler.
 
 This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code.
 
-### Background Tasks and Dependencies with `yield`, Technical Details
+### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details }
 
 Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
 
@@ -220,9 +220,9 @@ If you used to rely on this behavior, now you should create the resources for ba
 
 For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.
 
-## Context Managers
+## Context Managers { #context-managers }
 
-### What are "Context Managers"
+### What are "Context Managers" { #what-are-context-managers }
 
 "Context Managers" are any of those Python objects that you can use in a `with` statement.
 
@@ -240,7 +240,7 @@ When the `with` block finishes, it makes sure to close the file, even if there w
 
 When you create a dependency with `yield`, **FastAPI** will internally create a context manager for it, and combine it with some other related tools.
 
-### Using context managers in dependencies with `yield`
+### Using context managers in dependencies with `yield` { #using-context-managers-in-dependencies-with-yield }
 
 /// warning
 
index e4696ee146681795e0c6fab9d847265f1f05e73a..5814397e53ddba519b707349227dbbdd28496964 100644 (file)
@@ -1,4 +1,4 @@
-# Global Dependencies
+# Global Dependencies { #global-dependencies }
 
 For some types of applications you might want to add dependencies to the whole application.
 
@@ -11,6 +11,6 @@ In that case, they will be applied to all the *path operations* in the applicati
 
 And all the ideas in the section about [adding `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} still apply, but in this case, to all of the *path operations* in the app.
 
-## Dependencies for groups of *path operations*
+## Dependencies for groups of *path operations* { #dependencies-for-groups-of-path-operations }
 
 Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
index 596ce159961c61429b2411f673919dd924026c6f..d1116b2be00dd2e1807252f0c43c533e1971359d 100644 (file)
@@ -1,10 +1,10 @@
-# Dependencies
+# Dependencies { #dependencies }
 
 **FastAPI** has a very powerful but intuitive **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
 
 It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
 
-## What is "Dependency Injection"
+## What is "Dependency Injection" { #what-is-dependency-injection }
 
 **"Dependency Injection"** means, in programming, that there is a way for your code (in this case, your *path operation functions*) to declare things that it requires to work and use: "dependencies".
 
@@ -19,13 +19,13 @@ This is very useful when you need to:
 
 All these, while minimizing code repetition.
 
-## First Steps
+## First Steps { #first-steps }
 
 Let's see a very simple example. It will be so simple that it is not very useful, for now.
 
 But this way we can focus on how the **Dependency Injection** system works.
 
-### Create a dependency, or "dependable"
+### Create a dependency, or "dependable" { #create-a-dependency-or-dependable }
 
 Let's first focus on the dependency.
 
@@ -61,11 +61,11 @@ Make sure you [Upgrade the FastAPI version](../../deployment/versions.md#upgradi
 
 ///
 
-### Import `Depends`
+### Import `Depends` { #import-depends }
 
 {* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *}
 
-### Declare the dependency, in the "dependant"
+### Declare the dependency, in the "dependant" { #declare-the-dependency-in-the-dependant }
 
 The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
 
@@ -114,7 +114,7 @@ You just pass it to `Depends` and **FastAPI** knows how to do the rest.
 
 ///
 
-## Share `Annotated` dependencies
+## Share `Annotated` dependencies { #share-annotated-dependencies }
 
 In the examples above, you see that there's a tiny bit of **code duplication**.
 
@@ -140,7 +140,7 @@ The dependencies will keep working as expected, and the **best part** is that th
 
 This will be especially useful when you use it in a **large code base** where you use **the same dependencies** over and over again in **many *path operations***.
 
-## To `async` or not to `async`
+## To `async` or not to `async` { #to-async-or-not-to-async }
 
 As dependencies will also be called by **FastAPI** (the same as your *path operation functions*), the same rules apply while defining your functions.
 
@@ -156,7 +156,7 @@ If you don't know, check the [Async: *"In a hurry?"*](../../async.md#in-a-hurry)
 
 ///
 
-## Integrated with OpenAPI
+## Integrated with OpenAPI { #integrated-with-openapi }
 
 All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
 
@@ -164,7 +164,7 @@ So, the interactive docs will have all the information from these dependencies t
 
 <img src="/img/tutorial/dependencies/image01.png">
 
-## Simple usage
+## Simple usage { #simple-usage }
 
 If you look at it, *path operation functions* are declared to be used whenever a *path* and *operation* matches, and then **FastAPI** takes care of calling the function with the correct parameters, extracting the data from the request.
 
@@ -182,7 +182,7 @@ Other common terms for this same idea of "dependency injection" are:
 * injectables
 * components
 
-## **FastAPI** plug-ins
+## **FastAPI** plug-ins { #fastapi-plug-ins }
 
 Integrations and "plug-ins" can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your *path operation functions*.
 
@@ -190,7 +190,7 @@ And dependencies can be created in a very simple and intuitive way that allows y
 
 You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
 
-## **FastAPI** compatibility
+## **FastAPI** compatibility { #fastapi-compatibility }
 
 The simplicity of the dependency injection system makes **FastAPI** compatible with:
 
@@ -203,7 +203,7 @@ The simplicity of the dependency injection system makes **FastAPI** compatible w
 * response data injection systems
 * etc.
 
-## Simple and Powerful
+## Simple and Powerful { #simple-and-powerful }
 
 Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
 
@@ -243,7 +243,7 @@ admin_user --> activate_user
 paying_user --> pro_items
 ```
 
-## Integrated with **OpenAPI**
+## Integrated with **OpenAPI** { #integrated-with-openapi_1 }
 
 All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your *path operations*.
 
index 1f8ba420a1cb91eee5d29733fd811835a3a3c638..d5dc90bef38421fcf2cf07b81afd67c815a2054e 100644 (file)
@@ -1,4 +1,4 @@
-# Sub-dependencies
+# Sub-dependencies { #sub-dependencies }
 
 You can create dependencies that have **sub-dependencies**.
 
@@ -6,7 +6,7 @@ They can be as **deep** as you need them to be.
 
 **FastAPI** will take care of solving them.
 
-## First dependency "dependable"
+## First dependency "dependable" { #first-dependency-dependable }
 
 You could create a first dependency ("dependable") like:
 
@@ -16,7 +16,7 @@ It declares an optional query parameter `q` as a `str`, and then it just returns
 
 This is quite simple (not very useful), but will help us focus on how the sub-dependencies work.
 
-## Second dependency, "dependable" and "dependant"
+## Second dependency, "dependable" and "dependant" { #second-dependency-dependable-and-dependant }
 
 Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
 
@@ -29,7 +29,7 @@ Let's focus on the parameters declared:
 * It also declares an optional `last_query` cookie, as a `str`.
     * If the user didn't provide any query `q`, we use the last query used, which we saved to a cookie before.
 
-## Use the dependency
+## Use the dependency { #use-the-dependency }
 
 Then we can use the dependency with:
 
@@ -54,7 +54,7 @@ read_query["/items/"]
 query_extractor --> query_or_cookie_extractor --> read_query
 ```
 
-## Using the same dependency multiple times
+## Using the same dependency multiple times { #using-the-same-dependency-multiple-times }
 
 If one of your dependencies is declared multiple times for the same *path operation*, for example, multiple dependencies have a common sub-dependency, **FastAPI** will know to call that sub-dependency only once per request.
 
@@ -86,7 +86,7 @@ async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False
 
 ////
 
-## Recap
+## Recap { #recap }
 
 Apart from all the fancy words used here, the **Dependency Injection** system is quite simple.
 
index e2eceafcc10372710a1fba83f873bc1a89334fe0..17982e9d795b41a5efd8f0da0d06a89670f2222a 100644 (file)
@@ -1,4 +1,4 @@
-# JSON Compatible Encoder
+# JSON Compatible Encoder { #json-compatible-encoder }
 
 There are some cases where you might need to convert a data type (like a Pydantic model) to something compatible with JSON (like a `dict`, `list`, etc).
 
@@ -6,7 +6,7 @@ For example, if you need to store it in a database.
 
 For that, **FastAPI** provides a `jsonable_encoder()` function.
 
-## Using the `jsonable_encoder`
+## Using the `jsonable_encoder` { #using-the-jsonable-encoder }
 
 Let's imagine that you have a database `fake_db` that only receives JSON compatible data.
 
index eb7ccd91d78b816eb11a479d16f34f78db6e0459..a41f7c5fc450d93b876d405e9bcf0cb8d35e07ea 100644 (file)
@@ -1,4 +1,4 @@
-# Extra Data Types
+# Extra Data Types { #extra-data-types }
 
 Up to now, you have been using common data types, like:
 
@@ -17,7 +17,7 @@ And you will still have the same features as seen up to now:
 * Data validation.
 * Automatic annotation and documentation.
 
-## Other data types
+## Other data types { #other-data-types }
 
 Here are some of the additional data types you can use:
 
@@ -51,7 +51,7 @@ Here are some of the additional data types you can use:
     * 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>.
 
-## Example
+## Example { #example }
 
 Here's an example *path operation* with parameters using some of the above types.
 
index ed1590ece1beeb732210f740336a0b7e7fbbbd81..7079bf73daf97fede600ae7449194b526490dab3 100644 (file)
@@ -1,4 +1,4 @@
-# Extra Models
+# Extra Models { #extra-models }
 
 Continuing with the previous example, it will be common to have more than one related model.
 
@@ -16,7 +16,7 @@ If you don't know, you will learn what a "password hash" is in the [security cha
 
 ///
 
-## Multiple models
+## Multiple models { #multiple-models }
 
 Here's a general idea of how the models could look like with their password fields and the places where they are used:
 
@@ -31,9 +31,9 @@ The examples here use `.dict()` for compatibility with Pydantic v1, but you shou
 
 ///
 
-### About `**user_in.dict()`
+### About `**user_in.dict()` { #about-user-in-dict }
 
-#### Pydantic's `.dict()`
+#### Pydantic's `.dict()` { #pydantics-dict }
 
 `user_in` is a Pydantic model of class `UserIn`.
 
@@ -70,7 +70,7 @@ we would get a Python `dict` with:
 }
 ```
 
-#### Unpacking a `dict`
+#### Unpacking a `dict` { #unpacking-a-dict }
 
 If we take a `dict` like `user_dict` and pass it to a function (or class) with `**user_dict`, Python will "unpack" it. It will pass the keys and values of the `user_dict` directly as key-value arguments.
 
@@ -102,7 +102,7 @@ UserInDB(
 )
 ```
 
-#### A Pydantic model from the contents of another
+#### A Pydantic model from the contents of another { #a-pydantic-model-from-the-contents-of-another }
 
 As in the example above we got `user_dict` from `user_in.dict()`, this code:
 
@@ -121,7 +121,7 @@ UserInDB(**user_in.dict())
 
 So, we get a Pydantic model from the data in another Pydantic model.
 
-#### Unpacking a `dict` and extra keywords
+#### Unpacking a `dict` and extra keywords { #unpacking-a-dict-and-extra-keywords }
 
 And then adding the extra keyword argument `hashed_password=hashed_password`, like in:
 
@@ -147,7 +147,7 @@ The supporting additional functions `fake_password_hasher` and `fake_save_user`
 
 ///
 
-## Reduce duplication
+## Reduce duplication { #reduce-duplication }
 
 Reducing code duplication is one of the core ideas in **FastAPI**.
 
@@ -165,7 +165,7 @@ That way, we can declare just the differences between the models (with plaintext
 
 {* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *}
 
-## `Union` or `anyOf`
+## `Union` or `anyOf` { #union-or-anyof }
 
 You can declare a response to be the `Union` of two or more types, that means, that the response would be any of them.
 
@@ -182,7 +182,7 @@ When defining a <a href="https://docs.pydantic.dev/latest/concepts/types/#unions
 {* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *}
 
 
-### `Union` in Python 3.10
+### `Union` in Python 3.10 { #union-in-python-3-10 }
 
 In this example we pass `Union[PlaneItem, CarItem]` as the value of the argument `response_model`.
 
@@ -196,7 +196,7 @@ some_variable: PlaneItem | CarItem
 
 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.
 
-## List of models
+## List of models { #list-of-models }
 
 The same way, you can declare responses of lists of objects.
 
@@ -205,7 +205,7 @@ For that, use the standard Python `typing.List` (or just `list` in Python 3.9 an
 {* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
 
 
-## Response with arbitrary `dict`
+## Response with arbitrary `dict` { #response-with-arbitrary-dict }
 
 You can also declare a response using a plain arbitrary `dict`, declaring just the type of the keys and values, without using a Pydantic model.
 
@@ -216,7 +216,7 @@ In this case, you can use `typing.Dict` (or just `dict` in Python 3.9 and above)
 {* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
 
 
-## Recap
+## Recap { #recap }
 
 Use multiple Pydantic models and inherit freely for each case.
 
index 4f1b1f1163dd376682345e1b99a0ea303c2c3d69..e75e4099165aa163c1ab5f9dc0cf6b96920b4bc2 100644 (file)
@@ -1,4 +1,4 @@
-# First Steps
+# First Steps { #first-steps }
 
 The simplest FastAPI file could look like this:
 
@@ -56,7 +56,7 @@ INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
 
 That line shows the URL where your app is being served, in your local machine.
 
-### Check it
+### Check it { #check-it }
 
 Open your browser at <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
 
@@ -66,7 +66,7 @@ You will see the JSON response as:
 {"message": "Hello World"}
 ```
 
-### Interactive API docs
+### Interactive API docs { #interactive-api-docs }
 
 Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
@@ -74,7 +74,7 @@ You will see the automatic interactive API documentation (provided by <a href="h
 
 ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
 
-### Alternative API docs
+### Alternative API docs { #alternative-api-docs }
 
 And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
 
@@ -82,31 +82,31 @@ You will see the alternative automatic documentation (provided by <a href="https
 
 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
 
-### OpenAPI
+### OpenAPI { #openapi }
 
 **FastAPI** generates a "schema" with all your API using the **OpenAPI** standard for defining APIs.
 
-#### "Schema"
+#### "Schema" { #schema }
 
 A "schema" is a definition or description of something. Not the code that implements it, but just an abstract description.
 
-#### API "schema"
+#### API "schema" { #api-schema }
 
 In this case, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> is a specification that dictates how to define a schema of your API.
 
 This schema definition includes your API paths, the possible parameters they take, etc.
 
-#### Data "schema"
+#### Data "schema" { #data-schema }
 
 The term "schema" might also refer to the shape of some data, like a JSON content.
 
 In that case, it would mean the JSON attributes, and data types they have, etc.
 
-#### OpenAPI and JSON Schema
+#### OpenAPI and JSON Schema { #openapi-and-json-schema }
 
 OpenAPI defines an API schema for your API. And that schema includes definitions (or "schemas") of the data sent and received by your API using **JSON Schema**, the standard for JSON data schemas.
 
-#### Check the `openapi.json`
+#### Check the `openapi.json` { #check-the-openapi-json }
 
 If you are curious about how the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API.
 
@@ -135,7 +135,7 @@ It will show a JSON starting with something like:
 ...
 ```
 
-#### What is OpenAPI for
+#### What is OpenAPI for { #what-is-openapi-for }
 
 The OpenAPI schema is what powers the two interactive documentation systems included.
 
@@ -143,9 +143,9 @@ And there are dozens of alternatives, all based on OpenAPI. You could easily add
 
 You could also use it to generate code automatically, for clients that communicate with your API. For example, frontend, mobile or IoT applications.
 
-## Recap, step by step
+## Recap, step by step { #recap-step-by-step }
 
-### Step 1: import `FastAPI`
+### Step 1: import `FastAPI` { #step-1-import-fastapi }
 
 {* ../../docs_src/first_steps/tutorial001.py hl[1] *}
 
@@ -159,7 +159,7 @@ You can use all the <a href="https://www.starlette.io/" class="external-link" ta
 
 ///
 
-### Step 2: create a `FastAPI` "instance"
+### Step 2: create a `FastAPI` "instance" { #step-2-create-a-fastapi-instance }
 
 {* ../../docs_src/first_steps/tutorial001.py hl[3] *}
 
@@ -167,9 +167,9 @@ Here the `app` variable will be an "instance" of the class `FastAPI`.
 
 This will be the main point of interaction to create all your API.
 
-### Step 3: create a *path operation*
+### Step 3: create a *path operation* { #step-3-create-a-path-operation }
 
-#### Path
+#### Path { #path }
 
 "Path" here refers to the last part of the URL starting from the first `/`.
 
@@ -193,7 +193,7 @@ A "path" is also commonly called an "endpoint" or a "route".
 
 While building an API, the "path" is the main way to separate "concerns" and "resources".
 
-#### Operation
+#### Operation { #operation }
 
 "Operation" here refers to one of the HTTP "methods".
 
@@ -228,7 +228,7 @@ So, in OpenAPI, each of the HTTP methods is called an "operation".
 
 We are going to call them "**operations**" too.
 
-#### Define a *path operation decorator*
+#### Define a *path operation decorator* { #define-a-path-operation-decorator }
 
 {* ../../docs_src/first_steps/tutorial001.py hl[6] *}
 
@@ -276,7 +276,7 @@ For example, when using GraphQL you normally perform all the actions using only
 
 ///
 
-### Step 4: define the **path operation function**
+### Step 4: define the **path operation function** { #step-4-define-the-path-operation-function }
 
 This is our "**path operation function**":
 
@@ -304,7 +304,7 @@ If you don't know the difference, check the [Async: *"In a hurry?"*](../async.md
 
 ///
 
-### Step 5: return the content
+### Step 5: return the content { #step-5-return-the-content }
 
 {* ../../docs_src/first_steps/tutorial001.py hl[8] *}
 
@@ -314,7 +314,7 @@ You can also return Pydantic models (you'll see more about that later).
 
 There are many other objects and models that will be automatically converted to JSON (including ORMs, etc). Try using your favorite ones, it's highly probable that they are already supported.
 
-## Recap
+## Recap { #recap }
 
 * Import `FastAPI`.
 * Create an `app` instance.
index 5b8e677e49e49419c6ab75be7c4f8147a10941cb..58bf8ffa785f9ed6cb684570039f5a4584941790 100644 (file)
@@ -1,4 +1,4 @@
-# Handling Errors
+# Handling Errors { #handling-errors }
 
 There are many situations in which you need to notify an error to a client that is using your API.
 
@@ -19,15 +19,15 @@ The status codes in the 400 range mean that there was an error from the client.
 
 Remember all those **"404 Not Found"** errors (and jokes)?
 
-## Use `HTTPException`
+## Use `HTTPException` { #use-httpexception }
 
 To return HTTP responses with errors to the client you use `HTTPException`.
 
-### Import `HTTPException`
+### Import `HTTPException` { #import-httpexception }
 
 {* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
 
-### Raise an `HTTPException` in your code
+### Raise an `HTTPException` in your code { #raise-an-httpexception-in-your-code }
 
 `HTTPException` is a normal Python exception with additional data relevant for APIs.
 
@@ -41,7 +41,7 @@ In this example, when the client requests an item by an ID that doesn't exist, r
 
 {* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
 
-### The resulting response
+### The resulting response { #the-resulting-response }
 
 If the client requests `http://example.com/items/foo` (an `item_id` `"foo"`), that client will receive an HTTP status code of 200, and a JSON response of:
 
@@ -69,7 +69,7 @@ They are handled automatically by **FastAPI** and converted to JSON.
 
 ///
 
-## Add custom headers
+## Add custom headers { #add-custom-headers }
 
 There are some situations in where it's useful to be able to add custom headers to the HTTP error. For example, for some types of security.
 
@@ -79,7 +79,7 @@ But in case you needed it for an advanced scenario, you can add custom headers:
 
 {* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
 
-## Install custom exception handlers
+## Install custom exception handlers { #install-custom-exception-handlers }
 
 You can add custom exception handlers with <a href="https://www.starlette.io/exceptions/" class="external-link" target="_blank">the same exception utilities from Starlette</a>.
 
@@ -109,7 +109,7 @@ You could also use `from starlette.requests import Request` and `from starlette.
 
 ///
 
-## Override the default exception handlers
+## Override the default exception handlers { #override-the-default-exception-handlers }
 
 **FastAPI** has some default exception handlers.
 
@@ -117,7 +117,7 @@ These handlers are in charge of returning the default JSON responses when you `r
 
 You can override these exception handlers with your own.
 
-### Override request validation exceptions
+### Override request validation exceptions { #override-request-validation-exceptions }
 
 When a request contains invalid data, **FastAPI** internally raises a `RequestValidationError`.
 
@@ -154,7 +154,7 @@ path -> item_id
   value is not a valid integer (type=type_error.integer)
 ```
 
-#### `RequestValidationError` vs `ValidationError`
+#### `RequestValidationError` vs `ValidationError` { #requestvalidationerror-vs-validationerror }
 
 /// warning
 
@@ -172,7 +172,7 @@ It should be this way because if you have a Pydantic `ValidationError` in your *
 
 And while you fix it, your clients/users shouldn't have access to internal information about the error, as that could expose a security vulnerability.
 
-### Override the `HTTPException` error handler
+### Override the `HTTPException` error handler { #override-the-httpexception-error-handler }
 
 The same way, you can override the `HTTPException` handler.
 
@@ -188,7 +188,7 @@ You could also use `from starlette.responses import PlainTextResponse`.
 
 ///
 
-### Use the `RequestValidationError` body
+### Use the `RequestValidationError` body { #use-the-requestvalidationerror-body }
 
 The `RequestValidationError` contains the `body` it received with invalid data.
 
@@ -226,7 +226,7 @@ You will receive a response telling you that the data is invalid containing the
 }
 ```
 
-#### FastAPI's `HTTPException` vs Starlette's `HTTPException`
+#### FastAPI's `HTTPException` vs Starlette's `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception }
 
 **FastAPI** has its own `HTTPException`.
 
@@ -246,7 +246,7 @@ In this example, to be able to have both `HTTPException`s in the same code, Star
 from starlette.exceptions import HTTPException as StarletteHTTPException
 ```
 
-### Reuse **FastAPI**'s exception handlers
+### Reuse **FastAPI**'s exception handlers { #reuse-fastapis-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`:
 
index 4cdf097057a15f6adb755dee5444a44e91b0b95d..011d5d7fc25ca3783b91a7e96f9cf6f1174db0ee 100644 (file)
@@ -1,4 +1,4 @@
-# Header Parameter Models
+# Header Parameter Models { #header-parameter-models }
 
 If you have a group of related **header parameters**, you can create a **Pydantic model** to declare them.
 
@@ -10,7 +10,7 @@ This is supported since FastAPI version `0.115.0`. 🤓
 
 ///
 
-## Header Parameters with a Pydantic Model
+## Header Parameters with a Pydantic Model { #header-parameters-with-a-pydantic-model }
 
 Declare the **header parameters** that you need in a **Pydantic model**, and then declare the parameter as `Header`:
 
@@ -18,7 +18,7 @@ Declare the **header parameters** that you need in a **Pydantic model**, and the
 
 **FastAPI** will **extract** the data for **each field** from the **headers** in the request and give you the Pydantic model you defined.
 
-## Check the Docs
+## Check the Docs { #check-the-docs }
 
 You can see the required headers in the docs UI at `/docs`:
 
@@ -26,7 +26,7 @@ You can see the required headers in the docs UI at `/docs`:
 <img src="/img/tutorial/header-param-models/image01.png">
 </div>
 
-## Forbid Extra Headers
+## Forbid Extra Headers { #forbid-extra-headers }
 
 In some special use cases (probably not very common), you might want to **restrict** the headers that you want to receive.
 
@@ -51,7 +51,7 @@ For example, if the client tries to send a `tool` header with a value of `plumbu
 }
 ```
 
-## Disable Convert Underscores
+## Disable Convert Underscores { #disable-convert-underscores }
 
 The same way as with regular header parameters, when you have underscore characters in the parameter names, they are **automatically converted to hyphens**.
 
@@ -67,6 +67,6 @@ Before setting `convert_underscores` to `False`, bear in mind that some HTTP pro
 
 ///
 
-## Summary
+## Summary { #summary }
 
 You can use **Pydantic models** to declare **headers** in **FastAPI**. 😎
index 49ad7aa25b24ef884d3f959d8d1672c015a5bba0..3765956a05172278a3fe885bcc07a8d3569c9c16 100644 (file)
@@ -1,14 +1,14 @@
-# Header Parameters
+# Header Parameters { #header-parameters }
 
 You can define Header parameters the same way you define `Query`, `Path` and `Cookie` parameters.
 
-## Import `Header`
+## Import `Header` { #import-header }
 
 First import `Header`:
 
 {* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *}
 
-## Declare `Header` parameters
+## Declare `Header` parameters { #declare-header-parameters }
 
 Then declare the header parameters using the same structure as with `Path`, `Query` and `Cookie`.
 
@@ -30,7 +30,7 @@ To declare headers, you need to use `Header`, because otherwise the parameters w
 
 ///
 
-## Automatic conversion
+## Automatic conversion { #automatic-conversion }
 
 `Header` has a little extra functionality on top of what `Path`, `Query` and `Cookie` provide.
 
@@ -54,7 +54,7 @@ Before setting `convert_underscores` to `False`, bear in mind that some HTTP pro
 
 ///
 
-## Duplicate headers
+## Duplicate headers { #duplicate-headers }
 
 It is possible to receive duplicate headers. That means, the same header with multiple values.
 
@@ -84,7 +84,7 @@ The response would be like:
 }
 ```
 
-## Recap
+## Recap { #recap }
 
 Declare headers with `Header`, using the same common pattern as `Query`, `Path` and `Cookie`.
 
index 17f6fb6857b76e63d83a1772d88f396d8a7cb113..7212a0c4a9cd26e647f06f1839290cec547862da 100644 (file)
@@ -1,4 +1,4 @@
-# Tutorial - User Guide
+# Tutorial - User Guide { #tutorial-user-guide }
 
 This tutorial shows you how to use **FastAPI** with most of its features, step by step.
 
@@ -6,7 +6,7 @@ Each section gradually builds on the previous ones, but it's structured to separ
 
 It is also built to work as a future reference so you can come back and see exactly what you need.
 
-## Run the code
+## Run the code { #run-the-code }
 
 All the code blocks can be copied and used directly (they are actually tested Python files).
 
@@ -58,7 +58,7 @@ Using it in your editor is what really shows you the benefits of FastAPI, seeing
 
 ---
 
-## Install FastAPI
+## Install FastAPI { #install-fastapi }
 
 The first step is to install FastAPI.
 
@@ -84,7 +84,7 @@ If you want to install the standard dependencies but without the `fastapi-cloud-
 
 ///
 
-## Advanced User Guide
+## Advanced User Guide { #advanced-user-guide }
 
 There is also an **Advanced User Guide** that you can read later after this **Tutorial - User guide**.
 
index 6bd48caaf3faf14c7bde4fee4a0b056a051bf08c..55ef620bfc2cd49eff218a3708f4d4e414d2f13d 100644 (file)
@@ -1,8 +1,8 @@
-# Metadata and Docs URLs
+# Metadata and Docs URLs { #metadata-and-docs-urls }
 
 You can customize several metadata configurations in your **FastAPI** application.
 
-## Metadata for API
+## Metadata for API { #metadata-for-api }
 
 You can set the following fields that are used in the OpenAPI specification and the automatic API docs UIs:
 
@@ -30,7 +30,7 @@ With this configuration, the automatic API docs would look like:
 
 <img src="/img/tutorial/metadata/image01.png">
 
-## License identifier
+## License identifier { #license-identifier }
 
 Since OpenAPI 3.1.0 and FastAPI 0.99.0, you can also set the `license_info` with an `identifier` instead of a `url`.
 
@@ -38,7 +38,7 @@ For example:
 
 {* ../../docs_src/metadata/tutorial001_1.py hl[31] *}
 
-## Metadata for tags
+## Metadata for tags { #metadata-for-tags }
 
 You can also add additional metadata for the different tags used to group your path operations with the parameter `openapi_tags`.
 
@@ -52,7 +52,7 @@ Each dictionary can contain:
     * `description`: a `str` with a short description for the external docs.
     * `url` (**required**): a `str` with the URL for the external documentation.
 
-### Create metadata for tags
+### Create metadata for tags { #create-metadata-for-tags }
 
 Let's try that in an example with tags for `users` and `items`.
 
@@ -68,7 +68,7 @@ You don't have to add metadata for all the tags that you use.
 
 ///
 
-### Use your tags
+### Use your tags { #use-your-tags }
 
 Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assign them to different tags:
 
@@ -80,19 +80,19 @@ Read more about tags in [Path Operation Configuration](path-operation-configurat
 
 ///
 
-### Check the docs
+### Check the docs { #check-the-docs }
 
 Now, if you check the docs, they will show all the additional metadata:
 
 <img src="/img/tutorial/metadata/image02.png">
 
-### Order of tags
+### Order of tags { #order-of-tags }
 
 The order of each tag metadata dictionary also defines the order shown in the docs UI.
 
 For example, even though `users` would go after `items` in alphabetical order, it is shown before them, because we added their metadata as the first dictionary in the list.
 
-## OpenAPI URL
+## OpenAPI URL { #openapi-url }
 
 By default, the OpenAPI schema is served at `/openapi.json`.
 
@@ -104,7 +104,7 @@ For example, to set it to be served at `/api/v1/openapi.json`:
 
 If you want to disable the OpenAPI schema completely you can set `openapi_url=None`, that will also disable the documentation user interfaces that use it.
 
-## Docs URLs
+## Docs URLs { #docs-urls }
 
 You can configure the two documentation user interfaces included:
 
index b7c03a3199b7e9d6270a3034ca909ff9106c5798..9bfbf47c920b0b1ba59239b0b599a02823f5d730 100644 (file)
@@ -1,4 +1,4 @@
-# Middleware
+# Middleware { #middleware }
 
 You can add middleware to **FastAPI** applications.
 
@@ -19,7 +19,7 @@ If there were any background tasks (covered in the [Background Tasks](background
 
 ///
 
-## Create a middleware
+## Create a middleware { #create-a-middleware }
 
 To create a middleware you use the decorator `@app.middleware("http")` on top of a function.
 
@@ -49,7 +49,7 @@ You could also use `from starlette.requests import Request`.
 
 ///
 
-### Before and after the `response`
+### Before and after the `response` { #before-and-after-the-response }
 
 You can add code to be run with the `request`,  before any *path operation* receives it.
 
@@ -65,7 +65,7 @@ Here we use <a href="https://docs.python.org/3/library/time.html#time.perf_count
 
 ///
 
-## Multiple middleware execution order
+## Multiple middleware execution order { #multiple-middleware-execution-order }
 
 When you add multiple middlewares using either `@app.middleware()` decorator or `app.add_middleware()` method, each new middleware wraps the application, forming a stack. The last middleware added is the *outermost*, and the first is the *innermost*.
 
@@ -88,7 +88,7 @@ This results in the following execution order:
 
 This stacking behavior ensures that middlewares are executed in a predictable and controllable order.
 
-## Other middlewares
+## Other middlewares { #other-middlewares }
 
 You can later read more about other middlewares in the [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.
 
index f2b5fd7957bc1908f3caea7c4ac7726bd66dd61f..522d67288ae10d85a264f96c941dec45c79d5dc6 100644 (file)
@@ -1,4 +1,4 @@
-# Path Operation Configuration
+# Path Operation Configuration { #path-operation-configuration }
 
 There are several parameters that you can pass to your *path operation decorator* to configure it.
 
@@ -8,7 +8,7 @@ Notice that these parameters are passed directly to the *path operation decorato
 
 ///
 
-## Response Status Code
+## Response Status Code { #response-status-code }
 
 You can define the (HTTP) `status_code` to be used in the response of your *path operation*.
 
@@ -28,7 +28,7 @@ You could also use `from starlette import status`.
 
 ///
 
-## Tags
+## Tags { #tags }
 
 You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
 
@@ -38,7 +38,7 @@ They will be added to the OpenAPI schema and used by the automatic documentation
 
 <img src="/img/tutorial/path-operation-configuration/image01.png">
 
-### Tags with Enums
+### Tags with Enums { #tags-with-enums }
 
 If you have a big application, you might end up accumulating **several tags**, and you would want to make sure you always use the **same tag** for related *path operations*.
 
@@ -48,13 +48,13 @@ In these cases, it could make sense to store the tags in an `Enum`.
 
 {* ../../docs_src/path_operation_configuration/tutorial002b.py hl[1,8:10,13,18] *}
 
-## Summary and description
+## Summary and description { #summary-and-description }
 
 You can add a `summary` and `description`:
 
 {* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
 
-## Description from docstring
+## Description from docstring { #description-from-docstring }
 
 As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function <abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation">docstring</abbr> and **FastAPI** will read it from there.
 
@@ -66,7 +66,7 @@ It will be used in the interactive docs:
 
 <img src="/img/tutorial/path-operation-configuration/image02.png">
 
-## Response description
+## Response description { #response-description }
 
 You can specify the response description with the parameter `response_description`:
 
@@ -88,7 +88,7 @@ So, if you don't provide one, **FastAPI** will automatically generate one of "Su
 
 <img src="/img/tutorial/path-operation-configuration/image03.png">
 
-## Deprecate a *path operation*
+## Deprecate a *path operation* { #deprecate-a-path-operation }
 
 If you need to mark a *path operation* as <abbr title="obsolete, recommended not to use it">deprecated</abbr>, but without removing it, pass the parameter `deprecated`:
 
@@ -102,6 +102,6 @@ Check how deprecated and non-deprecated *path operations* look like:
 
 <img src="/img/tutorial/path-operation-configuration/image05.png">
 
-## Recap
+## Recap { #recap }
 
 You can configure and add metadata for your *path operations* easily by passing parameters to the *path operation decorators*.
index 9440bcc03b00a48a4fe4126d8d88d9f1c71727cc..435606bbfbd5527bea6aab836d83e0497ac747aa 100644 (file)
@@ -1,8 +1,8 @@
-# Path Parameters and Numeric Validations
+# Path Parameters and Numeric Validations { #path-parameters-and-numeric-validations }
 
 In the same way that you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`.
 
-## Import Path
+## Import Path { #import-path }
 
 First, import `Path` from `fastapi`, and import `Annotated`:
 
@@ -18,7 +18,7 @@ Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-
 
 ///
 
-## Declare metadata
+## Declare metadata { #declare-metadata }
 
 You can declare all the same parameters as for `Query`.
 
@@ -32,7 +32,7 @@ A path parameter is always required as it has to be part of the path. Even if yo
 
 ///
 
-## Order the parameters as you need
+## Order the parameters as you need { #order-the-parameters-as-you-need }
 
 /// tip
 
@@ -70,7 +70,7 @@ But keep in mind that if you use `Annotated`, you won't have this problem, it wo
 
 {* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
 
-## Order the parameters as you need, tricks
+## Order the parameters as you need, tricks { #order-the-parameters-as-you-need-tricks }
 
 /// tip
 
@@ -95,13 +95,13 @@ Python won't do anything with that `*`, but it will know that all the following
 
 {* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
 
-### Better with `Annotated`
+### Better with `Annotated` { #better-with-annotated }
 
 Keep in mind that if you use `Annotated`, as you are not using function parameter default values, you won't have this problem, and you probably won't need to use `*`.
 
 {* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
 
-## Number validations: greater than or equal
+## Number validations: greater than or equal { #number-validations-greater-than-or-equal }
 
 With `Query` and `Path` (and others you'll see later) you can declare number constraints.
 
@@ -109,7 +109,7 @@ Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than o
 
 {* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
 
-## Number validations: greater than and less than or equal
+## Number validations: greater than and less than or equal { #number-validations-greater-than-and-less-than-or-equal }
 
 The same applies for:
 
@@ -118,7 +118,7 @@ The same applies for:
 
 {* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
 
-## Number validations: floats, greater than and less than
+## Number validations: floats, greater than and less than { #number-validations-floats-greater-than-and-less-than }
 
 Number validations also work for `float` values.
 
@@ -130,7 +130,7 @@ And the same for <abbr title="less than"><code>lt</code></abbr>.
 
 {* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
 
-## Recap
+## Recap { #recap }
 
 With `Query`, `Path` (and others you haven't seen yet) you can declare metadata and string validations in the same ways as with [Query Parameters and String Validations](query-params-str-validations.md){.internal-link target=_blank}.
 
index 7e83d3ae57e7f4ef8f5ccc6e8783881a7c72e7f9..7f15cb92be7ce764905c7b9f2491e93d4157a3e7 100644 (file)
@@ -1,4 +1,4 @@
-# Path Parameters
+# Path Parameters { #path-parameters }
 
 You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
 
@@ -12,7 +12,7 @@ So, if you run this example and go to <a href="http://127.0.0.1:8000/items/foo"
 {"item_id":"foo"}
 ```
 
-## Path parameters with types
+## Path parameters with types { #path-parameters-with-types }
 
 You can declare the type of a path parameter in the function, using standard Python type annotations:
 
@@ -26,7 +26,7 @@ This will give you editor support inside of your function, with error checks, co
 
 ///
 
-## Data <abbr title="also known as: serialization, parsing, marshalling">conversion</abbr>
+## Data <abbr title="also known as: serialization, parsing, marshalling">conversion</abbr> { #data-conversion }
 
 If you run this example and open your browser at <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, you will see a response of:
 
@@ -42,7 +42,7 @@ So, with that type declaration, **FastAPI** gives you automatic request <abbr ti
 
 ///
 
-## Data validation
+## Data validation { #data-validation }
 
 But if you go to the browser at <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, you will see a nice HTTP error of:
 
@@ -77,7 +77,7 @@ This is incredibly helpful while developing and debugging code that interacts wi
 
 ///
 
-## Documentation
+## Documentation { #documentation }
 
 And when you open your browser at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, you will see an automatic, interactive, API documentation like:
 
@@ -91,7 +91,7 @@ Notice that the path parameter is declared to be an integer.
 
 ///
 
-## Standards-based benefits, alternative documentation
+## Standards-based benefits, alternative documentation { #standards-based-benefits-alternative-documentation }
 
 And because the generated schema is from the <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a> standard, there are many compatible tools.
 
@@ -101,7 +101,7 @@ Because of this, **FastAPI** itself provides an alternative API documentation (u
 
 The same way, there are many compatible tools. Including code generation tools for many languages.
 
-## Pydantic
+## Pydantic { #pydantic }
 
 All the data validation is performed under the hood by <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, so you get all the benefits from it. And you know you are in good hands.
 
@@ -109,7 +109,7 @@ You can use the same type declarations with `str`, `float`, `bool` and many othe
 
 Several of these are explored in the next chapters of the tutorial.
 
-## Order matters
+## Order matters { #order-matters }
 
 When creating *path operations*, you can find situations where you have a fixed path.
 
@@ -129,11 +129,11 @@ Similarly, you cannot redefine a path operation:
 
 The first one will always be used since the path matches first.
 
-## Predefined values
+## Predefined values { #predefined-values }
 
 If you have a *path operation* that receives a *path parameter*, but you want the possible valid *path parameter* values to be predefined, you can use a standard Python <abbr title="Enumeration">`Enum`</abbr>.
 
-### Create an `Enum` class
+### Create an `Enum` class { #create-an-enum-class }
 
 Import `Enum` and create a sub-class that inherits from `str` and from `Enum`.
 
@@ -155,29 +155,29 @@ If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine
 
 ///
 
-### Declare a *path parameter*
+### Declare a *path parameter* { #declare-a-path-parameter }
 
 Then create a *path parameter* with a type annotation using the enum class you created (`ModelName`):
 
 {* ../../docs_src/path_params/tutorial005.py hl[16] *}
 
-### Check the docs
+### Check the docs { #check-the-docs }
 
 Because the available values for the *path parameter* are predefined, the interactive docs can show them nicely:
 
 <img src="/img/tutorial/path-params/image03.png">
 
-### Working with Python *enumerations*
+### Working with Python *enumerations* { #working-with-python-enumerations }
 
 The value of the *path parameter* will be an *enumeration member*.
 
-#### Compare *enumeration members*
+#### Compare *enumeration members* { #compare-enumeration-members }
 
 You can compare it with the *enumeration member* in your created enum `ModelName`:
 
 {* ../../docs_src/path_params/tutorial005.py hl[17] *}
 
-#### Get the *enumeration value*
+#### Get the *enumeration value* { #get-the-enumeration-value }
 
 You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
 
@@ -189,7 +189,7 @@ You could also access the value `"lenet"` with `ModelName.lenet.value`.
 
 ///
 
-#### Return *enumeration members*
+#### Return *enumeration members* { #return-enumeration-members }
 
 You can return *enum members* from your *path operation*, even nested in a JSON body (e.g. a `dict`).
 
@@ -206,7 +206,7 @@ In your client you will get a JSON response like:
 }
 ```
 
-## Path parameters containing paths
+## Path parameters containing paths { #path-parameters-containing-paths }
 
 Let's say you have a *path operation* with a path `/files/{file_path}`.
 
@@ -214,7 +214,7 @@ But you need `file_path` itself to contain a *path*, like `home/johndoe/myfile.t
 
 So, the URL for that file would be something like: `/files/home/johndoe/myfile.txt`.
 
-### OpenAPI support
+### OpenAPI support { #openapi-support }
 
 OpenAPI doesn't support a way to declare a *path parameter* to contain a *path* inside, as that could lead to scenarios that are difficult to test and define.
 
@@ -222,7 +222,7 @@ Nevertheless, you can still do it in **FastAPI**, using one of the internal tool
 
 And the docs would still work, although not adding any documentation telling that the parameter should contain a path.
 
-### Path convertor
+### Path convertor { #path-convertor }
 
 Using an option directly from Starlette you can declare a *path parameter* containing a *path* using a URL like:
 
@@ -244,7 +244,7 @@ In that case, the URL would be: `/files//home/johndoe/myfile.txt`, with a double
 
 ///
 
-## Recap
+## Recap { #recap }
 
 With **FastAPI**, by using short, intuitive and standard Python type declarations, you get:
 
index 84d82931a89c55686baebf31e8e3a44739a0bd3d..b70cdc3354d8d5f649d11c0276d66210d6c47d12 100644 (file)
@@ -1,4 +1,4 @@
-# Query Parameter Models
+# Query Parameter Models { #query-parameter-models }
 
 If you have a group of **query parameters** that are related, you can create a **Pydantic model** to declare them.
 
@@ -10,7 +10,7 @@ This is supported since FastAPI version `0.115.0`. 🤓
 
 ///
 
-## Query Parameters with a Pydantic Model
+## Query Parameters with a Pydantic Model { #query-parameters-with-a-pydantic-model }
 
 Declare the **query parameters** that you need in a **Pydantic model**, and then declare the parameter as `Query`:
 
@@ -18,7 +18,7 @@ Declare the **query parameters** that you need in a **Pydantic model**, and then
 
 **FastAPI** will **extract** the data for **each field** from the **query parameters** in the request and give you the Pydantic model you defined.
 
-## Check the Docs
+## Check the Docs { #check-the-docs }
 
 You can see the query parameters in the docs UI at `/docs`:
 
@@ -26,7 +26,7 @@ You can see the query parameters in the docs UI at `/docs`:
 <img src="/img/tutorial/query-param-models/image01.png">
 </div>
 
-## Forbid Extra Query Parameters
+## Forbid Extra Query Parameters { #forbid-extra-query-parameters }
 
 In some special use cases (probably not very common), you might want to **restrict** the query parameters that you want to receive.
 
@@ -57,7 +57,7 @@ They will receive an **error** response telling them that the query parameter `t
 }
 ```
 
-## Summary
+## Summary { #summary }
 
 You can use **Pydantic models** to declare **query parameters** in **FastAPI**. 😎
 
index e50fc347c4a0b4912a8fc81208141305185b0b97..a55b4cfb0196bf70cddfc34d05523bd446c2d996 100644 (file)
@@ -1,4 +1,4 @@
-# Query Parameters and String Validations
+# Query Parameters and String Validations { #query-parameters-and-string-validations }
 
 **FastAPI** allows you to declare additional information and validation for your parameters.
 
@@ -16,11 +16,11 @@ Having `str | None` will allow your editor to give you better support and detect
 
 ///
 
-## Additional validation
+## Additional validation { #additional-validation }
 
 We are going to enforce that even though `q` is optional, whenever it is provided, **its length doesn't exceed 50 characters**.
 
-### Import `Query` and `Annotated`
+### Import `Query` and `Annotated` { #import-query-and-annotated }
 
 To achieve that, first import:
 
@@ -39,7 +39,7 @@ Make sure you [Upgrade the FastAPI version](../deployment/versions.md#upgrading-
 
 ///
 
-## Use `Annotated` in the type for the `q` parameter
+## Use `Annotated` in the type for the `q` parameter { #use-annotated-in-the-type-for-the-q-parameter }
 
 Remember I told you before that `Annotated` can be used to add metadata to your parameters in the [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
 
@@ -85,7 +85,7 @@ Both of those versions mean the same thing, `q` is a parameter that can be a `st
 
 Now let's jump to the fun stuff. 🎉
 
-## Add `Query` to `Annotated` in the `q` parameter
+## Add `Query` to `Annotated` in the `q` parameter { #add-query-to-annotated-in-the-q-parameter }
 
 Now that we have this `Annotated` where we can put more information (in this case some additional validation), add `Query` inside of `Annotated`, and set the parameter `max_length` to `50`:
 
@@ -107,7 +107,7 @@ FastAPI will now:
 * 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 { #alternative-old-query-as-the-default-value }
 
 Previous versions of FastAPI (before <abbr title="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.
 
@@ -146,7 +146,7 @@ q: str | None = Query(default=None, max_length=50)
 
 This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
 
-### `Query` as the default value or in `Annotated`
+### `Query` as the default value or in `Annotated` { #query-as-the-default-value-or-in-annotated }
 
 Keep in mind that when using `Query` inside of `Annotated` you cannot use the `default` parameter for `Query`.
 
@@ -172,7 +172,7 @@ q: Annotated[str, Query()] = "rick"
 q: str = Query(default="rick")
 ```
 
-### Advantages of `Annotated`
+### Advantages of `Annotated` { #advantages-of-annotated }
 
 **Using `Annotated` is recommended** instead of the default value in function parameters, it is **better** for multiple reasons. 🤓
 
@@ -184,13 +184,13 @@ When you don't use `Annotated` and instead use the **(old) default value style**
 
 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>. 🚀
 
-## Add more validations
+## Add more validations { #add-more-validations }
 
 You can also add a parameter `min_length`:
 
 {* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
 
-## Add regular expressions
+## Add regular expressions { #add-regular-expressions }
 
 You can define a <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">regular expression</abbr> `pattern` that the parameter should match:
 
@@ -206,7 +206,7 @@ If you feel lost with all these **"regular expression"** ideas, don't worry. The
 
 Now you know that whenever you need them you can use them in **FastAPI**.
 
-### Pydantic v1 `regex` instead of `pattern`
+### Pydantic v1 `regex` instead of `pattern` { #pydantic-v1-regex-instead-of-pattern }
 
 Before Pydantic version 2 and before FastAPI 0.100.0, the parameter was called `regex` instead of `pattern`, but it's now deprecated.
 
@@ -220,7 +220,7 @@ You could still see some code using it:
 
 But know that this is deprecated and it should be updated to use the new parameter `pattern`. 🤓
 
-## Default values
+## Default values { #default-values }
 
 You can, of course, use default values other than `None`.
 
@@ -234,7 +234,7 @@ Having a default value of any type, including `None`, makes the parameter option
 
 ///
 
-## Required parameters
+## Required parameters { #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:
 
@@ -262,7 +262,7 @@ So, when you need to declare a value as required while using `Query`, you can si
 
 {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
 
-### Required, can be `None`
+### Required, can be `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`.
 
@@ -270,7 +270,7 @@ To do that, you can declare that `None` is a valid type but simply do not declar
 
 {* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
 
-## Query parameter list / multiple values
+## Query parameter list / multiple values { #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 another way, to receive multiple values.
 
@@ -307,7 +307,7 @@ The interactive API docs will update accordingly, to allow multiple values:
 
 <img src="/img/tutorial/query-params-str-validations/image02.png">
 
-### Query parameter list / multiple values with defaults
+### Query parameter list / multiple values with defaults { #query-parameter-list-multiple-values-with-defaults }
 
 You can also define a default `list` of values if none are provided:
 
@@ -330,7 +330,7 @@ the default of `q` will be: `["foo", "bar"]` and your response will be:
 }
 ```
 
-#### Using just `list`
+#### Using just `list` { #using-just-list }
 
 You can also use `list` directly instead of `list[str]`:
 
@@ -344,7 +344,7 @@ For example, `list[int]` would check (and document) that the contents of the lis
 
 ///
 
-## Declare more metadata
+## Declare more metadata { #declare-more-metadata }
 
 You can add more information about the parameter.
 
@@ -366,7 +366,7 @@ And a `description`:
 
 {* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
 
-## Alias parameters
+## Alias parameters { #alias-parameters }
 
 Imagine that you want the parameter to be `item-query`.
 
@@ -386,7 +386,7 @@ Then you can declare an `alias`, and that alias is what will be used to find the
 
 {* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
 
-## Deprecating parameters
+## Deprecating parameters { #deprecating-parameters }
 
 Now let's say you don't like this parameter anymore.
 
@@ -400,13 +400,13 @@ The docs will show it like this:
 
 <img src="/img/tutorial/query-params-str-validations/image01.png">
 
-## Exclude parameters from OpenAPI
+## Exclude parameters from OpenAPI { #exclude-parameters-from-openapi }
 
 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`:
 
 {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
 
-## Custom Validation
+## Custom Validation { #custom-validation }
 
 There could be cases where you need to do some **custom validation** that can't be done with the parameters shown above.
 
@@ -438,7 +438,7 @@ These custom validators are for things that can be checked with **only** the **s
 
 ///
 
-### Understand that Code
+### Understand that Code { #understand-that-code }
 
 The important point is just using **`AfterValidator` with a function inside `Annotated`**. Feel free to skip this part. 🤸
 
@@ -446,13 +446,13 @@ The important point is just using **`AfterValidator` with a function inside `Ann
 
 But if you're curious about this specific code example and you're still entertained, here are some extra details.
 
-#### String with `value.startswith()`
+#### String with `value.startswith()` { #string-with-value-startswith }
 
 Did you notice? a string using `value.startswith()` can take a tuple, and it will check each value in the tuple:
 
 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
 
-#### A Random Item
+#### A Random Item { #a-random-item }
 
 With `data.items()` we get an <abbr title="Something we can iterate on with a for loop, like a list, set, etc.">iterable object</abbr> with tuples containing the key and value for each dictionary item.
 
@@ -468,7 +468,7 @@ So, if the user didn't provide an item ID, they will still receive a random sugg
 
 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
 
-## Recap
+## Recap { #recap }
 
 You can declare additional validations and metadata for your parameters.
 
index c8477387c8fda260bd3a24f8b4a6a77aa556e999..366620f926c927b4cdd8163358c7e34aee7e69a0 100644 (file)
@@ -1,4 +1,4 @@
-# Query Parameters
+# Query Parameters { #query-parameters }
 
 When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.
 
@@ -28,7 +28,7 @@ All the same process that applied for path parameters also applies for query par
 * Data validation
 * Automatic documentation
 
-## Defaults
+## Defaults { #defaults }
 
 As query parameters are not a fixed part of a path, they can be optional and can have default values.
 
@@ -57,7 +57,7 @@ The parameter values in your function will be:
 * `skip=20`: because you set it in the URL
 * `limit=10`: because that was the default value
 
-## Optional parameters
+## Optional parameters { #optional-parameters }
 
 The same way, you can declare optional query parameters, by setting their default to `None`:
 
@@ -71,7 +71,7 @@ Also notice that **FastAPI** is smart enough to notice that the path parameter `
 
 ///
 
-## Query parameter type conversion
+## Query parameter type conversion { #query-parameter-type-conversion }
 
 You can also declare `bool` types, and they will be converted:
 
@@ -110,7 +110,7 @@ http://127.0.0.1:8000/items/foo?short=yes
 or any other case variation (uppercase, first letter in uppercase, etc), your function will see the parameter `short` with a `bool` value of `True`. Otherwise as `False`.
 
 
-## Multiple path and query parameters
+## Multiple path and query parameters { #multiple-path-and-query-parameters }
 
 You can declare multiple path parameters and query parameters at the same time, **FastAPI** knows which is which.
 
@@ -120,7 +120,7 @@ They will be detected by name:
 
 {* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
 
-## Required query parameters
+## Required query parameters { #required-query-parameters }
 
 When you declare a default value for non-path parameters (for now, we have only seen query parameters), then it is not required.
 
index 0d57f35660df998ecdcf35c6ff4872939b41fb24..3d6e9c18a043da424298cf156179a40a26952067 100644 (file)
@@ -1,4 +1,4 @@
-# Request Files
+# Request Files { #request-files }
 
 You can define files to be uploaded by the client using `File`.
 
@@ -16,13 +16,13 @@ This is because uploaded files are sent as "form data".
 
 ///
 
-## Import `File`
+## Import `File` { #import-file }
 
 Import `File` and `UploadFile` from `fastapi`:
 
 {* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
 
-## Define `File` Parameters
+## Define `File` Parameters { #define-file-parameters }
 
 Create file parameters the same way you would for `Body` or `Form`:
 
@@ -50,7 +50,7 @@ Keep in mind that this means that the whole contents will be stored in memory. T
 
 But there are several cases in which you might benefit from using `UploadFile`.
 
-## File Parameters with `UploadFile`
+## File Parameters with `UploadFile` { #file-parameters-with-uploadfile }
 
 Define a file parameter with a type of `UploadFile`:
 
@@ -66,7 +66,7 @@ Using `UploadFile` has several advantages over `bytes`:
 * It has a <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> `async` interface.
 * It exposes an actual Python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> object that you can pass directly to other libraries that expect a file-like object.
 
-### `UploadFile`
+### `UploadFile` { #uploadfile }
 
 `UploadFile` has the following attributes:
 
@@ -109,7 +109,7 @@ When you use the `async` methods, **FastAPI** runs the file methods in a threadp
 
 ///
 
-## What is "Form Data"
+## What is "Form Data" { #what-is-form-data }
 
 The way HTML forms (`<form></form>`) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON.
 
@@ -133,19 +133,19 @@ This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
 
 ///
 
-## Optional File Upload
+## Optional File Upload { #optional-file-upload }
 
 You can make a file optional by using standard type annotations and setting a default value of `None`:
 
 {* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
 
-## `UploadFile` with Additional Metadata
+## `UploadFile` with Additional Metadata { #uploadfile-with-additional-metadata }
 
 You can also use `File()` with `UploadFile`, for example, to set additional metadata:
 
 {* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
 
-## Multiple File Uploads
+## Multiple File Uploads { #multiple-file-uploads }
 
 It's possible to upload several files at the same time.
 
@@ -165,12 +165,12 @@ You could also use `from starlette.responses import HTMLResponse`.
 
 ///
 
-### Multiple File Uploads with Additional Metadata
+### Multiple File Uploads with Additional Metadata { #multiple-file-uploads-with-additional-metadata }
 
 And the same way as before, you can use `File()` to set additional parameters, even for `UploadFile`:
 
 {* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
 
-## Recap
+## Recap { #recap }
 
 Use `File`, `bytes`, and `UploadFile` to declare files to be uploaded in the request, sent as form data.
index 79046a3f692db38435eafa503644d975f458999a..68bdf198e76e0fbe3532c1a7290c4fea814fcc22 100644 (file)
@@ -1,4 +1,4 @@
-# Form Models
+# Form Models { #form-models }
 
 You can use **Pydantic models** to declare **form fields** in FastAPI.
 
@@ -20,7 +20,7 @@ This is supported since FastAPI version `0.113.0`. 🤓
 
 ///
 
-## Pydantic Models for Forms
+## Pydantic Models for Forms { #pydantic-models-for-forms }
 
 You just need to declare a **Pydantic model** with the fields you want to receive as **form fields**, and then declare the parameter as `Form`:
 
@@ -28,7 +28,7 @@ You just need to declare a **Pydantic model** with the fields you want to receiv
 
 **FastAPI** will **extract** the data for **each field** from the **form data** in the request and give you the Pydantic model you defined.
 
-## Check the Docs
+## Check the Docs { #check-the-docs }
 
 You can verify it in the docs UI at `/docs`:
 
@@ -36,7 +36,7 @@ You can verify it in the docs UI at `/docs`:
 <img src="/img/tutorial/request-form-models/image01.png">
 </div>
 
-## Forbid Extra Form Fields
+## Forbid Extra Form Fields { #forbid-extra-form-fields }
 
 In some special use cases (probably not very common), you might want to **restrict** the form fields to only those declared in the Pydantic model. And **forbid** any **extra** fields.
 
@@ -73,6 +73,6 @@ They will receive an error response telling them that the field `extra` is not a
 }
 ```
 
-## Summary
+## Summary { #summary }
 
 You can use Pydantic models to declare form fields in FastAPI. 😎
index 21e4bbd301044a7d47b36458ab5fc71dfebd4f1d..a9d905a51d0c3c02579b1ae39212446548638a6a 100644 (file)
@@ -1,4 +1,4 @@
-# Request Forms and Files
+# Request Forms and Files { #request-forms-and-files }
 
 You can define files and form fields at the same time using `File` and `Form`.
 
@@ -14,11 +14,11 @@ $ pip install python-multipart
 
 ///
 
-## Import `File` and `Form`
+## Import `File` and `Form` { #import-file-and-form }
 
 {* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
 
-## Define `File` and `Form` parameters
+## Define `File` and `Form` parameters { #define-file-and-form-parameters }
 
 Create file and form parameters the same way you would for `Body` or `Query`:
 
@@ -36,6 +36,6 @@ This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
 
 ///
 
-## Recap
+## Recap { #recap }
 
 Use `File` and `Form` together when you need to receive data and files in the same request.
index 3c6a0ddaaa8a76da1f6b0028b7d01e981ae05ef4..d743c2ec4e8be9c37f2f02784d7230c625c5640e 100644 (file)
@@ -1,4 +1,4 @@
-# Form Data
+# Form Data { #form-data }
 
 When you need to receive form fields instead of JSON, you can use `Form`.
 
@@ -14,13 +14,13 @@ $ pip install python-multipart
 
 ///
 
-## Import `Form`
+## Import `Form` { #import-form }
 
 Import `Form` from `fastapi`:
 
 {* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
 
-## Define `Form` parameters
+## Define `Form` parameters { #define-form-parameters }
 
 Create form parameters the same way you would for `Body` or `Query`:
 
@@ -44,7 +44,7 @@ To declare form bodies, you need to use `Form` explicitly, because without it th
 
 ///
 
-## About "Form Fields"
+## About "Form Fields" { #about-form-fields }
 
 The way HTML forms (`<form></form>`) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON.
 
@@ -68,6 +68,6 @@ This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
 
 ///
 
-## Recap
+## Recap { #recap }
 
 Use `Form` to declare form data input parameters.
index e7837086fb94903764991271ba53e35b5f5bc73d..5090dbcdfd253a9675c7c479e14070747ec32bbd 100644 (file)
@@ -1,4 +1,4 @@
-# Response Model - Return Type
+# Response Model - Return Type { #response-model-return-type }
 
 You can declare the type used for the response by annotating the *path operation function* **return type**.
 
@@ -19,7 +19,7 @@ But most importantly:
 * It will **limit and filter** the output data to what is defined in the return type.
     * This is particularly important for **security**, we'll see more of that below.
 
-## `response_model` Parameter
+## `response_model` Parameter { #response-model-parameter }
 
 There are some cases where you need or want to return some data that is not exactly what the type declares.
 
@@ -57,7 +57,7 @@ That way you tell the editor that you are intentionally returning anything. But
 
 ///
 
-### `response_model` Priority
+### `response_model` Priority { #response-model-priority }
 
 If you declare both a return type and a `response_model`, the `response_model` will take priority and be used by FastAPI.
 
@@ -65,7 +65,7 @@ This way you can add correct type annotations to your functions even when you ar
 
 You can also use `response_model=None` to disable creating a response model for that *path operation*, you might need to do it if you are adding type annotations for things that are not valid Pydantic fields, you will see an example of that in one of the sections below.
 
-## Return the same input data
+## Return the same input data { #return-the-same-input-data }
 
 Here we are declaring a `UserIn` model, it will contain a plaintext password:
 
@@ -105,7 +105,7 @@ Never store the plain password of a user or send it in a response like this, unl
 
 ///
 
-## Add an output model
+## Add an output model { #add-an-output-model }
 
 We can instead create an input model with the plaintext password and an output model without it:
 
@@ -121,7 +121,7 @@ Here, even though our *path operation function* is returning the same input user
 
 So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
 
-### `response_model` or Return Type
+### `response_model` or Return Type { #response-model-or-return-type }
 
 In this case, because the two models are different, if we annotated the function return type as `UserOut`, the editor and tools would complain that we are returning an invalid type, as those are different classes.
 
@@ -129,7 +129,7 @@ That's why in this example we have to declare it in the `response_model` paramet
 
 ...but continue reading below to see how to overcome that.
 
-## Return Type and Data Filtering
+## Return Type and Data Filtering { #return-type-and-data-filtering }
 
 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**.
 
@@ -147,7 +147,7 @@ With this, we get tooling support, from editors and mypy as this code is correct
 
 How does this work? Let's check that out. 🤓
 
-### Type Annotations and Tooling
+### Type Annotations and Tooling { #type-annotations-and-tooling }
 
 First let's see how editors, mypy and other tools would see this.
 
@@ -157,7 +157,7 @@ We annotate the function return type as `BaseUser`, but we are actually returnin
 
 The editor, mypy, and other tools won't complain about this because, in typing terms, `UserIn` is a subclass of `BaseUser`, which means it's a *valid* type when what is expected is anything that is a `BaseUser`.
 
-### FastAPI Data Filtering
+### FastAPI Data Filtering { #fastapi-data-filtering }
 
 Now, for FastAPI, it will see the return type and make sure that what you return includes **only** the fields that are declared in the type.
 
@@ -165,7 +165,7 @@ FastAPI does several things internally with Pydantic to make sure that those sam
 
 This way, you can get the best of both worlds: type annotations with **tooling support** and **data filtering**.
 
-## See it in the docs
+## See it in the docs { #see-it-in-the-docs }
 
 When you see the automatic docs, you can check that the input model and output model will both have their own JSON Schema:
 
@@ -175,11 +175,11 @@ And both models will be used for the interactive API documentation:
 
 <img src="/img/tutorial/response-model/image02.png">
 
-## Other Return Type Annotations
+## Other Return Type Annotations { #other-return-type-annotations }
 
 There might be cases where you return something that is not a valid Pydantic field and you annotate it in the function, only to get the support provided by tooling (the editor, mypy, etc).
 
-### Return a Response Directly
+### Return a Response Directly { #return-a-response-directly }
 
 The most common case would be [returning a Response directly as explained later in the advanced docs](../advanced/response-directly.md){.internal-link target=_blank}.
 
@@ -189,7 +189,7 @@ This simple case is handled automatically by FastAPI because the return type ann
 
 And tools will also be happy because both `RedirectResponse` and `JSONResponse` are subclasses of `Response`, so the type annotation is correct.
 
-### Annotate a Response Subclass
+### Annotate a Response Subclass { #annotate-a-response-subclass }
 
 You can also use a subclass of `Response` in the type annotation:
 
@@ -197,7 +197,7 @@ You can also use a subclass of `Response` in the type annotation:
 
 This will also work because `RedirectResponse` is a subclass of `Response`, and FastAPI will automatically handle this simple case.
 
-### Invalid Return Type Annotations
+### Invalid Return Type Annotations { #invalid-return-type-annotations }
 
 But when you return some other arbitrary object that is not a valid Pydantic type (e.g. a database object) and you annotate it like that in the function, FastAPI will try to create a Pydantic response model from that type annotation, and will fail.
 
@@ -207,7 +207,7 @@ The same would happen if you had something like a <abbr title='A union between m
 
 ...this fails because the type annotation is not a Pydantic type and is not just a single `Response` class or subclass, it's a union (any of the two) between a `Response` and a `dict`.
 
-### Disable Response Model
+### Disable Response Model { #disable-response-model }
 
 Continuing from the example above, you might not want to have the default data validation, documentation, filtering, etc. that is performed by FastAPI.
 
@@ -219,7 +219,7 @@ In this case, you can disable the response model generation by setting `response
 
 This will make FastAPI skip the response model generation and that way you can have any return type annotations you need without it affecting your FastAPI application. 🤓
 
-## Response Model encoding parameters
+## Response Model encoding parameters { #response-model-encoding-parameters }
 
 Your response model could have default values, like:
 
@@ -233,7 +233,7 @@ but you might want to omit them from the result if they were not actually stored
 
 For example, if you have models with many optional attributes in a NoSQL database, but you don't want to send very long JSON responses full of default values.
 
-### Use the `response_model_exclude_unset` parameter
+### Use the `response_model_exclude_unset` parameter { #use-the-response-model-exclude-unset-parameter }
 
 You can set the *path operation decorator* parameter `response_model_exclude_unset=True`:
 
@@ -275,7 +275,7 @@ as described in <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#
 
 ///
 
-#### Data with values for fields with defaults
+#### Data with values for fields with defaults { #data-with-values-for-fields-with-defaults }
 
 But if your data has values for the model's fields with default values, like the item with ID `bar`:
 
@@ -290,7 +290,7 @@ But if your data has values for the model's fields with default values, like the
 
 they will be included in the response.
 
-#### Data with the same values as the defaults
+#### Data with the same values as the defaults { #data-with-the-same-values-as-the-defaults }
 
 If the data has the same values as the default ones, like the item with ID `baz`:
 
@@ -316,7 +316,7 @@ They can be a list (`[]`), a `float` of `10.5`, etc.
 
 ///
 
-### `response_model_include` and `response_model_exclude`
+### `response_model_include` and `response_model_exclude` { #response-model-include-and-response-model-exclude }
 
 You can also use the *path operation decorator* parameters `response_model_include` and `response_model_exclude`.
 
@@ -344,13 +344,13 @@ It is equivalent to `set(["name", "description"])`.
 
 ///
 
-#### Using `list`s instead of `set`s
+#### Using `list`s instead of `set`s { #using-lists-instead-of-sets }
 
 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:
 
 {* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *}
 
-## Recap
+## Recap { #recap }
 
 Use the *path operation decorator's* parameter `response_model` to define response models and especially to ensure private data is filtered out.
 
index 41bf02a8f53e637760c7a3a0b9b5adbaaa502e06..a2d9757b28cfc75174a494791db964c5aa7b3b90 100644 (file)
@@ -1,4 +1,4 @@
-# Response Status Code
+# Response Status Code { #response-status-code }
 
 The same way you can specify a response model, you can also declare the HTTP status code used for the response with the parameter `status_code` in any of the *path operations*:
 
@@ -39,7 +39,7 @@ FastAPI knows this, and will produce OpenAPI docs that state there is no respons
 
 ///
 
-## About HTTP status codes
+## About HTTP status codes { #about-http-status-codes }
 
 /// note
 
@@ -70,7 +70,7 @@ To know more about each status code and which code is for what, check the <a hre
 
 ///
 
-## Shortcut to remember the names
+## Shortcut to remember the names { #shortcut-to-remember-the-names }
 
 Let's see the previous example again:
 
@@ -96,6 +96,6 @@ You could also use `from starlette import status`.
 
 ///
 
-## Changing the default
+## Changing the default { #changing-the-default }
 
 Later, in the [Advanced User Guide](../advanced/response-change-status-code.md){.internal-link target=_blank}, you will see how to return a different status code than the default you are declaring here.
index 32a1f5ca21f479051094c90a0f5479bde1ea01a7..f3ddaf36974b6257ee365066b56b99302e2fd40b 100644 (file)
@@ -1,10 +1,10 @@
-# Declare Request Example Data
+# Declare Request Example Data { #declare-request-example-data }
 
 You can declare examples of the data your app can receive.
 
 Here are several ways to do it.
 
-## Extra JSON Schema data in Pydantic models
+## Extra JSON Schema data in Pydantic models { #extra-json-schema-data-in-pydantic-models }
 
 You can declare `examples` for a Pydantic model that will be added to the generated JSON Schema.
 
@@ -56,13 +56,13 @@ You can read more at the end of this page.
 
 ///
 
-## `Field` additional arguments
+## `Field` additional arguments { #field-additional-arguments }
 
 When using `Field()` with Pydantic models, you can also declare additional `examples`:
 
 {* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *}
 
-## `examples` in JSON Schema - OpenAPI
+## `examples` in JSON Schema - OpenAPI { #examples-in-json-schema-openapi }
 
 When using any of:
 
@@ -76,19 +76,19 @@ When using any of:
 
 you can also declare a group of `examples` with additional information that will be added to their **JSON Schemas** inside of **OpenAPI**.
 
-### `Body` with `examples`
+### `Body` with `examples` { #body-with-examples }
 
 Here we pass `examples` containing one example of the data expected in `Body()`:
 
 {* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *}
 
-### Example in the docs UI
+### Example in the docs UI { #example-in-the-docs-ui }
 
 With any of the methods above it would look like this in the `/docs`:
 
 <img src="/img/tutorial/body-fields/image01.png">
 
-### `Body` with multiple `examples`
+### `Body` with multiple `examples` { #body-with-multiple-examples }
 
 You can of course also pass multiple `examples`:
 
@@ -98,7 +98,7 @@ When you do this, the examples will be part of the internal **JSON Schema** for
 
 Nevertheless, at the <abbr title="2023-08-26">time of writing this</abbr>, Swagger UI, the tool in charge of showing the docs UI, doesn't support showing multiple examples for the data in **JSON Schema**. But read below for a workaround.
 
-### OpenAPI-specific `examples`
+### OpenAPI-specific `examples` { #openapi-specific-examples }
 
 Since before **JSON Schema** supported `examples` OpenAPI had support for a different field also called `examples`.
 
@@ -110,7 +110,7 @@ The shape of this OpenAPI-specific field `examples` is a `dict` with **multiple
 
 This doesn't go inside of each JSON Schema contained in OpenAPI, this goes outside, in the *path operation* directly.
 
-### Using the `openapi_examples` Parameter
+### Using the `openapi_examples` Parameter { #using-the-openapi-examples-parameter }
 
 You can declare the OpenAPI-specific `examples` in FastAPI with the parameter `openapi_examples` for:
 
@@ -135,13 +135,13 @@ You can use it like this:
 
 {* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
 
-### OpenAPI Examples in the Docs UI
+### OpenAPI Examples in the Docs UI { #openapi-examples-in-the-docs-ui }
 
 With `openapi_examples` added to `Body()` the `/docs` would look like:
 
 <img src="/img/tutorial/body-fields/image02.png">
 
-## Technical Details
+## Technical Details { #technical-details }
 
 /// tip
 
@@ -183,7 +183,7 @@ This old OpenAPI-specific `examples` parameter is now `openapi_examples` since F
 
 ///
 
-### JSON Schema's `examples` field
+### JSON Schema's `examples` field { #json-schemas-examples-field }
 
 But then JSON Schema added an <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a> field to a new version of the specification.
 
@@ -201,7 +201,7 @@ Because of that, versions of FastAPI previous to 0.99.0 still used versions of O
 
 ///
 
-### Pydantic and FastAPI `examples`
+### Pydantic and FastAPI `examples` { #pydantic-and-fastapi-examples }
 
 When you add `examples` inside a Pydantic model, using `schema_extra` or `Field(examples=["something"])` that example is added to the **JSON Schema** for that Pydantic model.
 
@@ -211,13 +211,13 @@ In versions of FastAPI before 0.99.0 (0.99.0 and above use the newer OpenAPI 3.1
 
 But now that FastAPI 0.99.0 and above uses OpenAPI 3.1.0, that uses JSON Schema 2020-12, and Swagger UI 5.0.0 and above, everything is more consistent and the examples are included in JSON Schema.
 
-### Swagger UI and OpenAPI-specific `examples`
+### Swagger UI and OpenAPI-specific `examples` { #swagger-ui-and-openapi-specific-examples }
 
 Now, as Swagger UI didn't support multiple JSON Schema examples (as of 2023-08-26), users didn't have a way to show multiple examples in the docs.
 
 To solve that, FastAPI `0.103.0` **added support** for declaring the same old **OpenAPI-specific** `examples` field with the new parameter `openapi_examples`. 🤓
 
-### Summary
+### Summary { #summary }
 
 I used to say I didn't like history that much... and look at me now giving "tech history" lessons. 😅
 
index 8f6578e12b067b70b860d21f49438009d1a6e4f9..fd8a44f7688e87f7a2c5d2b997684b44ee62408d 100644 (file)
@@ -1,4 +1,4 @@
-# Security - First Steps
+# Security - First Steps { #security-first-steps }
 
 Let's imagine that you have your **backend** API in some domain.
 
@@ -12,17 +12,17 @@ But let's save you the time of reading the full long specification just to find
 
 Let's use the tools provided by **FastAPI** to handle security.
 
-## How it looks
+## How it looks { #how-it-looks }
 
 Let's first just use the code and see how it works, and then we'll come back to understand what's happening.
 
-## Create `main.py`
+## Create `main.py` { #create-main-py }
 
 Copy the example in a file `main.py`:
 
 {* ../../docs_src/security/tutorial001_an_py39.py *}
 
-## Run it
+## Run it { #run-it }
 
 /// info
 
@@ -52,7 +52,7 @@ $ fastapi dev main.py
 
 </div>
 
-## Check it
+## Check it { #check-it }
 
 Go to the interactive docs at: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
@@ -86,7 +86,7 @@ It can be used by third party applications and systems.
 
 And it can also be used by yourself, to debug, check and test the same application.
 
-## The `password` flow
+## The `password` flow { #the-password-flow }
 
 Now let's go back a bit and understand what is all that.
 
@@ -112,7 +112,7 @@ So, let's review it from that simplified point of view:
     * So, to authenticate with our API, it sends a header `Authorization` with a value of `Bearer ` plus the token.
     * If the token contains `foobar`, the content of the `Authorization` header would be: `Bearer foobar`.
 
-## **FastAPI**'s `OAuth2PasswordBearer`
+## **FastAPI**'s `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer }
 
 **FastAPI** provides several tools, at different levels of abstraction, to implement these security features.
 
@@ -166,7 +166,7 @@ oauth2_scheme(some, parameters)
 
 So, it can be used with `Depends`.
 
-### Use it
+### Use it { #use-it }
 
 Now you can pass that `oauth2_scheme` in a dependency with `Depends`.
 
@@ -184,7 +184,7 @@ All the security utilities that integrate with OpenAPI (and the automatic API do
 
 ///
 
-## What it does
+## What it does { #what-it-does }
 
 It will go and look in the request for that `Authorization` header, check if the value is `Bearer ` plus some token, and will return the token as a `str`.
 
@@ -198,6 +198,6 @@ You can try it already in the interactive docs:
 
 We are not verifying the validity of the token yet, but that's a start already.
 
-## Recap
+## Recap { #recap }
 
 So, in just 3 or 4 extra lines, you already have some primitive form of security.
index 5de3a8e7df13374823d054a67d5538bbe873ad84..d9fc8119ba00ac8cfd6be29588c3770173cf08ef 100644 (file)
@@ -1,4 +1,4 @@
-# Get Current User
+# Get Current User { #get-current-user }
 
 In the previous chapter the security system (which is based on the dependency injection system) was giving the *path operation function* a `token` as a `str`:
 
@@ -8,7 +8,7 @@ But that is still not that useful.
 
 Let's make it give us the current user.
 
-## Create a user model
+## Create a user model { #create-a-user-model }
 
 First, let's create a Pydantic user model.
 
@@ -16,7 +16,7 @@ The same way we use Pydantic to declare bodies, we can use it anywhere else:
 
 {* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *}
 
-## Create a `get_current_user` dependency
+## Create a `get_current_user` dependency { #create-a-get-current-user-dependency }
 
 Let's create a dependency `get_current_user`.
 
@@ -28,13 +28,13 @@ The same as we were doing before in the *path operation* directly, our new depen
 
 {* ../../docs_src/security/tutorial002_an_py310.py hl[25] *}
 
-## Get the user
+## Get the user { #get-the-user }
 
 `get_current_user` will use a (fake) utility function we created, that takes a token as a `str` and returns our Pydantic `User` model:
 
 {* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *}
 
-## Inject the current user
+## Inject the current user { #inject-the-current-user }
 
 So now we can use the same `Depends` with our `get_current_user` in the *path operation*:
 
@@ -60,7 +60,7 @@ We are not restricted to having only one dependency that can return that type of
 
 ///
 
-## Other models
+## Other models { #other-models }
 
 You can now get the current user directly in the *path operation functions* and deal with the security mechanisms at the **Dependency Injection** level, using `Depends`.
 
@@ -76,7 +76,7 @@ You actually don't have users that log in to your application but robots, bots,
 
 Just use any kind of model, any kind of class, any kind of database that you need for your application. **FastAPI** has you covered with the dependency injection system.
 
-## Code size
+## Code size { #code-size }
 
 This example might seem verbose. Keep in mind that we are mixing security, data models, utility functions and *path operations* in the same file.
 
@@ -94,7 +94,7 @@ And all these thousands of *path operations* can be as small as 3 lines:
 
 {* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *}
 
-## Recap
+## Recap { #recap }
 
 You can now get the current user directly in your *path operation function*.
 
index d33a2b14d986c9f613e8c8df1686546d68625d59..92e0e932b4de1dff939b444adb08754e6e33fddb 100644 (file)
@@ -1,4 +1,4 @@
-# Security
+# Security { #security }
 
 There are many ways to handle security, authentication and authorization.
 
@@ -10,11 +10,11 @@ In many frameworks and systems just handling security and authentication takes a
 
 But first, let's check some small concepts.
 
-## In a hurry?
+## In a hurry? { #in-a-hurry }
 
 If you don't care about any of these terms and you just need to add security with authentication based on username and password *right now*, skip to the next chapters.
 
-## OAuth2
+## OAuth2 { #oauth2 }
 
 OAuth2 is a specification that defines several ways to handle authentication and authorization.
 
@@ -24,7 +24,7 @@ It includes ways to authenticate using a "third party".
 
 That's what all the systems with "login with Facebook, Google, Twitter, GitHub" use underneath.
 
-### OAuth 1
+### OAuth 1 { #oauth-1 }
 
 There was an OAuth 1, which is very different from OAuth2, and more complex, as it included direct specifications on how to encrypt the communication.
 
@@ -38,7 +38,7 @@ In the section about **deployment** you will see how to set up HTTPS for free, u
 
 ///
 
-## OpenID Connect
+## OpenID Connect { #openid-connect }
 
 OpenID Connect is another specification, based on **OAuth2**.
 
@@ -48,7 +48,7 @@ For example, Google login uses OpenID Connect (which underneath uses OAuth2).
 
 But Facebook login doesn't support OpenID Connect. It has its own flavor of OAuth2.
 
-### OpenID (not "OpenID Connect")
+### OpenID (not "OpenID Connect") { #openid-not-openid-connect }
 
 There was also an "OpenID" specification. That tried to solve the same thing as **OpenID Connect**, but was not based on OAuth2.
 
@@ -56,7 +56,7 @@ So, it was a complete additional system.
 
 It is not very popular or used nowadays.
 
-## OpenAPI
+## OpenAPI { #openapi }
 
 OpenAPI (previously known as Swagger) is the open specification for building APIs (now part of the Linux Foundation).
 
@@ -97,7 +97,7 @@ The most complex problem is building an authentication/authorization provider li
 
 ///
 
-## **FastAPI** utilities
+## **FastAPI** utilities { #fastapi-utilities }
 
 FastAPI provides several tools for each of these security schemes in the `fastapi.security` module that simplify using these security mechanisms.
 
index 8644db45c20b1a61699ece3a00ca9eceae22499f..470202c99953b550e3431658637e9ba0d366ab73 100644 (file)
@@ -1,4 +1,4 @@
-# OAuth2 with Password (and hashing), Bearer with JWT tokens
+# OAuth2 with Password (and hashing), Bearer with JWT tokens { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens }
 
 Now that we have all the security flow, let's make the application actually secure, using <abbr title="JSON Web Tokens">JWT</abbr> tokens and secure password hashing.
 
@@ -6,7 +6,7 @@ This code is something you can actually use in your application, save the passwo
 
 We are going to start from where we left in the previous chapter and increment it.
 
-## About JWT
+## About JWT { #about-jwt }
 
 JWT means "JSON Web Tokens".
 
@@ -26,7 +26,7 @@ After a week, the token will be expired and the user will not be authorized and
 
 If you want to play with JWT tokens and see how they work, check <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>.
 
-## Install `PyJWT`
+## Install `PyJWT` { #install-pyjwt }
 
 We need to install `PyJWT` to generate and verify the JWT tokens in Python.
 
@@ -50,7 +50,7 @@ You can read more about it in the <a href="https://pyjwt.readthedocs.io/en/lates
 
 ///
 
-## Password hashing
+## Password hashing { #password-hashing }
 
 "Hashing" means converting some content (a password in this case) into a sequence of bytes (just a string) that looks like gibberish.
 
@@ -58,13 +58,13 @@ Whenever you pass exactly the same content (exactly the same password) you get e
 
 But you cannot convert from the gibberish back to the password.
 
-### Why use password hashing
+### Why use password hashing { #why-use-password-hashing }
 
 If your database is stolen, the thief won't have your users' plaintext passwords, only the hashes.
 
 So, the thief won't be able to try to use that password in another system (as many users use the same password everywhere, this would be dangerous).
 
-## Install `passlib`
+## Install `passlib` { #install-passlib }
 
 PassLib is a great Python package to handle password hashes.
 
@@ -94,7 +94,7 @@ And your users would be able to login from your Django app or from your **FastAP
 
 ///
 
-## Hash and verify the passwords
+## Hash and verify the passwords { #hash-and-verify-the-passwords }
 
 Import the tools we need from `passlib`.
 
@@ -124,7 +124,7 @@ If you check the new (fake) database `fake_users_db`, you will see how the hashe
 
 ///
 
-## Handle JWT tokens
+## Handle JWT tokens { #handle-jwt-tokens }
 
 Import the modules installed.
 
@@ -154,7 +154,7 @@ Create a utility function to generate a new access token.
 
 {* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
 
-## Update the dependencies
+## Update the dependencies { #update-the-dependencies }
 
 Update `get_current_user` to receive the same token as before, but this time, using JWT tokens.
 
@@ -164,7 +164,7 @@ If the token is invalid, return an HTTP error right away.
 
 {* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
 
-## Update the `/token` *path operation*
+## Update the `/token` *path operation* { #update-the-token-path-operation }
 
 Create a `timedelta` with the expiration time of the token.
 
@@ -172,7 +172,7 @@ Create a real JWT access token and return it.
 
 {* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
 
-### Technical details about the JWT "subject" `sub`
+### Technical details about the JWT "subject" `sub` { #technical-details-about-the-jwt-subject-sub }
 
 The JWT specification says that there's a key `sub`, with the subject of the token.
 
@@ -194,7 +194,7 @@ So, to avoid ID collisions, when creating the JWT token for the user, you could
 
 The important thing to keep in mind is that the `sub` key should have a unique identifier across the entire application, and it should be a string.
 
-## Check it
+## Check it { #check-it }
 
 Run the server and go to the docs: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
@@ -240,7 +240,7 @@ Notice the header `Authorization`, with a value that starts with `Bearer `.
 
 ///
 
-## Advanced usage with `scopes`
+## Advanced usage with `scopes` { #advanced-usage-with-scopes }
 
 OAuth2 has the notion of "scopes".
 
@@ -250,7 +250,7 @@ Then you can give this token to a user directly or a third party, to interact wi
 
 You can learn how to use them and how they are integrated into **FastAPI** later in the **Advanced User Guide**.
 
-## Recap
+## Recap { #recap }
 
 With what you have seen up to now, you can set up a secure **FastAPI** application using standards like OAuth2 and JWT.
 
index 1b70aa8111ec0b467e710994bf4b9a528cf2609c..296e0e2950177ed057af6224e1668447b92f508a 100644 (file)
@@ -1,8 +1,8 @@
-# Simple OAuth2 with Password and Bearer
+# Simple OAuth2 with Password and Bearer { #simple-oauth2-with-password-and-bearer }
 
 Now let's build from the previous chapter and add the missing parts to have a complete security flow.
 
-## Get the `username` and `password`
+## Get the `username` and `password` { #get-the-username-and-password }
 
 We are going to use **FastAPI** security utilities to get the `username` and `password`.
 
@@ -18,7 +18,7 @@ But for the login *path operation*, we need to use these names to be compatible
 
 The spec also states that the `username` and `password` must be sent as form data (so, no JSON here).
 
-### `scope`
+### `scope` { #scope }
 
 The spec also says that the client can send another form field "`scope`".
 
@@ -44,11 +44,11 @@ For OAuth2 they are just strings.
 
 ///
 
-## Code to get the `username` and `password`
+## Code to get the `username` and `password` { #code-to-get-the-username-and-password }
 
 Now let's use the utilities provided by **FastAPI** to handle this.
 
-### `OAuth2PasswordRequestForm`
+### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform }
 
 First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` in the *path operation* for `/token`:
 
@@ -84,7 +84,7 @@ But as it's a common use case, it is provided by **FastAPI** directly, just to m
 
 ///
 
-### Use the form data
+### Use the form data { #use-the-form-data }
 
 /// tip
 
@@ -102,7 +102,7 @@ For the error, we use the exception `HTTPException`:
 
 {* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *}
 
-### Check the password
+### Check the password { #check-the-password }
 
 At this point we have the user data from our database, but we haven't checked the password.
 
@@ -112,7 +112,7 @@ You should never save plaintext passwords, so, we'll use the (fake) password has
 
 If the passwords don't match, we return the same error.
 
-#### Password hashing
+#### Password hashing { #password-hashing }
 
 "Hashing" means: converting some content (a password in this case) into a sequence of bytes (just a string) that looks like gibberish.
 
@@ -120,7 +120,7 @@ Whenever you pass exactly the same content (exactly the same password) you get e
 
 But you cannot convert from the gibberish back to the password.
 
-##### Why use password hashing
+##### Why use password hashing { #why-use-password-hashing }
 
 If your database is stolen, the thief won't have your users' plaintext passwords, only the hashes.
 
@@ -128,7 +128,7 @@ So, the thief won't be able to try to use those same passwords in another system
 
 {* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *}
 
-#### About `**user_dict`
+#### About `**user_dict` { #about-user-dict }
 
 `UserInDB(**user_dict)` means:
 
@@ -146,11 +146,11 @@ UserInDB(
 
 /// info
 
-For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user_indict){.internal-link target=_blank}.
+For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user-in-dict){.internal-link target=_blank}.
 
 ///
 
-## Return the token
+## Return the token { #return-the-token }
 
 The response of the `token` endpoint must be a JSON object.
 
@@ -182,7 +182,7 @@ For the rest, **FastAPI** handles it for you.
 
 ///
 
-## Update the dependencies
+## Update the dependencies { #update-the-dependencies }
 
 Now we are going to update our dependencies.
 
@@ -214,11 +214,11 @@ That's the benefit of standards...
 
 ///
 
-## See it in action
+## See it in action { #see-it-in-action }
 
 Open the interactive docs: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
 
-### Authenticate
+### Authenticate { #authenticate }
 
 Click the "Authorize" button.
 
@@ -234,7 +234,7 @@ After authenticating in the system, you will see it like:
 
 <img src="/img/tutorial/security/image05.png">
 
-### Get your own user data
+### Get your own user data { #get-your-own-user-data }
 
 Now use the operation `GET` with the path `/users/me`.
 
@@ -260,7 +260,7 @@ If you click the lock icon and logout, and then try the same operation again, yo
 }
 ```
 
-### Inactive user
+### Inactive user { #inactive-user }
 
 Now try with an inactive user, authenticate with:
 
@@ -278,7 +278,7 @@ You will get an "Inactive user" error, like:
 }
 ```
 
-## Recap
+## Recap { #recap }
 
 You now have the tools to implement a complete security system based on `username` and `password` for your API.
 
index eac86f7fb65ac3cb94dc0ca19fc65704d29a5c90..79538e566a839dfc1eda49bc9c2be62f02135a3e 100644 (file)
@@ -1,4 +1,4 @@
-# SQL (Relational) Databases
+# SQL (Relational) Databases { #sql-relational-databases }
 
 **FastAPI** doesn't require you to use a SQL (relational) database. But you can use **any database** that you want.
 
@@ -32,7 +32,7 @@ There is an official project generator with **FastAPI** and **PostgreSQL** inclu
 
 This is a very simple and short tutorial, if you want to learn about databases in general, about SQL, or more advanced features, go to the <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel docs</a>.
 
-## Install `SQLModel`
+## Install `SQLModel` { #install-sqlmodel }
 
 First, make sure you create your [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and then install `sqlmodel`:
 
@@ -45,13 +45,13 @@ $ pip install sqlmodel
 
 </div>
 
-## Create the App with a Single Model
+## Create the App with a Single Model { #create-the-app-with-a-single-model }
 
 We'll create the simplest first version of the app with a single **SQLModel** model first.
 
 Later we'll improve it increasing security and versatility with **multiple models** below. 🤓
 
-### Create Models
+### Create Models { #create-models }
 
 Import `SQLModel` and create a database model:
 
@@ -71,7 +71,7 @@ There are a few differences:
 
     SQLModel will know that something declared as `str` will be a SQL column of type `TEXT` (or `VARCHAR`, depending on the database).
 
-### Create an Engine
+### Create an Engine { #create-an-engine }
 
 A SQLModel `engine` (underneath it's actually a SQLAlchemy `engine`) is what **holds the connections** to the database.
 
@@ -83,13 +83,13 @@ Using `check_same_thread=False` allows FastAPI to use the same SQLite database i
 
 Don't worry, with the way the code is structured, we'll make sure we use **a single SQLModel *session* per request** later, this is actually what the `check_same_thread` is trying to achieve.
 
-### Create the Tables
+### Create the Tables { #create-the-tables }
 
 We then add a function that uses `SQLModel.metadata.create_all(engine)` to **create the tables** for all the *table models*.
 
 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *}
 
-### Create a Session Dependency
+### Create a Session Dependency { #create-a-session-dependency }
 
 A **`Session`** is what stores the **objects in memory** and keeps track of any changes needed in the data, then it **uses the `engine`** to communicate with the database.
 
@@ -99,7 +99,7 @@ Then we create an `Annotated` dependency `SessionDep` to simplify the rest of th
 
 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30]  hl[25:27,30] *}
 
-### Create Database Tables on Startup
+### Create Database Tables on Startup { #create-database-tables-on-startup }
 
 We will create the database tables when the application starts.
 
@@ -115,7 +115,7 @@ SQLModel will have migration utilities wrapping Alembic, but for now, you can us
 
 ///
 
-### Create a Hero
+### Create a Hero { #create-a-hero }
 
 Because each SQLModel model is also a Pydantic model, you can use it in the same **type annotations** that you could use Pydantic models.
 
@@ -127,25 +127,25 @@ The same way, you can declare it as the function's **return type**, and then the
 
 Here we use the `SessionDep` dependency (a `Session`) to add the new `Hero` to the `Session` instance, commit the changes to the database, refresh the data in the `hero`, and then return it.
 
-### Read Heroes
+### Read Heroes { #read-heroes }
 
 We can **read** `Hero`s from the database using a `select()`. We can include a `limit` and `offset` to paginate the results.
 
 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *}
 
-### Read One Hero
+### Read One Hero { #read-one-hero }
 
 We can **read** a single `Hero`.
 
 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *}
 
-### Delete a Hero
+### Delete a Hero { #delete-a-hero }
 
 We can also **delete** a `Hero`.
 
 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *}
 
-### Run the App
+### Run the App { #run-the-app }
 
 You can run the app:
 
@@ -165,7 +165,7 @@ Then go to the `/docs` UI, you will see that **FastAPI** is using these **models
 <img src="/img/tutorial/sql-databases/image01.png">
 </div>
 
-## Update the App with Multiple Models
+## Update the App with Multiple Models { #update-the-app-with-multiple-models }
 
 Now let's **refactor** this app a bit to increase **security** and **versatility**.
 
@@ -177,7 +177,7 @@ Additionally, we create a `secret_name` for the hero, but so far, we are returni
 
 We'll fix these things by adding a few **extra models**. Here's where SQLModel will shine. ✨
 
-### Create Multiple Models
+### Create Multiple Models { #create-multiple-models }
 
 In **SQLModel**, any model class that has `table=True` is a **table model**.
 
@@ -185,7 +185,7 @@ And any model class that doesn't have `table=True` is a **data model**, these on
 
 With SQLModel, we can use **inheritance** to **avoid duplicating** all the fields in all the cases.
 
-#### `HeroBase` - the base class
+#### `HeroBase` - the base class { #herobase-the-base-class }
 
 Let's start with a `HeroBase` model that has all the **fields that are shared** by all the models:
 
@@ -194,7 +194,7 @@ Let's start with a `HeroBase` model that has all the **fields that are shared**
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *}
 
-#### `Hero` - the *table model*
+#### `Hero` - the *table model* { #hero-the-table-model }
 
 Then let's create `Hero`, the actual *table model*, with the **extra fields** that are not always in the other models:
 
@@ -210,7 +210,7 @@ Because `Hero` inherits form `HeroBase`, it **also** has the **fields** declared
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *}
 
-#### `HeroPublic` - the public *data model*
+#### `HeroPublic` - the public *data model* { #heropublic-the-public-data-model }
 
 Next, we create a `HeroPublic` model, this is the one that will be **returned** to the clients of the API.
 
@@ -236,7 +236,7 @@ All the fields in `HeroPublic` are the same as in `HeroBase`, with `id` declared
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *}
 
-#### `HeroCreate` - the *data model* to create a hero
+#### `HeroCreate` - the *data model* to create a hero { #herocreate-the-data-model-to-create-a-hero }
 
 Now we create a `HeroCreate` model, this is the one that will **validate** the data from the clients.
 
@@ -260,7 +260,7 @@ The fields of `HeroCreate` are:
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *}
 
-#### `HeroUpdate` - the *data model* to update a hero
+#### `HeroUpdate` - the *data model* to update a hero { #heroupdate-the-data-model-to-update-a-hero }
 
 We didn't have a way to **update a hero** in the previous version of the app, but now with **multiple models**, we can do it. 🎉
 
@@ -278,7 +278,7 @@ The fields of `HeroUpdate` are:
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *}
 
-### Create with `HeroCreate` and return a `HeroPublic`
+### Create with `HeroCreate` and return a `HeroPublic` { #create-with-herocreate-and-return-a-heropublic }
 
 Now that we have **multiple models**, we can update the parts of the app that use them.
 
@@ -300,19 +300,19 @@ By declaring it in `response_model` we are telling **FastAPI** to do its thing,
 
 ///
 
-### Read Heroes with `HeroPublic`
+### Read Heroes with `HeroPublic` { #read-heroes-with-heropublic }
 
 We can do the same as before to **read** `Hero`s, again, we use `response_model=list[HeroPublic]` to ensure that the data is validated and serialized correctly.
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *}
 
-### Read One Hero with `HeroPublic`
+### Read One Hero with `HeroPublic` { #read-one-hero-with-heropublic }
 
 We can **read** a single hero:
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *}
 
-### Update a Hero with `HeroUpdate`
+### Update a Hero with `HeroUpdate` { #update-a-hero-with-heroupdate }
 
 We can **update a hero**. For this we use an HTTP `PATCH` operation.
 
@@ -322,7 +322,7 @@ Then we use `hero_db.sqlmodel_update(hero_data)` to update the `hero_db` with th
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *}
 
-### Delete a Hero Again
+### Delete a Hero Again { #delete-a-hero-again }
 
 **Deleting** a hero stays pretty much the same.
 
@@ -330,7 +330,7 @@ We won't satisfy the desire to refactor everything in this one. 😅
 
 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *}
 
-### Run the App Again
+### Run the App Again { #run-the-app-again }
 
 You can run the app again:
 
@@ -350,7 +350,7 @@ If you go to the `/docs` API UI, you will see that it is now updated, and it won
 <img src="/img/tutorial/sql-databases/image02.png">
 </div>
 
-## Recap
+## Recap { #recap }
 
 You can use <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">**SQLModel**</a> to interact with a SQL database and simplify the code with *data models*  and *table models*.
 
index 1d277a51cb312866fdee8658b0e5633ef73846e3..5b75d048b48bfa44b8d4a02a6ff9c4019635ad42 100644 (file)
@@ -1,8 +1,8 @@
-# Static Files
+# Static Files { #static-files }
 
 You can serve static files automatically from a directory using `StaticFiles`.
 
-## Use `StaticFiles`
+## Use `StaticFiles` { #use-staticfiles }
 
 * Import `StaticFiles`.
 * "Mount" a `StaticFiles()` instance in a specific path.
@@ -17,7 +17,7 @@ You could also use `from starlette.staticfiles import StaticFiles`.
 
 ///
 
-### What is "Mounting"
+### What is "Mounting" { #what-is-mounting }
 
 "Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
 
@@ -25,7 +25,7 @@ This is different from using an `APIRouter` as a mounted application is complete
 
 You can read more about this in the [Advanced User Guide](../advanced/index.md){.internal-link target=_blank}.
 
-## Details
+## Details { #details }
 
 The first `"/static"` refers to the sub-path this "sub-application" will be "mounted" on. So, any path that starts with `"/static"` will be handled by it.
 
@@ -35,6 +35,6 @@ The `name="static"` gives it a name that can be used internally by **FastAPI**.
 
 All these parameters can be different than "`static`", adjust them with the needs and specific details of your own application.
 
-## More info
+## More info { #more-info }
 
 For more details and options check <a href="https://www.starlette.io/staticfiles/" class="external-link" target="_blank">Starlette's docs about Static Files</a>.
index 35940d920495942047254e1193a6689dda352ed6..1e333c8f19a3f9e54a9d2d0be5ba381bf14694e0 100644 (file)
@@ -1,4 +1,4 @@
-# Testing
+# Testing { #testing }
 
 Thanks to <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a>, testing **FastAPI** applications is easy and enjoyable.
 
@@ -6,7 +6,7 @@ It is based on <a href="https://www.python-httpx.org" class="external-link" targ
 
 With it, you can use <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> directly with **FastAPI**.
 
-## Using `TestClient`
+## Using `TestClient` { #using-testclient }
 
 /// info
 
@@ -56,13 +56,13 @@ If you want to call `async` functions in your tests apart from sending requests
 
 ///
 
-## Separating tests
+## Separating tests { #separating-tests }
 
 In a real application, you probably would have your tests in a different file.
 
 And your **FastAPI** application might also be composed of several files/modules, etc.
 
-### **FastAPI** app file
+### **FastAPI** app file { #fastapi-app-file }
 
 Let's say you have a file structure as described in [Bigger Applications](bigger-applications.md){.internal-link target=_blank}:
 
@@ -78,7 +78,7 @@ In the file `main.py` you have your **FastAPI** app:
 
 {* ../../docs_src/app_testing/main.py *}
 
-### Testing file
+### Testing file { #testing-file }
 
 Then you could have a file `test_main.py` with your tests. It could live on the same Python package (the same directory with a `__init__.py` file):
 
@@ -97,11 +97,11 @@ Because this file is in the same package, you can use relative imports to import
 
 ...and have the code for the tests just like before.
 
-## Testing: extended example
+## Testing: extended example { #testing-extended-example }
 
 Now let's extend this example and add more details to see how to test different parts.
 
-### Extended **FastAPI** app file
+### Extended **FastAPI** app file { #extended-fastapi-app-file }
 
 Let's continue with the same file structure as before:
 
@@ -173,7 +173,7 @@ Prefer to use the `Annotated` version if possible.
 
 ////
 
-### Extended testing file
+### Extended testing file { #extended-testing-file }
 
 You could then update `test_main.py` with the extended tests:
 
@@ -202,7 +202,7 @@ If you have a Pydantic model in your test and you want to send its data to the a
 
 ///
 
-## Run it
+## Run it { #run-it }
 
 After that, you just need to install `pytest`.
 
index 4f65b3b808c771289a26729735a076eead07ff35..e9b0a9fc454bfc9f867ce3b1a14cbfec792aa17b 100644 (file)
@@ -1,4 +1,4 @@
-# Virtual Environments
+# Virtual Environments { #virtual-environments }
 
 When you work in Python projects you probably should use a **virtual environment** (or a similar mechanism) to isolate the packages you install for each project.
 
@@ -26,7 +26,7 @@ If you are ready to adopt a **tool that manages everything** for you (including
 
 ///
 
-## Create a Project
+## Create a Project { #create-a-project }
 
 First, create a directory for your project.
 
@@ -51,7 +51,7 @@ $ cd awesome-project
 
 </div>
 
-## Create a Virtual Environment
+## Create a Virtual Environment { #create-a-virtual-environment }
 
 When you start working on a Python project **for the first time**, create a virtual environment **<abbr title="there are other options, this is a simple guideline">inside your project</abbr>**.
 
@@ -114,7 +114,7 @@ You could create the virtual environment in a different directory, but there's a
 
 ///
 
-## Activate the Virtual Environment
+## Activate the Virtual Environment { #activate-the-virtual-environment }
 
 Activate the new virtual environment so that any Python command you run or package you install uses it.
 
@@ -170,7 +170,7 @@ This makes sure that if you use a **terminal (<abbr title="command line interfac
 
 ///
 
-## Check the Virtual Environment is Active
+## Check the Virtual Environment is Active { #check-the-virtual-environment-is-active }
 
 Check that the virtual environment is active (the previous command worked).
 
@@ -212,7 +212,7 @@ If it shows the `python` binary at `.venv\Scripts\python`, inside of your projec
 
 ////
 
-## Upgrade `pip`
+## Upgrade `pip` { #upgrade-pip }
 
 /// tip
 
@@ -242,7 +242,7 @@ $ python -m pip install --upgrade pip
 
 </div>
 
-## Add `.gitignore`
+## Add `.gitignore` { #add-gitignore }
 
 If you are using **Git** (you should), add a `.gitignore` file to exclude everything in your `.venv` from Git.
 
@@ -282,7 +282,7 @@ That command will create a file `.gitignore` with the content:
 
 ///
 
-## Install Packages
+## Install Packages { #install-packages }
 
 After activating the environment, you can install packages in it.
 
@@ -294,7 +294,7 @@ If you need to upgrade a version or add a new package you would **do this again*
 
 ///
 
-### Install Packages Directly
+### Install Packages Directly { #install-packages-directly }
 
 If you're in a hurry and don't want to use a file to declare your project's package requirements, you can install them directly.
 
@@ -333,7 +333,7 @@ $ uv pip install "fastapi[standard]"
 
 ////
 
-### Install from `requirements.txt`
+### Install from `requirements.txt` { #install-from-requirements-txt }
 
 If you have a `requirements.txt`, you can now use it to install its packages.
 
@@ -376,7 +376,7 @@ pydantic==2.8.0
 
 ///
 
-## Run Your Program
+## Run Your Program { #run-your-program }
 
 After you activated the virtual environment, you can run your program, and it will use the Python inside of your virtual environment with the packages you installed there.
 
@@ -390,7 +390,7 @@ Hello World
 
 </div>
 
-## Configure Your Editor
+## Configure Your Editor { #configure-your-editor }
 
 You would probably use an editor, make sure you configure it to use the same virtual environment you created (it will probably autodetect it) so that you can get autocompletion and inline errors.
 
@@ -405,7 +405,7 @@ You normally have to do this only **once**, when you create the virtual environm
 
 ///
 
-## Deactivate the Virtual Environment
+## Deactivate the Virtual Environment { #deactivate-the-virtual-environment }
 
 Once you are done working on your project you can **deactivate** the virtual environment.
 
@@ -419,7 +419,7 @@ $ deactivate
 
 This way, when you run `python` it won't try to run it from that virtual environment with the packages installed there.
 
-## Ready to Work
+## Ready to Work { #ready-to-work }
 
 Now you're ready to start working on your project.
 
@@ -433,7 +433,7 @@ Continue reading. 👇🤓
 
 ///
 
-## Why Virtual Environments
+## Why Virtual Environments { #why-virtual-environments }
 
 To work with FastAPI you need to install <a href="https://www.python.org/" class="external-link" target="_blank">Python</a>.
 
@@ -443,7 +443,7 @@ To install packages you would normally use the `pip` command that comes with Pyt
 
 Nevertheless, if you just use `pip` directly, the packages would be installed in your **global Python environment** (the global installation of Python).
 
-### The Problem
+### The Problem { #the-problem }
 
 So, what's the problem with installing packages in the global Python environment?
 
@@ -526,7 +526,7 @@ Now, imagine that with **many** other **packages** that all your **projects depe
 
 Also, depending on your operating system (e.g. Linux, Windows, macOS), it could have come with Python already installed. And in that case it probably had some packages pre-installed with some specific versions **needed by your system**. If you install packages in the global Python environment, you could end up **breaking** some of the programs that came with your operating system.
 
-## Where are Packages Installed
+## Where are Packages Installed { #where-are-packages-installed }
 
 When you install Python, it creates some directories with some files in your computer.
 
@@ -552,7 +552,7 @@ Then it will **extract** all those files and put them in a directory in your com
 
 By default, it will put those files downloaded and extracted in the directory that comes with your Python installation, that's the **global environment**.
 
-## What are Virtual Environments
+## What are Virtual Environments { #what-are-virtual-environments }
 
 The solution to the problems of having all the packages in the global environment is to use a **virtual environment for each project** you work on.
 
@@ -577,7 +577,7 @@ flowchart TB
     stone-project ~~~ azkaban-project
 ```
 
-## What Does Activating a Virtual Environment Mean
+## What Does Activating a Virtual Environment Mean { #what-does-activating-a-virtual-environment-mean }
 
 When you activate a virtual environment, for example with:
 
@@ -714,7 +714,7 @@ An important detail is that it will put the virtual environment path at the **be
 
 Activating a virtual environment also changes a couple of other things, but this is one of the most important things it does.
 
-## Checking a Virtual Environment
+## Checking a Virtual Environment { #checking-a-virtual-environment }
 
 When you check if a virtual environment is active, for example with:
 
@@ -766,7 +766,7 @@ It's useful being able to check what `python` is being used. 🤓
 
 ///
 
-## Why Deactivate a Virtual Environment
+## Why Deactivate a Virtual Environment { #why-deactivate-a-virtual-environment }
 
 For example, you could be working on a project `philosophers-stone`, **activate that virtual environment**, install packages and work with that environment.
 
@@ -820,7 +820,7 @@ I solemnly swear 🐺
 
 </div>
 
-## Alternatives
+## Alternatives { #alternatives }
 
 This is a simple guide to get you started and teach you how everything works **underneath**.
 
@@ -837,7 +837,7 @@ Once you are ready and want to use a tool to **manage the entire project**, pack
 * Make sure you have an **exact** set of packages and versions to install, including their dependencies, so that you can be sure that you can run your project in production exactly the same as in your computer while developing, this is called **locking**
 * And many other things
 
-## Conclusion
+## Conclusion { #conclusion }
 
 If you read and understood all this, now **you know much more** about virtual environments than many developers out there. 🤓