pip install fastapi
```
-You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" target="_blank">Hypercorn</a>.
+You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
```bash
pip install uvicorn

-For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/intro/">Tutorial - User Guide</a>.
+For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Spoiler alert**: the tutorial - user guide includes:
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/" target="_blank">Benchmarks</a>.
+To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Optional Dependencies
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 before hand what you are going to return.
-But you can document that in your code, using: <a href="https://fastapi.tiangolo.com/tutorial/additional-responses/" target="_blank">Additional Responses</a>.
\ No newline at end of file
+But you can document that in your code, using: [Additional Responses](additional-responses.md){.internal-link target=_blank}.
checker(q="somequery")
```
-...and pass whatever that returns as the value of the dependency in our path operation function as the parameter `fixed_content_included`:
+...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`:
```Python hl_lines="20"
{!./src/dependencies/tutorial011.py!}
These examples are intentionally simple, but show how it all works.
- In the chapters about security, you will be using utility functions that are implemented in this same way.
+ In the chapters about security, there are utility functions that are implemented in this same way.
If you understood all this, you already know how those utility tools for security work underneath.
Later, for your production application, you might want to use a database server like **PostgreSQL**.
!!! tip
- You could adopt ideas from the previous section about <a href="/tutorial/sql-databases/" target="_blank">SQLAlchemy ORM</a>, like using utility functions to perform operations in the database, independent of your **FastAPI** code.
+ You could adopt ideas from the section about SQLAlchemy ORM ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}), like using utility functions to perform operations in the database, independent of your **FastAPI** code.
This section doesn't apply those ideas, to be equivalent to the counterpart in <a href="https://www.starlette.io/database/" class="external-link" target="_blank">Starlette</a>.
## Accessing the request body in an exception handler
!!! tip
- To solve this same problem, it's probably a lot easier to [use the `body` in a custom handler for `RequestValidationError`](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-the-requestvalidationerror-body).
+ To solve this same problem, it's probably a lot easier to use the `body` in a custom handler for `RequestValidationError` ([Handling Errors](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}).
But this example is still valid and it shows how to interact with the internal components.
By default, **FastAPI** will return the responses using Starlette's `JSONResponse`.
-You can override it by returning a `Response` directly, <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">as seen in a previous section</a>.
+You can override it by returning a `Response` directly as seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}.
But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type`).
To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
* Import `HTMLResponse`.
-* Pass `HTMLResponse` as the parameter `content_type` of your path operation.
+* Pass `HTMLResponse` as the parameter `content_type` of your *path operation*.
```Python hl_lines="2 7"
{!./src/custom_response/tutorial002.py!}
### Return a Starlette `Response`
-As seen in <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">another section</a>, you can also override the response directly in your path operation, by returning it.
+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.
The same example from above, returning an `HTMLResponse`, could look like:
```
!!! warning
- A `Response` returned directly by your path operation function won't be documented in OpenAPI (for example, the `Content-Type` won't be documented) and won't be visible in the automatic interactive docs.
+ A `Response` returned directly by your *path operation function* won't be documented in OpenAPI (for example, the `Content-Type` won't be documented) and won't be visible in the automatic interactive docs.
!!! info
Of course, the actual `Content-Type` header, status code, etc, will come from the `Response` object your returned.
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.
+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
## Additional documentation
-You can also declare the media type and many other details in OpenAPI using `responses`: <a href="https://fastapi.tiangolo.com/tutorial/additional-responses/" target="_blank">Additional Responses in OpenAPI</a>.
+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}.
### Serve the static files
* Import `StaticFiles` from Starlette.
-* "Mount" it the same way you would <a href="https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/" target="_blank">mount a Sub-Application</a>.
+* "Mount" a `StaticFiles()` instance in a specific path.
```Python hl_lines="7 11"
{!./src/extending_openapi/tutorial002.py!}
### Create a *path operation* to test it
-Now, to be able to test that everything works, create a path operation:
+Now, to be able to test that everything works, create a *path operation*:
```Python hl_lines="39 40 41"
{!./src/extending_openapi/tutorial002.py!}
**FastAPI** has optional support for GraphQL (provided by Starlette directly), using the `graphene` library.
-You can combine normal FastAPI path operations with GraphQL on the same application.
+You can combine normal FastAPI *path operations* with GraphQL on the same application.
## Import and use `graphene`
--- /dev/null
+## Additional Features
+
+The main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank} should be enough to give you a tour through all the main features of **FastAPI**.
+
+In the next sections you will see other options, configurations, and additional features.
+
+!!! tip
+ The next sections are **not necessarily "advanced"**.
+
+ And it's possible that for your use case, the solution is in one of them.
+
+## Read the Tutorial first
+
+You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank}.
+
+And the next sections assume you already read it, and assume that you know those main ideas.
{!./src/nosql_databases/tutorial001.py!}
```
-We will use this model in our path operation function, so, we don't include in it the `hashed_password`.
+We will use this model in our *path operation function*, so, we don't include in it the `hashed_password`.
### `UserInDB` model
!!! note
Notice that we have a `hashed_password` and a `type` field that will be stored in the database.
- But it is not part of the general `User` model (the one we will return in the path operation).
+ But it is not part of the general `User` model (the one we will return in the *path operation*).
## Get the user
* Get the document with that ID.
* Put the contents of the document in a `UserInDB` model.
-By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your path operation function, you can more easily re-use it in multiple parts and also add <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
+By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your *path operation function*, you can more easily re-use it in multiple parts and also add <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
```Python hl_lines="37 38 39 40 41 42 43"
{!./src/nosql_databases/tutorial001.py!}
{!./src/nosql_databases/tutorial001.py!}
```
-### Create the path operation function
+### Create the *path operation function*
As our code is calling Couchbase and we are not using the <a href="https://docs.couchbase.com/python-sdk/2.5/async-programming.html#asyncio-python-3-5" class="external-link" target="_blank">experimental Python <code>await</code> support</a>, we should declare our function with normal `def` instead of `async def`.
!!! tip
The actual callback is just an HTTP request.
- When implementing the callback yourself, you could use something like <a href="https://www.encode.io/httpx/" target="_blank">HTTPX</a> or <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
+ When implementing the callback yourself, you could use something like <a href="https://www.encode.io/httpx/" class="external-link" target="_blank">HTTPX</a> or <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
## Write the callback documentation code
## OpenAPI operationId
-!!! danger
+!!! warning
If you are not an "expert" in OpenAPI, you probably don't need this.
-You can set the OpenAPI `operationId` to be used in your path operation with the parameter `operation_id`.
+You can set the OpenAPI `operationId` to be used in your *path operation* with the parameter `operation_id`.
You would have to make sure that it is unique for each operation.
## 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`;
+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`;
```Python hl_lines="6"
{!./src/path_operation_advanced_configuration/tutorial003.py!}
-You probably read before that you can set a <a href="https://fastapi.tiangolo.com/tutorial/response-status-code/" target="_blank">default Response Status Code</a>.
+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 a `Response` parameter
-You can declare a parameter of type `Response` in your *path operation function*, the same way you can declare a `Request` parameter.
+You can declare a parameter of type `Response` in your *path operation function*.
And then you can set headers in that *temporal* response object.
You can also create cookies when returning a `Response` directly in your code.
-To do that, you can create a response as described in <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">Return a Response directly</a>.
+To do that, you can create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank}.
Then set Cookies in it, and then return it:
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.
-By default, **FastAPI** would automatically convert that return value to JSON using the <a href="https://fastapi.tiangolo.com/tutorial/encoder/" target="_blank">`jsonable_encoder`</a>.
+By default, **FastAPI** would automatically convert that return value to JSON using the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a Starlette `JSONResponse` that would be used to send the response to the client.
When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically.
-But you can still <a href="https://fastapi.tiangolo.com/tutorial/additional-responses/" target="_blank">document it</a>.
+But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
-In the next sections you will see how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc.
-
-You will also see how to use them to set response Headers and Cookies.
+You can see in later sections how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc.
## Use a `Response` parameter
-You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies), the same way you can declare a `Request` parameter.
+You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies).
And then you can set headers in that *temporal* response object.
You can also add headers when you return a `Response` directly.
-Create a response as described in <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">Return a Response directly</a> and pass the headers as an additional parameter:
+Create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank} and pass the headers as an additional parameter:
```Python hl_lines="10 11 12"
{!./src/response_headers/tutorial001.py!}
Have 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>.
-But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your <a href="https://fastapi.tiangolo.com/tutorial/cors/" target="_blank">CORS configurations</a>, using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
+But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
--- /dev/null
+## Additional Features
+
+There are some extra features to handle security apart from the ones covered in the [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
+
+!!! tip
+ The next sections are **not necessarily "advanced"**.
+
+ And it's possible that for your use case, the solution is in one of them.
+
+## Read the Tutorial first
+
+The next sections assume you already read the main [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
+
+They are all based on the same concepts, but allow some extra functionalities.
These scopes represent "permissions".
-In OpenAPI (e.g. the API docs), you can define "security schemes", the same as you saw in the previous sections.
+In OpenAPI (e.g. the API docs), you can define "security schemes".
When one of these security schemes uses OAuth2, you can also declare and use scopes.
+Each "scope" is just a string (without spaces).
+
+They are normally used to declare specific security permissions, for example:
+
+* `users:read` or `users:write` are common examples.
+* `instagram_basic` is used by Facebook / Instagram.
+* `https://www.googleapis.com/auth/drive` is used by Google.
+
+!!! info
+ In OAuth2 a "scope" is just a string that declares a specific permission required.
+
+ It doesn't matter if it has other characters like `:` or if it is a URL.
+
+ Those details are implementation specific.
+
+ For OAuth2 they are just strings.
+
## Global view
-First, let's quickly see the parts that change from the previous section about OAuth2 and JWT. Now using OAuth2 scopes:
+First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
```Python hl_lines="2 5 9 13 48 66 107 109 110 111 112 113 114 115 116 117 123 124 125 126 130 131 132 133 134 135 136 141 155"
{!./src/security/tutorial005.py!}
But by using `Security` instead of `Depends`, **FastAPI** will know that it can declare security scopes, use them internally, and document the API with OpenAPI.
- But when you import `Query`, `Path`, `Depends`, `Security` and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+ But when you import `Query`, `Path`, `Depends`, `Security` and others from `fastapi`, those are actually functions that return special classes.
## Use `SecurityScopes`
!!! tip
The important and "magic" thing here is that `get_current_user` will have a different list of `scopes` to check for each *path operation*.
- All depending on the `scopes` declared in each *path operation* and each dependency in the dependency tree for that specific path operation.
+ All depending on the `scopes` declared in each *path operation* and each dependency in the dependency tree for that specific *path operation*.
## More details about `SecurityScopes`
Because the `SecurityScopes` will have all the scopes declared by dependants, you can use it to verify that a token has the required scopes in a central dependency function, and then declare different scope requirements in different *path operations*.
-They will be checked independently for each path operation.
+They will be checked independently for each *path operation*.
## Check it
## `Security` in decorator `dependencies`
-The same way you can define a `list` of <a href="https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/" target="_blank">`Depends` in the decorator's `dependencies` parameter</a>, you could also use `Security` with `scopes` there.
+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.
!!! warning
- If you are just starting, the <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQLAlchemy tutorial</a> should be enough.
+ If you are just starting, the tutorial [SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank} that uses SQLAlchemy should be enough.
Feel free to skip this.
-If you are starting a project from scratch, you are probably better off with <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQLAlchemy ORM</a>, or any other async ORM.
+If you are starting a project from scratch, you are probably better off with SQLAlchemy ORM ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}), or any other async ORM.
If you already have a code base that uses <a href="http://docs.peewee-orm.com/en/latest/" class="external-link" target="_blank">Peewee ORM</a>, you can check here how to use it with **FastAPI**.
Nevertheless, it's possible to do it, and here you'll see exactly what code you have to add to be able to use Peewee with FastAPI.
!!! note "Technical Details"
- You can read more about Peewee's stand about async in Python <a href="http://docs.peewee-orm.com/en/latest/peewee/database.html#async-with-gevent" target="_blank">in the docs</a>, <a href="https://github.com/coleifer/peewee/issues/263#issuecomment-517347032" target="_blank">an issue</a>, <a href="https://github.com/coleifer/peewee/pull/2072#issuecomment-563215132" class="external-link" target="_blank">a PR</a>.
+ You can read more about Peewee's stand about async in Python <a href="http://docs.peewee-orm.com/en/latest/peewee/database.html#async-with-gevent" class="external-link" target="_blank">in the docs</a>, <a href="https://github.com/coleifer/peewee/issues/263#issuecomment-517347032" class="external-link" target="_blank">an issue</a>, <a href="https://github.com/coleifer/peewee/pull/2072#issuecomment-563215132" class="external-link" target="_blank">a PR</a>.
## The same app
-We are going to create the same application as in the <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQLAlchemy tutorial</a>.
+We are going to create the same application as in the SQLAlchemy tutorial ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}).
Most of the code is actually the same.
!!! info "Technical Details"
- Exactly the same technical details as in the <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/#note" target="_blank">SQLAlchemy tutorial</a> apply.
+ Exactly the same technical details as in [SQL (Relational) Databases](../tutorial/sql-databases.md#note){.internal-link target=_blank} apply.
### Make Peewee async-compatible `PeeweeConnectionState`
list(models.User.select())
```
-This is for the same reason that we had to create a custom `PeeweeGetterDict`. But by returning something that is already a `list` instead of the `peewee.ModelSelect` the `response_model` in the path operation with `List[models.User]` (that we'll see later) will work correctly.
+This is for the same reason that we had to create a custom `PeeweeGetterDict`. But by returning something that is already a `list` instead of the `peewee.ModelSelect` the `response_model` in the *path operation* with `List[models.User]` (that we'll see later) will work correctly.
## Main **FastAPI** app
### Top-level application
-First, create the main, top-level, **FastAPI** application, and its path operations:
+First, create the main, top-level, **FastAPI** application, and its *path operations*:
```Python hl_lines="3 6 7 8"
{!./src/sub_applications/tutorial001.py!}
### Sub-application
-Then, create your sub-application, and its path operations.
+Then, create your sub-application, and its *path operations*.
This sub-application is just another standard FastAPI application, but this is the one that will be "mounted".
--- /dev/null
+## Testing Events, `startup` and `shutdown`
+
+When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement:
+
+```Python hl_lines="9 10 11 12 20 21 22 23 24"
+{!./src/app_testing/tutorial003.py!}
+```
\ No newline at end of file
--- /dev/null
+## Testing WebSockets
+
+You can use the same `TestClient` to test WebSockets.
+
+For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket:
+
+```Python hl_lines="27 28 29 30 31"
+{!./src/app_testing/tutorial002.py!}
+```
response = requests.get("http://example.com/some/url")
```
-The FastAPI counterpart API path operation could look like:
+The FastAPI counterpart API *path operation* could look like:
```Python hl_lines="1"
@app.get("/some/url")
* <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
* <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
-And these same full-stack generators were the base of the <a href="/project-generation/" target="_blank">**FastAPI** project generator</a>.
+And these same full-stack generators were the base of the [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}.
!!! info
Flask-apispec was created by the same Marshmallow developers.
You can combine it with Gunicorn, to have an asynchronous multi-process server.
- Check more details in the <a href="/deployment/" target="_blank">Deployment</a> section.
+ Check more details in the [Deployment](deployment.md){.internal-link target=_blank} section.
## Benchmarks and speed
-To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](/benchmarks/).
\ No newline at end of file
+To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](benchmarks.md){.internal-link target=_blank}.
-Details about the `async def` syntax for path operation functions and some background about asynchronous code, concurrency, and parallelism.
-
+Details about the `async def` syntax for *path operation functions* and some background about asynchronous code, concurrency, and parallelism.
## In a hurry?
If you are using third party libraries that tell you to call them with `await`, like:
-
```Python
results = await some_library()
```
-Then, declare your path operation functions with `async def` like:
+Then, declare your *path operation functions* with `async def` like:
```Python hl_lines="2"
@app.get('/')
---
-If you are using a third party library that communicates with something (a database, an API, the file system, etc) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your path operation functions as normally, with just `def`, like:
+If you are using a third party library that communicates with something (a database, an API, the file system, etc) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like:
```Python hl_lines="2"
@app.get('/')
---
-**Note**: you can mix `def` and `async def` in your path operation functions as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
+**Note**: you can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast.
But by following the steps above, it will be able to do some performance optimizations.
-
## Technical Details
Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax.
* **`async` and `await`**
* **Coroutines**
-
## Asynchronous Code
Asynchronous code just means that the language has a way to tell the computer / program that at some point in the code, he will have to wait for *something else* to finish somewhere else. Let's say that *something else* is called "slow-file".
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
This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**.
To see the difference, imagine the following story about 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.
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
You go with your crush to get parallel fast food.
You probably wouldn't want to take your crush with you to do errands at the bank.
-
### 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.
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?
Nope! That's not the moral of the story.
* **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
With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attractive of NodeJS).
That, plus the simple fact that Python is the main language for **Data Science**, Machine Learning and especially Deep Learning, make FastAPI a very good match for Data Science / Machine Learning web APIs and applications (among many others).
-To see how to achieve this parallelism in production see the section about [Deployment](deployment.md).
-
+To see how to achieve this parallelism in production see the section about [Deployment](deployment.md){.internal-link target=_blank}.
## `async` and `await`
---
-So, if you are using a library that tells you that you can call it with `await`, you need to create the path operation functions that uses it with `async def`, like in:
+So, if you are using a library that tells you that you can call it with `await`, you need to create the *path operation functions* that uses it with `async def`, like in:
```Python hl_lines="2 3"
@app.get('/burgers')
So, about the egg and the chicken, how do you call the first `async` function?
-If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your path operation function, and FastAPI will know how to do the right thing.
+If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your *path operation function*, and FastAPI will know how to do the right thing.
But if you want to use `async` / `await` without FastAPI, <a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" class="external-link" target="_blank">check the official Python docs</a>.
-
### Other forms of asynchronous code
This style of using `async` and `await` is relatively new in the language.
In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which lead to <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
-
## 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.
All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance.
-
## Very Technical Details
!!! warning
If you are coming from another async framework that does not work in the way described above and you are used to define trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">IO</abbr>.
-Still, in both situations, chances are that **FastAPI** will <a href="https://fastapi.tiangolo.com/#performance" target="_blank">still be faster</a> than (or at least comparable to) your previous framework.
+Still, in both situations, chances are that **FastAPI** will [still be faster](/#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework.
### Dependencies
-First, you might want to see the basic ways to <a href="https://fastapi.tiangolo.com/help-fastapi/" target="_blank">help FastAPI and get help</a>.
+First, you might want to see the basic ways to [help FastAPI and get help](help-fastapi.md){.internal-link target=_blank}.
## Developing
a.external-link::after {
- content: " [↪]";
+ /* \00A0 is a non-breaking space
+ to make the mark be on the same line as the link
+ */
+ content: "\00A0[↪]";
+}
+
+a.internal-link::after {
+ /* \00A0 is a non-breaking space
+ to make the mark be on the same line as the link
+ */
+ content: "\00A0↪";
}
#### Bigger Applications
-If you followed the section about creating <a href="https://fastapi.tiangolo.com/tutorial/bigger-applications/" target="_blank">Bigger Applications with Multiple Files
-</a>, your `Dockerfile` might instead look like:
+If you followed the section about creating [Bigger Applications with Multiple Files](tutorial/bigger-applications.md){.internal-link target=_blank}, your `Dockerfile` might instead look like:
```Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
### Deploy a FastAPI application
-The easiest way to set everything up, would be using the <a href="/project-generation/" target="_blank">FastAPI project generator</a>.
+The easiest way to set everything up, would be using the [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}.
It is designed to be integrated with this Docker Swarm cluster with Traefik and HTTPS described above.
It's all based on standard **Python 3.6 type** declarations (thanks to Pydantic). No new syntax to learn. Just standard modern Python.
-If you need a 2 minute refresher of how to use Python types (even if you don't use FastAPI), check the tutorial section: [Python types](python-types.md).
+If you need a 2 minute refresher of how to use Python types (even if you don't use FastAPI), check the short tutorial: [Python Types](python-types.md){.internal-link target=_blank}.
You write standard Python with types:
All the security schemes defined in OpenAPI, including:
* HTTP Basic.
-* **OAuth2** (also with **JWT tokens**). Check the [tutorial on OAuth2 with JWT](tutorial/security/oauth2-jwt.md).
+* **OAuth2** (also with **JWT tokens**). Check the tutorial on [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* API keys in:
* Headers.
* Query parameters.
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.
* Even dependencies can have dependencies, creating a hierarchy or **"graph" of dependencies**.
-* All **automatically handled** by the framework.
+* All **automatically handled** by the framework.
* All the dependencies can require data from requests and **augment the path operation** constraints and automatic documentation.
-* **Automatic validation** even for path operation parameters defined in dependencies.
+* **Automatic validation** even for *path operation* parameters defined in dependencies.
* Support for complex user authentication systems, **database connections**, etc.
* **No compromise** with databases, frontends, etc. But easy integration with all of them.
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.
+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
The history of **FastAPI** is in great part the history of its predecessors.
-As said in the section <a href="https://fastapi.tiangolo.com/alternatives/" target="_blank">Alternatives</a>:
+As said in the section [Alternatives](alternatives.md){.internal-link target=_blank}:
<blockquote markdown="1">
**FastAPI** has a great future ahead.
-And <a href="https://fastapi.tiangolo.com/help-fastapi/" target="_blank">your help</a> is greatly appreciated.
+And [your help](help-fastapi.md){.internal-link target=_blank} is greatly appreciated.
pip install fastapi
```
-You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" target="_blank">Hypercorn</a>.
+You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
```bash
pip install uvicorn

-For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/intro/">Tutorial - User Guide</a>.
+For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Spoiler alert**: the tutorial - user guide includes:
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/" target="_blank">Benchmarks</a>.
+To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Optional Dependencies
* Docker Swarm Mode deployment.
* **Docker Compose** integration and optimization for local development
* **Production ready** Python web server using Uvicorn and Gunicorn.
-* Python **[FastAPI](https://github.com/tiangolo/fastapi)** backend:
+* Python <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">**FastAPI**</a> backend:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic).
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
* **Short**: Minimize code duplication. Multiple features from each parameter declaration.
* **Robust**: Get production-ready code. With automatic interactive documentation.
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
- * [**Many other features**](https://github.com/tiangolo/fastapi) including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
+ * Many other features including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
* **Secure password** hashing by default.
* **JWT token** authentication.
* **SQLAlchemy** models (independent of Flask extensions, so they can be used with Celery workers directly).
* Docker Swarm Mode deployment.
* **Docker Compose** integration and optimization for local development.
* **Production ready** Python web server using Uvicorn and Gunicorn.
-* Python **[FastAPI](https://github.com/tiangolo/fastapi)** backend:
+* Python <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">**FastAPI**</a> backend:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic).
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
* **Short**: Minimize code duplication. Multiple features from each parameter declaration.
* **Robust**: Get production-ready code. With automatic interactive documentation.
* **Standards-based**: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
- * [**Many other features**](https://github.com/tiangolo/fastapi) including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
+ * Many other features including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
* **Secure password** hashing by default.
* **JWT token** authentication.
* **CORS** (Cross Origin Resource Sharing).
{!./src/python_types/tutorial004.py!}
```
-
## Declaring types
You just saw the main place to declare type hints. As function parameters.
* 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).
-
### Classes as types
You can also declare a class as the type of a variable.
<img src="/img/python-types/image06.png">
-
## Pydantic models
<a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> is a Python library to perform data validation.
**FastAPI** is all based on Pydantic.
-You will see a lot more of all this in practice in the <a href="/tutorial/intro/" target="_blank">Tutorial - User Guide</a> (the next section).
-
+You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/){.internal-link target=_blank}.
## Type hints in **FastAPI**
* **Document** the API using OpenAPI:
* which is then used by the automatic interactive documentation user interfaces.
-This might all sound abstract. Don't worry. You'll see all this in action in the <a href="/tutorial/intro/" target="_blank">Tutorial - User Guide</a> (the next section).
+This might all sound abstract. Don't worry. You'll see all this in action in the [Tutorial - User Guide](tutorial/){.internal-link target=_blank}.
The important thing is that by using standard Python types, in a single place (instead of adding more classes, decorators, etc), **FastAPI** will do a lot of the work for you.
**FastAPI** will create the object of type `BackgroundTasks` for you and pass it as that parameter.
-!!! tip
- You declare a parameter of `BackgroundTasks` and use it in a very similar way as to when <a href="/tutorial/using-request-directly/" target="_blank">using the `Request` directly</a>.
-
## Create a task function
Create a function to be run as the background task.
They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers.
-To see an example, check the <a href="https://fastapi.tiangolo.com/project-generation/" target="_blank">Project Generators</a>, they all include Celery already configured.
+To see an example, check the [Project Generators](../project-generation.md){.internal-link target=_blank}, they all include Celery already configured.
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`.
{!./src/bigger_applications/app/routers/users.py!}
```
-### Path operations with `APIRouter`
+### *Path operations* with `APIRouter`
And then you use it to declare your *path operations*.
Let's say you also have the endpoints dedicated to handling "Items" from your application in the module at `app/routers/items.py`.
-You have path operations for:
+You have *path operations* for:
* `/items/`
* `/items/{item_id}`
But, remember that we were lazy and didn't add `/items/` nor `tags` to all the *path operations*?
-We can add a prefix to all the path operations using the parameter `prefix` of `app.include_router()`.
+We can add a prefix to all the *path operations* using the parameter `prefix` of `app.include_router()`.
-As the path of each path operation has to start with `/`, like in:
+As the path of each *path operation* has to start with `/`, like in:
```Python hl_lines="1"
@router.get("/{item_id}")
* The *path operation* that declared a custom `403` response will have both the predefined responses (`404`) and the `403` declared in it directly.
* All these *path operations* will have the list of `dependencies` evaluated/executed before them.
* If you also declare dependencies in a specific *path operation*, **they will be executed too**.
- * The router dependencies are executed first, then the <a href="https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-decorator/" target="_blank">`dependencies` in the decorator</a>, and then the normal parameter dependencies.
- * You can also add <a href="https://fastapi.tiangolo.com/tutorial/security/oauth2-scopes/" target="_blank">`Security` dependencies with `scopes`</a>.
+ * The router dependencies are executed first, then the [`dependencies` in the decorator](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, and then the normal parameter dependencies.
+ * You can also add [`Security` dependencies with `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}.
!!! tip
Having `dependencies` in a decorator can be used, for example, to require authentication for a whole group of *path operations*. Even if the dependencies are not added individually to each one of them.
The `prefix`, `tags`, `responses` and `dependencies` parameters are (as in many other cases) just a feature from **FastAPI** to help you avoid code duplication.
!!! tip
- You could also add path operations directly, for example with: `@app.get(...)`.
+ You could also add *path operations* directly, for example with: `@app.get(...)`.
Apart from `app.include_router()`, in the same **FastAPI** app.
The `APIRouter`s are not "mounted", they are not isolated from the rest of the application.
- This is because we want to include their path operations in the OpenAPI schema and the user interfaces.
+ This is because we want to include their *path operations* in the OpenAPI schema and the user interfaces.
- As we cannot just isolate them and "mount" them independently of the rest, the path operations are "cloned" (re-created), not included directly.
+ As we cannot just isolate them and "mount" them independently of the rest, the *path operations* are "cloned" (re-created), not included directly.
## Check the automatic API docs
-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`.
+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`
`Body` also returns objects of a subclass of `FieldInfo` directly. And there are others you will see later that are subclasses of the `Body` class.
- Remember that when you import `Query`, `Path`, and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+ Remember that when you import `Query`, `Path`, and others from `fastapi`, those are actually functions that return special classes.
!!! tip
- Notice how each model's attribute with a type, default value and `Field` has the same structure as a path operation function's parameter, with `Field` instead of `Path`, `Query` and `Body`.
+ Notice how each model's attribute with a type, default value and `Field` has the same structure as a *path operation function's* parameter, with `Field` instead of `Path`, `Query` and `Body`.
## JSON Schema extras
!!! note
Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value.
-
## Multiple body parameters
-In the previous example, the path operations would expect a JSON body with the attributes of an `Item`, like:
+In the previous example, the *path operations* would expect a JSON body with the attributes of an `Item`, like:
```JSON
{
## Recap
-You can add multiple body parameters to your path operation function, even though a request can only have a single body.
+You can add multiple body parameters to your *path operation function*, even though a request can only have a single body.
-But **FastAPI** will handle it, give you the correct data in your function, and validate and document the correct schema in the path operation.
+But **FastAPI** will handle it, give you the correct data in your function, and validate and document the correct schema in the *path operation*.
You can also declare singular values to be received as part of the body.
Apart from normal singular types like `str`, `int`, `float`, etc. You can use more complex singular types that inherit from `str`.
-To see all the options you have, checkout the docs for <a href="https://pydantic-docs.helpmanual.io/#exotic-types" class="external-link" target="_blank">Pydantic's exotic types</a>. You will see some examples in the next chapter.
+To see all the options you have, checkout the docs for <a href="https://pydantic-docs.helpmanual.io/usage/types/" class="external-link" target="_blank">Pydantic's exotic types</a>. You will see some examples in the next chapter.
For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `HttpUrl`:
So, if you want to receive partial updates that can omit all the attributes, you need to have a model with all the attributes marked as optional (with default values or `None`).
- To distinguish from the models with all optional values for **updates** and models with required values for **creation**, you can use the ideas described in <a href="https://fastapi.tiangolo.com/tutorial/extra-models/" target="_blank">Extra Models</a>.
+ To distinguish from the models with all optional values for **updates** and models with required values for **creation**, you can use the ideas described in [Extra Models](extra-models.md){.internal-link target=_blank}.
## Declare it as a parameter
-To add it to your path operation, declare it the same way you declared path and query parameters:
+To add it to your *path operation*, declare it the same way you declared path and query parameters:
```Python hl_lines="16"
{!./src/body/tutorial001.py!}
<img src="/img/tutorial/body/image01.png">
-And will be also used in the API docs inside each path operation that needs them:
+And will be also used in the API docs inside each *path operation* that needs them:
<img src="/img/tutorial/body/image02.png">
!!! note "Technical Details"
`Cookie` is a "sister" class of `Path` and `Query`. It also inherits from the same common `Param` class.
- But remember that when you import `Query`, `Path`, `Cookie` and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+ But remember that when you import `Query`, `Path`, `Cookie` and others from `fastapi`, those are actually functions that return special classes.
!!! info
To declare cookies, you need to use `Cookie`, because otherwise the parameters would be interpreted as query parameters.
## A `dict` from the previous example
-In the previous example, we are returning a `dict` from our dependency ("dependable"):
+In the previous example, we were returning a `dict` from our dependency ("dependable"):
```Python hl_lines="7"
{!./src/dependencies/tutorial001.py!}
```
-But then we get a `dict` in the parameter `commons` of the path operation function.
+But then we get a `dict` in the parameter `commons` of the *path operation function*.
And we know that editors can't provide a lot of support (like completion) for `dict`s, because they can't know their keys and value types.
What FastAPI actually checks is that it is a "callable" (function, class or anything else) and the parameters defined.
-If you pass a "callable" as a dependency in **FastAPI**, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a path operation function. Including sub-dependencies.
+If you pass a "callable" as a dependency in **FastAPI**, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a *path operation function*. Including sub-dependencies.
-That also applies to callables with no parameters at all. The same as it would be for path operation functions with no parameters.
+That also applies to callables with no parameters at all. The same as it would be for *path operation functions* with no parameters.
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParameters`:
commons: CommonQueryParams = Depends()
```
-So, you can declare the dependency as the type of the variable, and use `Depends()` as the "default" value, without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
+So, you can declare the dependency as the type of the variable, and use `Depends()` as the "default" value (the value after the `=`) for that function's parameter, without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
So, the same example would look like:
## Dependencies for a group of *path operations*
-Later, when reading about how to <a href="https://fastapi.tiangolo.com/tutorial/bigger-applications/" target="_blank">structure bigger applications</a>, possibly with multiple files, you will learn how to declare a single `dependencies` parameter 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*.
!!! info
For this to work, you need to use **Python 3.7** or above, or in **Python 3.6**, install the "backports":
- ```bash
+ ```
pip install async-exit-stack async-generator
```
- This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" target="_blank">async-generator</a>.
+ This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
!!! note "Technical Details"
Any function that is valid to use with:
print(contents)
```
-Underneath, the `open("./somefile.txt")` returns an object that is a called a "Context Manager".
+Underneath, the `open("./somefile.txt")` creates an object that is a called a "Context Manager".
When the `with` block finishes, it makes sure to close the file, even if there were exceptions.
If you are just starting with **FastAPI** you might want to skip it for now.
-In Python, you can create context managers by <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank">creating a class with two methods: `__enter__()` and `__exit__()`</a>.
+In Python, you can create Context Managers by <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank">creating a class with two methods: `__enter__()` and `__exit__()`</a>.
-You can also use them with **FastAPI** dependencies with `yield` by using
+You can also use them inside of **FastAPI** dependencies with `yield` by using
`with` or `async with` statements inside of the dependency function:
```Python hl_lines="1 2 3 4 5 6 7 8 9 13"
It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
-## "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".
+**"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".
And then, that system (in this case **FastAPI**) will take care of doing whatever is needed to provide your code with those needed dependencies ("inject" the dependencies).
* Have shared logic (the same code logic again and again).
* Share database connections.
* Enforce security, authentication, role requirements, etc.
-* etc.
+* And many other things...
All these, while minimizing code repetition.
Let's first focus on the dependency.
-It is just a function that can take all the same parameters that a path operation function can take:
+It is just a function that can take all the same parameters that a *path operation function* can take:
```Python hl_lines="6 7"
{!./src/dependencies/tutorial001.py!}
**2 lines**.
-And it has the same shape and structure that all your path operation functions.
+And it has the same shape and structure that all your *path operation functions*.
-You can think of it as a path operation function without the "decorator" (without the `@app.get("/some-path")`).
+You can think of it as a *path operation function* without the "decorator" (without the `@app.get("/some-path")`).
And it can return anything you want.
### 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:
+The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
```Python hl_lines="11 16"
{!./src/dependencies/tutorial001.py!}
This parameter must be something like a function.
-And that function takes parameters in the same way that path operation functions do.
+And that function takes parameters in the same way that *path operation functions* do.
!!! tip
You'll see what other "things", apart from functions, can be used as dependencies in the next chapter.
* Calling your dependency ("dependable") function with the correct parameters.
* Get the result from your function.
-* Assign that result to the parameter in your path operation function.
+* Assign that result to the parameter in your *path operation function*.
-!!! note
+!!! check
Notice that you don't have to create a special class and pass it somewhere to **FastAPI** to "register" it or anything similar.
You just pass it to `Depends` and **FastAPI** knows how to do the rest.
## 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.
+As dependencies will also be called by **FastAPI** (the same as your *path operation functions*), the same rules apply while defining your functions.
You can use `async def` or normal `def`.
-And you can declare dependencies with `async def` inside of normal `def` path operation functions, or `def` dependencies inside of `async def` path operation functions, etc.
+And you can declare dependencies with `async def` inside of normal `def` *path operation functions*, or `def` dependencies inside of `async def` *path operation functions*, etc.
It doesn't matter. **FastAPI** will know what to do.
!!! note
- If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
-
+ If you don't know, check the [Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank} section about `async` and `await` in the docs.
## Integrated with OpenAPI
You never call those functions directly. They are called by your framework (in this case, **FastAPI**).
-With the Dependency Injection system, you can also tell **FastAPI** that your path operation function also "depends" on something else that should be executed before your *path operation function*, and **FastAPI** will take care of executing it and "injecting" the results.
+With the Dependency Injection system, you can also tell **FastAPI** that your *path operation function* also "depends" on something else that should be executed before your *path operation function*, and **FastAPI** will take care of executing it and "injecting" the results.
Other common terms for this same idea of "dependency injection" are:
## **FastAPI** plug-ins
-Integrations and "plug-in"s 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.
+Integrations and "plug-in"s 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*.
-And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, _literally_.
+And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, *literally*.
You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
## Integrated with **OpenAPI**
-All these dependencies, while declaring their requirements, add parameters, validations, etc. to your path operations.
+All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your *path operations*.
**FastAPI** will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.
-You can create dependencies that have sub-dependencies.
+You can create dependencies that have **sub-dependencies**.
-They can be as "deep" as you need them to be.
+They can be as **deep** as you need them to be.
**FastAPI** will take care of solving them.
```
!!! info
- Notice that we are only declaring one dependency in the path operation function, the `query_or_cookie_extractor`.
+ Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`.
But **FastAPI** will know that it has to solve `query_extractor` first, to pass the results of that to `query_or_cookie_extractor` while calling it.
Apart from all the fancy words used here, the **Dependency Injection** system is quite simple.
-Just functions that look the same as the path operation functions.
+Just functions that look the same as the *path operation functions*.
But still, it is very powerful, and allows you to declare arbitrarily deeply nested dependency "graphs" (trees).
## Example
-Here's an example path operation with parameters using some of the above types.
+Here's an example *path operation* with parameters using some of the above types.
```Python hl_lines="1 2 11 12 13 14 15"
{!./src/extra_data_types/tutorial001.py!}
!!! danger
Never store user's plaintext passwords. Always store a "secure hash" that you can then verify.
- If you don't know, you will learn what a "password hash" is in the <a href="/tutorial/security/simple-oauth2/#password-hashing" target="_blank">security chapters</a>.
+ If you don't know, you will learn what a "password hash" is in the [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.
## Multiple models
uvicorn main:my_awesome_api --reload
```
-### Step 3: create a path operation
+### Step 3: create a *path operation*
#### Path
We are going to call them "**operations**" too.
-#### Define a path operation function
+#### Define a *path operation function*
```Python hl_lines="6"
{!./src/first_steps/tutorial001.py!}
```
!!! note
- If you don't know the difference, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
+ If you don't know the difference, check the [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
### Step 5: return the content
Because it's a Python exception, you don't `return` it, you `raise` it.
-This also means that if you are inside a utility function that you are calling inside of your path operation function, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the path operation function, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client.
+This also means that if you are inside a utility function that you are calling inside of your *path operation function*, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the *path operation function*, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client.
The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security.
But when you register an exception handler, you should register it for Starlette's `HTTPException`.
-This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises an `HTTPException`, your handler will be able to catch handle it.
+This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises an `HTTPException`, your handler will be able to catch and handle it.
In this example, to be able to have both `HTTPException`s in the same code, Starlette's exceptions is renamed to `StarletteHTTPException`:
You can import and re-use the default exception handlers from `fastapi.exception_handlers`:
```Python hl_lines="2 3 4 5 15 21"
-{!./src/handling_errors/tutorial005.py!}
+{!./src/handling_errors/tutorial006.py!}
```
-In this example, you are just `print`ing the error with a very expressive notification.
+In this example, you are just `print`ing the error with a very expressive message.
But you get the idea, you can use the exception and then just re-use the default exception handlers.
!!! note "Technical Details"
`Header` is a "sister" class of `Path`, `Query` and `Cookie`. It also inherits from the same common `Param` class.
- But remember that when you import `Query`, `Path`, `Header`, and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+ But remember that when you import `Query`, `Path`, `Header`, and others from `fastapi`, those are actually functions that return special classes.
!!! info
To declare headers, you need to use `Header`, because otherwise the parameters would be interpreted as query parameters.
-This tutorial shows you how to use **FastAPI** with all its features, step by step.
+This tutorial shows you how to use **FastAPI** with most of its features, step by step.
Each section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
!!! note
You can also install it part by part.
-
+
This is what you would probably do once you want to deploy your application to production:
```
```
And the same for each of the optional dependencies that you want to use.
+
+## Advanced User Guide
+
+There is also an **Advanced User Guide** that you can read later after this **Tutorial - User guide**.
+
+The **Advanced User Guide**, builds on this, uses the same concepts, and teaches you some extra features.
+
+But you should first read the **Tutorial - User guide** (what you are reading right now).
+
+It's designed so that you can build a complete application with just the **Tutorial - User guide**, and then extend it in different ways, depending on your needs, using some of the additional ideas from the **Advanced User Guide**.
{!./src/middleware/tutorial001.py!}
```
-!!! tip
- This technique is used in the tutorial about <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQL (Relational) Databases</a>.
-
!!! tip
Have 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>.
- But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your <a href="https://fastapi.tiangolo.com/tutorial/cors/" target="_blank">CORS configurations</a>, using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
+ But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)
+](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
### Before and after the `response`
-You can add code to be run with the `request`, before any *path operation* receives it.
+You can add code to be run with the `request`, before any *path operation* receives it.
And also after the `response` is generated, before returning it.
-There are several parameters that you can pass to your path operation decorator to configure it.
+There are several parameters that you can pass to your *path operation decorator* to configure it.
!!! warning
- Notice that these parameters are passed directly to the path operation decorator, not to your path operation function.
+ Notice that these parameters are passed directly to the *path operation decorator*, not to your *path operation function*.
## Response Status Code
-You can define the (HTTP) `status_code` to be used in the response of your path operation.
+You can define the (HTTP) `status_code` to be used in the response of your *path operation*.
You can pass directly the `int` code, like `404`.
## Tags
-You can add tags to your path operation, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
+You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
```Python hl_lines="17 22 27"
{!./src/path_operation_configuration/tutorial002.py!}
## 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.
+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.
-You can write <a href="https://en.wikipedia.org/wiki/Markdown" class="target-blank" target="_blank">Markdown</a> in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
+You can write <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
```Python hl_lines="19 20 21 22 23 24 25 26 27"
{!./src/path_operation_configuration/tutorial004.py!}
```
!!! info
- Notice that `response_description` refers specifically to the response, the `description` refers to the path operation in general.
+ Notice that `response_description` refers specifically to the response, the `description` refers to the *path operation* in general.
-!!! info
- OpenAPI specifies that each path operation requires a response description.
+!!! check
+ OpenAPI specifies that each *path operation* requires a response description.
So, if you don't provide one, **FastAPI** will automatically generate one of "Successful response".
<img src="/img/tutorial/path-operation-configuration/image03.png">
-## 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`:
+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`:
```Python hl_lines="16"
{!./src/path_operation_configuration/tutorial006.py!}
<img src="/img/tutorial/path-operation-configuration/image04.png">
-Check how deprecated and non-deprecated path operations look like:
+Check how deprecated and non-deprecated *path operations* look like:
<img src="/img/tutorial/path-operation-configuration/image05.png">
## Recap
-You can configure and add metadata for your path operations easily by passing parameters to the path operation decorators.
+You can configure and add metadata for your *path operations* easily by passing parameters to the *path operation decorators*.
```Python hl_lines="8"
{!./src/path_params_numeric_validations/tutorial004.py!}
```
+
## Number validations: greater than and less than or equal
The same applies for:
## Recap
-With `Query`, `Path` (and others you haven't seen yet) you can declare [metadata and string validations (the previous chapter)](/tutorial/query-params-str-validations).
+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}.
And you can also declare numeric validations:
And then you can also have a path `/users/{user_id}` to get data about a specific user by some user ID.
-Because path operations are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
+Because *path operations* are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
```Python hl_lines="6 11"
{!./src/path_params/tutorial003.py!}
q: str = Query(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.
+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*.
## Add more validations
* `limit`, an optional `int`.
!!! tip
- You could also use `Enum`s <a href="https://fastapi.tiangolo.com/tutorial/path-params/#predefined-values" target="_blank">the same way as with *path parameters*</a>.
+ You could also use `Enum`s the same way as with [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
## Optional type declarations
!!! info
`File` is a class that inherits directly from `Form`.
- But remember that when you import `Query`, `Path`, `File` and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+ But remember that when you import `Query`, `Path`, `File` and others from `fastapi`, those are actually functions that return special classes.
-!!! info
+!!! tip
To declare File bodies, you need to use `File`, because otherwise the parameters would be interpreted as query parameters or body (JSON) parameters.
The files will be uploaded as "form data".
* `filename`: A `str` with the original file name that was uploaded (e.g. `myimage.jpg`).
* `content_type`: A `str` with the content type (MIME type / media type) (e.g. `image/jpeg`).
-* `file`: A <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" target="_blank">`SpooledTemporaryFile`</a> (a <a href="https://docs.python.org/3/glossary.html#term-file-like-object" target="_blank">file-like</a> object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
+* `file`: A <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (a <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
`UploadFile` has the following `async` methods. They all call the corresponding file methods underneath (using the internal `SpooledTemporaryFile`).
If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
!!! warning
- You can declare multiple `File` and `Form` parameters in a path operation, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
+ You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
!!! note
- Notice that, as of 2019-04-14, Swagger UI doesn't support multiple file uploads in the same form field. For more information, check <a href="https://github.com/swagger-api/swagger-ui/issues/4276" target="_blank">#4276</a> and <a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>.
+ Notice that, as of 2019-04-14, Swagger UI doesn't support multiple file uploads in the same form field. For more information, check <a href="https://github.com/swagger-api/swagger-ui/issues/4276" class="external-link" target="_blank">#4276</a> and <a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>.
Nevertheless, **FastAPI** is already compatible with it, using the standard OpenAPI.
And you can declare some of the files as `bytes` and some as `UploadFile`.
!!! warning
- You can declare multiple `File` and `Form` parameters in a path operation, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
+ You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
!!! info
`Form` is a class that inherits directly from `Body`.
-!!! info
+!!! tip
To declare form bodies, you need to use `Form` explicitly, because without it the parameters would be interpreted as query parameters or body (JSON) parameters.
## About "Form Fields"
If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
!!! warning
- You can declare multiple `Form` parameters in a path operation, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `application/x-www-form-urlencoded` instead of `application/json`.
+ You can declare multiple `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `application/x-www-form-urlencoded` instead of `application/json`.
This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
-You can declare the model used for the response with the parameter `response_model` in any of the path operations:
+You can declare the model used for the response with the parameter `response_model` in any of the *path operations*:
* `@app.get()`
* `@app.post()`
```
!!! note
- Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your path operation function, like all the parameters and body.
+ Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
It receives the same type you would declare for a Pydantic model attribute, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`.
* Convert the output data to its type declaration.
* Validate the data.
-* Add a JSON Schema for the response, in the OpenAPI path operation.
+* Add a JSON Schema for the response, in the OpenAPI *path operation*.
* Will be used by the automatic documentation systems.
But most importantly:
In this case, it might not be a problem, because the user himself is sending the password.
-But if we use the same model for another path operation, we could be sending our user's passwords to every client.
+But if we use the same model for another *path operation*, we could be sending our user's passwords to every client.
!!! danger
Never send the plain password of a user in a response.
{!./src/response_model/tutorial003.py!}
```
-Here, even though our path operation function is returning the same input user that contains the password:
+Here, even though our *path operation function* is returning the same input user that contains the password:
```Python hl_lines="22"
{!./src/response_model/tutorial003.py!}
## Recap
-Use the path operation decorator's parameter `response_model` to define response models and especially to ensure private data is filtered out.
+Use the *path operation decorator's* parameter `response_model` to define response models and especially to ensure private data is filtered out.
Use `response_model_exclude_unset` to return only the values explicitly set.
-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:
+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*:
* `@app.get()`
* `@app.post()`
```
!!! note
- Notice that `status_code` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your path operation function, like all the parameters and body.
+ Notice that `status_code` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
The `status_code` parameter receives a number with the HTTP status code.
## Changing the default
-Later, in a more advanced part of the tutorial/user guide, you will see how to <a href="https://fastapi.tiangolo.com/tutorial/response-change-status-code/" target="_blank">return a different status code than the default</a> you are declaring here.
+Later, in the **Advanced User Guide**, you will see how to return a different status code than the default you are declaring here.
!!! check "Authorize button!"
You already have a shinny new "Authorize" button.
- And your path operation has a little lock in the top-right corner that you can click.
+ And your *path operation* has a little lock in the top-right corner that you can click.
And if you click it, you have a little authorization form to type a `username` and `password` (and other optional fields):
{!./src/security/tutorial001.py!}
```
-It doesn't create that endpoint / path operation, but declares that that URL is the one that the client should use to get the token. That information is used in OpenAPI, and then in the interactive API documentation systems.
+It doesn't create that endpoint / *path operation*, but declares that that URL is the one that the client should use to get the token. That information is used in OpenAPI, and then in the interactive API documentation systems.
!!! info
If you are a very strict "Pythonista" you might dislike the style of the parameter name `tokenUrl` instead of `token_url`.
-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`:
+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`:
```Python hl_lines="10"
{!./src/security/tutorial001.py!}
`get_current_user` will have a dependency with the same `oauth2_scheme` we created before.
-The same as we were doing before in the path operation directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`:
+The same as we were doing before in the *path operation* directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`:
```Python hl_lines="25"
{!./src/security/tutorial002.py!}
## Inject the current user
-So now we can use the same `Depends` with our `get_current_user` in the path operation:
+So now we can use the same `Depends` with our `get_current_user` in the *path operation*:
```Python hl_lines="31"
{!./src/security/tutorial002.py!}
## 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`.
+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`.
And you can use any model or data for the security requirements (in this case, a Pydantic model `User`).
## Code size
-This example might seem verbose. Have in mind that we are mixing security, data models utility functions and path operations in the same file.
+This example might seem verbose. Have in mind that we are mixing security, data models utility functions and *path operations* in the same file.
But here's the key point.
And you can make it as complex as you want. And still, have it written only once, in a single place. With all the flexibility.
-But you can have thousands of endpoints (path operations) using the same security system.
+But you can have thousands of endpoints (*path operations*) using the same security system.
And all of them (or any portion of them that you want) can take the advantage of re-using these dependencies or any other dependencies you create.
-And all these thousands of path operations can be as small as 3 lines:
+And all these thousands of *path operations* can be as small as 3 lines:
```Python hl_lines="30 31 32"
{!./src/security/tutorial002.py!}
## Recap
-You can now get the current user directly in your path operation function.
+You can now get the current user directly in your *path operation function*.
We are already halfway there.
-We just need to add a path operation for the user/client to actually send the `username` and `password`.
+We just need to add a *path operation* for the user/client to actually send the `username` and `password`.
-That comes next.
\ No newline at end of file
+That comes next.
But it's signed. So, when you receive a token that you emitted, you can verify that you actually emitted it.
-That way, you can create a token with an expiration of, let's say, 1 week, and then, after a week, when the user comes back with the token, you know he's still signed into your system.
+That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know she/he is still signed into your system.
-And after a week, the token will be expired. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
+And after a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
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>.
{!./src/security/tutorial004.py!}
```
-## Update the `/token` path operation
+## Update the `/token` *path operation*
Create a `timedelta` with the expiration time of the token.
Then you can give this token to a user directly or a third party, to interact with your API with a set of restrictions.
-You can learn how to use them and how they are integrated into **FastAPI** in the next chapter.
+You can learn how to use them and how they are integrated into **FastAPI** later in the **Advanced User Guide**.
## Recap
And you can use directly many well maintained and widely used packages like `passlib` and `pyjwt`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
-But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness or security.
+But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security.
And you can use and implement secure, standard protocols, like OAuth2 in a relatively simple way.
-In the next (optional) section you can see how to extend this even further, using OAuth2 "scopes", for a more fine-grained permission system, following these same standards.
-
-OAuth2 with scopes (explained in the next section) is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, Twitter, etc.
+You can learn more in the **Advanced User Guide** about how to use OAuth2 "scopes", for a more fine-grained permission system, following these same standards. OAuth2 with scopes is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, Twitter, etc. to authorize third party applications to interact with their APIs on behalf of their users.
And your database models can use any other names you want.
-But for the login path operation, we need to use these names to be compatible with the spec (and be able to, for example, use the integrated API documentation system).
+But for the login *path operation*, we need to use these names to be compatible with the spec (and be able to, for example, use the integrated API documentation system).
The spec also states that the `username` and `password` must be sent as form data (so, no JSON here).
They are normally used to declare specific security permissions, for example:
-* `"users:read"` or `"users:write"` are common examples.
+* `users:read` or `users:write` are common examples.
* `instagram_basic` is used by Facebook / Instagram.
* `https://www.googleapis.com/auth/drive` is used by Google.
!!! info
In OAuth2 a "scope" is just a string that declares a specific permission required.
- It doesn't matter if it has other characters like `:`, or if it is a URL.
+ It doesn't matter if it has other characters like `:` or if it is a URL.
Those details are implementation specific.
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).
+So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
```Python hl_lines="79 80 81 82"
{!./src/security/tutorial003.py!}
```
!!! info
- For a more complete explanation of `**user_dict` check back in <a href="/tutorial/extra-models/#about-user_indict" target="_blank">the documentation for **Extra Models**</a>.
+ 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}.
## Return the token
```
!!! tip
- By creating functions that are only dedicated to interacting with the database (get a user or an item) independent of your path operation function, you can more easily reuse them in multiple parts and also add <abbr title="Automated tests, written in code, that check if another piece of code is working correctly.">unit tests</abbr> for them.
+ By creating functions that are only dedicated to interacting with the database (get a user or an item) independent of your *path operation function*, you can more easily reuse them in multiple parts and also add <abbr title="Automated tests, written in code, that check if another piece of code is working correctly.">unit tests</abbr> for them.
### Create data
pip install async-exit-stack async-generator
```
- This installs <a href="https://github.com/sorcio/async_exit_stack" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
+ This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
You can also use the alternative method with a "middleware" explained at the end.
And then a new session will be created for the next request.
-For that, we will create a new dependency with `yield`, as explained before in the section about <a href="https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/" target="_blank">Dependencies with `yield`</a>.
+For that, we will create a new dependency with `yield`, as explained before in the section about [Dependencies with `yield`](dependencies/dependencies-with-yield.md){.internal-link target=_blank}.
Our dependency will create a new SQLAlchemy `SessionLocal` that will be used in a single request, and then close it once the request is finished.
We are creating the database session before each request in the dependency with `yield`, and then closing it afterwards.
-And then we can create the required dependency in the path operation function, to get that session directly.
+And then we can create the required dependency in the *path operation function*, to get that session directly.
-With that, we can just call `crud.get_user` directly from inside of the path operation function and use that session.
+With that, we can just call `crud.get_user` directly from inside of the *path operation function* and use that session.
!!! tip
Notice that the values you return are SQLAlchemy models, or lists of SQLAlchemy models.
### About `def` vs `async def`
-Here we are using SQLAlchemy code inside of the path operation function and in the dependency, and, in turn, it will go and communicate with an external database.
+Here we are using SQLAlchemy code inside of the *path operation function* and in the dependency, and, in turn, it will go and communicate with an external database.
That could potentially require some "waiting".
```
!!! note "Very Technical Details"
- If you are curious and have a deep technical knowledge, you can check <a href="https://fastapi.tiangolo.com/async/#very-technical-details" target="_blank">the very technical details of how this `async def` vs `def` is handled</a>.
+ If you are curious and have a deep technical knowledge, you can check the very technical details of how this `async def` vs `def` is handled in the [Async](../async.md#very-technical-details){.internal-link target=_blank} docs.
## Migrations
<img src="/img/tutorial/sql-databases/image02.png">
-You can also use an online SQLite browser like <a href="https://inloop.github.io/sqlite-viewer/" target="_blank">SQLite Viewer</a> or <a href="https://extendsclass.com/sqlite-browser.html" class="external-link" target="_blank">ExtendsClass</a>.
+You can also use an online SQLite browser like <a href="https://inloop.github.io/sqlite-viewer/" class="external-link" target="_blank">SQLite Viewer</a> or <a href="https://extendsclass.com/sqlite-browser.html" class="external-link" target="_blank">ExtendsClass</a>.
## Alternative DB session with middleware
## Use `StaticFiles`
* Import `StaticFiles` from Starlette.
-* "Mount" it the same way you would <a href="https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/" target="_blank">mount a Sub-Application</a>.
+* "Mount" a `StaticFiles()` instance in a specific path.
```Python hl_lines="2 6"
{!./src/static_files/tutorial001.py!}
```
-Then you could have a directory `./static/` with some files that will be served directly.
+### What is "Mounting"
+
+"Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
+
+This is different from using an `APIRouter` as a mounted application is completely independent. The OpenAPI and docs from your main application won't include anything from the mounted application, etc.
+
+You can read more about this in the **Advanced User Guide**.
## Details
!!! info
Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models.
- If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the <a href="https://fastapi.tiangolo.com/tutorial/encoder/" target="_blank">JSON compatible encoder: `jsonable_encoder`</a>.
-
-## Testing WebSockets
-
-You can use the same `TestClient` to test WebSockets.
-
-For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket:
-
-```Python hl_lines="27 28 29 30 31"
-{!./src/app_testing/tutorial002.py!}
-```
-
-## Testing Events, `startup` and `shutdown`
-
-When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement:
-
-```Python hl_lines="9 10 11 12 20 21 22 23 24"
-{!./src/app_testing/tutorial003.py!}
-```
+ If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the `jsonable_encoder` descibed in [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
## Run it
- Features: 'features.md'
- Python types intro: 'python-types.md'
- Tutorial - User Guide:
- - Tutorial - User Guide - Intro: 'tutorial/intro.md'
+ - Tutorial - User Guide - Intro: 'tutorial/index.md'
- First Steps: 'tutorial/first-steps.md'
- Path Parameters: 'tutorial/path-params.md'
- Query Parameters: 'tutorial/query-params.md'
- Request Forms and Files: 'tutorial/request-forms-and-files.md'
- Handling Errors: 'tutorial/handling-errors.md'
- Path Operation Configuration: 'tutorial/path-operation-configuration.md'
- - Path Operation Advanced Configuration: 'tutorial/path-operation-advanced-configuration.md'
- - Additional Status Codes: 'tutorial/additional-status-codes.md'
- - JSON compatible encoder: 'tutorial/encoder.md'
+ - JSON Compatible Encoder: 'tutorial/encoder.md'
- Body - updates: 'tutorial/body-updates.md'
- - Return a Response directly: 'tutorial/response-directly.md'
- - Custom Response Class: 'tutorial/custom-response.md'
- - Additional Responses in OpenAPI: 'tutorial/additional-responses.md'
- - Response Cookies: 'tutorial/response-cookies.md'
- - Response Headers: 'tutorial/response-headers.md'
- - Response - Change Status Code: 'tutorial/response-change-status-code.md'
- Dependencies:
- - First Steps: 'tutorial/dependencies/first-steps.md'
+ - First Steps: 'tutorial/dependencies/index.md'
- Classes as Dependencies: 'tutorial/dependencies/classes-as-dependencies.md'
- Sub-dependencies: 'tutorial/dependencies/sub-dependencies.md'
- Dependencies in path operation decorators: 'tutorial/dependencies/dependencies-in-path-operation-decorators.md'
- Dependencies with yield: 'tutorial/dependencies/dependencies-with-yield.md'
- - Advanced Dependencies: 'tutorial/dependencies/advanced-dependencies.md'
- Security:
- - Security Intro: 'tutorial/security/intro.md'
+ - Security Intro: 'tutorial/security/index.md'
- First Steps: 'tutorial/security/first-steps.md'
- Get Current User: 'tutorial/security/get-current-user.md'
- Simple OAuth2 with Password and Bearer: 'tutorial/security/simple-oauth2.md'
- OAuth2 with Password (and hashing), Bearer with JWT tokens: 'tutorial/security/oauth2-jwt.md'
- - OAuth2 scopes: 'tutorial/security/oauth2-scopes.md'
- - HTTP Basic Auth: 'tutorial/security/http-basic-auth.md'
- Middleware: 'tutorial/middleware.md'
- CORS (Cross-Origin Resource Sharing): 'tutorial/cors.md'
- - Using the Request Directly: 'tutorial/using-request-directly.md'
- SQL (Relational) Databases: 'tutorial/sql-databases.md'
- - SQL (Relational) Databases with Peewee: 'tutorial/sql-databases-peewee.md'
- - Async SQL (Relational) Databases: 'tutorial/async-sql-databases.md'
- - NoSQL (Distributed / Big Data) Databases: 'tutorial/nosql-databases.md'
- Bigger Applications - Multiple Files: 'tutorial/bigger-applications.md'
- Background Tasks: 'tutorial/background-tasks.md'
- - Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md'
- Application Configuration: 'tutorial/application-configuration.md'
- Static Files: 'tutorial/static-files.md'
- - Templates: 'tutorial/templates.md'
- - GraphQL: 'tutorial/graphql.md'
- - WebSockets: 'tutorial/websockets.md'
- - 'Events: startup - shutdown': 'tutorial/events.md'
- - Custom Request and APIRoute class: 'tutorial/custom-request-and-route.md'
- Testing: 'tutorial/testing.md'
- - Testing Dependencies with Overrides: 'tutorial/testing-dependencies.md'
- Debugging: 'tutorial/debugging.md'
- - Extending OpenAPI: 'tutorial/extending-openapi.md'
- - OpenAPI Callbacks: 'tutorial/openapi-callbacks.md'
+ - Advanced User Guide:
+ - Advanced User Guide - Intro: 'advanced/index.md'
+ - Path Operation Advanced Configuration: 'advanced/path-operation-advanced-configuration.md'
+ - Additional Status Codes: 'advanced/additional-status-codes.md'
+ - Return a Response Directly: 'advanced/response-directly.md'
+ - Custom Response Class: 'advanced/custom-response.md'
+ - Additional Responses in OpenAPI: 'advanced/additional-responses.md'
+ - Response Cookies: 'advanced/response-cookies.md'
+ - Response Headers: 'advanced/response-headers.md'
+ - Response - Change Status Code: 'advanced/response-change-status-code.md'
+ - Advanced Dependencies: 'advanced/advanced-dependencies.md'
+ - Advanced Security:
+ - Advanced Security - Intro: advanced/security/index.md
+ - OAuth2 scopes: 'advanced/security/oauth2-scopes.md'
+ - HTTP Basic Auth: 'advanced/security/http-basic-auth.md'
+ - Using the Request Directly: 'advanced/using-request-directly.md'
+ - SQL (Relational) Databases with Peewee: 'advanced/sql-databases-peewee.md'
+ - Async SQL (Relational) Databases: 'advanced/async-sql-databases.md'
+ - NoSQL (Distributed / Big Data) Databases: 'advanced/nosql-databases.md'
+ - Sub Applications - Behind a Proxy: 'advanced/sub-applications-proxy.md'
+ - Templates: 'advanced/templates.md'
+ - GraphQL: 'advanced/graphql.md'
+ - WebSockets: 'advanced/websockets.md'
+ - 'Events: startup - shutdown': 'advanced/events.md'
+ - Custom Request and APIRoute class: 'advanced/custom-request-and-route.md'
+ - Testing WebSockets: 'advanced/testing-websockets.md'
+ - 'Testing Events: startup - shutdown': 'advanced/testing-events.md'
+ - Testing Dependencies with Overrides: 'advanced/testing-dependencies.md'
+ - Extending OpenAPI: 'advanced/extending-openapi.md'
+ - OpenAPI Callbacks: 'advanced/openapi-callbacks.md'
- Concurrency and async / await: 'async.md'
- Deployment: 'deployment.md'
- Project Generation - Template: 'project-generation.md'