mirror of https://github.com/tiangolo/fastapi.git
📝 Improve explanation of dependencies
This commit is contained in:
parent
a59408f68c
commit
9a8349bf96
|
|
@ -10,3 +10,8 @@ async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
|
|||
@app.get("/items/")
|
||||
async def read_items(commons: dict = Depends(common_parameters)):
|
||||
return commons
|
||||
|
||||
|
||||
@app.get("/users/")
|
||||
async def read_users(commons: dict = Depends(common_parameters)):
|
||||
return commons
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
Let's see a very simple example of the **Dependency Injection** system.
|
||||
|
||||
It will be so simple that it is not very useful, for now.
|
||||
|
||||
But this way we can focus on how the **Dependency Injection** system works.
|
||||
|
||||
In the next chapters we'll extend it to see how can it be so useful.
|
||||
|
||||
## Create a dependency, or "dependable"
|
||||
|
||||
Let's first focus on the dependency.
|
||||
|
||||
It is just a function that can take all the same parameters that a path operation function can take:
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
That's it.
|
||||
|
||||
**2 lines**.
|
||||
|
||||
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")`).
|
||||
|
||||
And it can return anything you want.
|
||||
|
||||
In this case, this dependency expects:
|
||||
|
||||
* An optional query parameter `q` that is a `str`.
|
||||
* An optional query parameter `skip` that is an `int`, and by default is `0`.
|
||||
* An optional query parameter `limit` that is an `int`, and by default is `100`.
|
||||
|
||||
And then it just returns a `dict` containing those values.
|
||||
|
||||
## Import `Depends`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
## 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:
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
Although you use it in the parameters of your function too, `Depends` works a bit differently.
|
||||
|
||||
You only give `Depends` a single parameter.
|
||||
|
||||
This parameter must be a function with the same parameters that can be taken by a path operation function.
|
||||
|
||||
Whenever a new request arrives, **FastAPI** will take care of:
|
||||
|
||||
* 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.
|
||||
|
||||
!!! note
|
||||
Notice that you don't have to create a special class and pass it somewhere to **FastAPI** 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.
|
||||
|
||||
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.
|
||||
|
||||
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>.
|
||||
|
||||
## Integrated wiht OpenAPI
|
||||
|
||||
All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
|
||||
|
||||
So, the interactive docs will have all the information they need, while you keep all the flexibility of the dependencies:
|
||||
|
||||
<img src="/img/tutorial/dependencies/image01.png">
|
||||
|
||||
## Recap
|
||||
|
||||
Create Dependencies with **2 lines** of code.
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
**FastAPI** has a very powerful but intuitive **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
|
||||
It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
|
||||
|
||||
## "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".
|
||||
|
||||
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).
|
||||
|
||||
This is very useful when you need to:
|
||||
|
||||
* Have shared logic (the same code logic again and again).
|
||||
* Share database connections.
|
||||
* Enforce security, authentication, role requirements, etc.
|
||||
* etc.
|
||||
|
||||
All these, while minimizing code repetition.
|
||||
|
||||
|
||||
## First Steps
|
||||
|
||||
Let's see a very simple example. It will be so simple that it is not very useful, for now.
|
||||
|
||||
But this way we can focus on how the **Dependency Injection** system works.
|
||||
|
||||
|
||||
### Create a dependency, or "dependable"
|
||||
|
||||
Let's first focus on the dependency.
|
||||
|
||||
It is just a function that can take all the same parameters that a path operation function can take:
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
That's it.
|
||||
|
||||
**2 lines**.
|
||||
|
||||
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")`).
|
||||
|
||||
And it can return anything you want.
|
||||
|
||||
In this case, this dependency expects:
|
||||
|
||||
* An optional query parameter `q` that is a `str`.
|
||||
* An optional query parameter `skip` that is an `int`, and by default is `0`.
|
||||
* An optional query parameter `limit` that is an `int`, and by default is `100`.
|
||||
|
||||
And then it just returns a `dict` containing those values.
|
||||
|
||||
### Import `Depends`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
### 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:
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!./src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
Although you use `Depends` in the parameters of your function the same way you use `Body`, `Query`, etc, `Depends` works a bit differently.
|
||||
|
||||
You only give `Depends` a single parameter.
|
||||
|
||||
This parameter must be something like a function.
|
||||
|
||||
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.
|
||||
|
||||
Whenever a new request arrives, **FastAPI** will take care of:
|
||||
|
||||
* 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.
|
||||
|
||||
!!! note
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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>.
|
||||
|
||||
|
||||
## Integrated with OpenAPI
|
||||
|
||||
All the request declarations, validations and requirements of your dependencies (and sub-dependencies) will be integrated in the same OpenAPI schema.
|
||||
|
||||
So, the interactive docs will have all the information from these dependencies too:
|
||||
|
||||
<img src="/img/tutorial/dependencies/image01.png">
|
||||
|
||||
|
||||
## Simple usage
|
||||
|
||||
If you look at it, *path operation functions* are declared to be used whenever a *path* and *operation* matches, and then **FastAPI** takes care of calling the function with the correct parameters and use the response.
|
||||
|
||||
Actually, all (or most) of the web frameworks work in this same way.
|
||||
|
||||
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.
|
||||
|
||||
Other common terms for this same idea of "dependency injection" are:
|
||||
|
||||
* resources
|
||||
* providers
|
||||
* services
|
||||
* injectables
|
||||
* components
|
||||
|
||||
## **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.
|
||||
|
||||
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.
|
||||
|
||||
## **FastAPI** compatibility
|
||||
|
||||
The simplicity of the dependency injection system makes **FastAPI** compatible with:
|
||||
|
||||
* all the relational databases
|
||||
* NoSQL databases
|
||||
* external packages
|
||||
* external APIs
|
||||
* authentication and authorization systems
|
||||
* API usage monitoring systems
|
||||
* response data injection systems
|
||||
* etc.
|
||||
|
||||
|
||||
## Simple and Powerful
|
||||
|
||||
Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
|
||||
|
||||
You can define dependencies that in turn can define dependencies themselves.
|
||||
|
||||
In the end, a hierarchical tree of dependencies is built, and the **Dependency Injection** system takes care of solving all these dependencies for you (and your dependencies) and providing (injecting) the results at each step.
|
||||
|
||||
## Integrated with **OpenAPI**
|
||||
|
||||
All these dependencies, while declaring their requirements, 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.
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
**FastAPI** has a very powerful but intuitive **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
|
||||
It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
|
||||
|
||||
## "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.
|
||||
|
||||
And then, that system (in this case **FastAPI**) will take care of doing whatever is needed to provide your code with that thing that it needs.
|
||||
|
||||
If you look at it, path operation functions are declared to be used whenever a path and operation matches, and then **FastAPI** will take care of calling the function with the correct parameters and use the response.
|
||||
|
||||
Actually, all (or most) of the web frameworks work in this same way.
|
||||
|
||||
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.
|
||||
|
||||
Other common terms for this same idea are:
|
||||
|
||||
* resources
|
||||
* providers
|
||||
* services
|
||||
* injectables
|
||||
|
||||
## **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.
|
||||
|
||||
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_.
|
||||
|
||||
## **FastAPI** compatibility
|
||||
|
||||
The simplicity of the dependency injection system makes **FastAPI** compatible with:
|
||||
|
||||
* all the relational databases
|
||||
* NoSQL databases
|
||||
* external packages
|
||||
* external APIs
|
||||
* authentication and authorization systems
|
||||
* API usage monitoring systems
|
||||
* response data injection systems
|
||||
* etc.
|
||||
|
||||
|
||||
## Simple and Powerful
|
||||
|
||||
Although the hierarchical dependency injection system is very simple to define and use, it's still very powerful.
|
||||
|
||||
You can define dependencies that in turn can define dependencies themselves.
|
||||
|
||||
In the end, a hierarchical tree of dependencies is built, and the **Dependency Injection** system takes care of solving all these dependencies for you (and your dependencies) and providing the results at each step.
|
||||
|
||||
## Integrated with **OpenAPI**
|
||||
|
||||
All these dependencies, while declaring their requirements, might have been adding 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.
|
||||
|
|
@ -23,8 +23,8 @@ nav:
|
|||
- Path Parameters: 'tutorial/path-params.md'
|
||||
- Query Parameters: 'tutorial/query-params.md'
|
||||
- Request Body: 'tutorial/body.md'
|
||||
- Query Parameters - String Validations: 'tutorial/query-params-str-validations.md'
|
||||
- Path Parameters - Numeric Validations: 'tutorial/path-params-numeric-validations.md'
|
||||
- Query Parameters and String Validations: 'tutorial/query-params-str-validations.md'
|
||||
- Path Parameters and Numeric Validations: 'tutorial/path-params-numeric-validations.md'
|
||||
- Body - Multiple Parameters: 'tutorial/body-multiple-params.md'
|
||||
- Body - Schema: 'tutorial/body-schema.md'
|
||||
- Body - Nested Models: 'tutorial/body-nested-models.md'
|
||||
|
|
@ -40,8 +40,7 @@ nav:
|
|||
- Path Operation Advanced Configuration: 'tutorial/path-operation-advanced-configuration.md'
|
||||
- Custom Response: 'tutorial/custom-response.md'
|
||||
- Dependencies:
|
||||
- Dependencies Intro: 'tutorial/dependencies/intro.md'
|
||||
- First Steps - Functions: 'tutorial/dependencies/first-steps-functions.md'
|
||||
- First Steps: 'tutorial/dependencies/first-steps.md'
|
||||
- Classes as Dependencies: 'tutorial/dependencies/classes-as-dependencies.md'
|
||||
- Sub-dependencies: 'tutorial/dependencies/sub-dependencies.md'
|
||||
- Advanced Dependencies: 'tutorial/dependencies/advanced-dependencies.md'
|
||||
|
|
|
|||
|
|
@ -50,7 +50,49 @@ openapi_schema = {
|
|||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"summary": "Read Users Get",
|
||||
"operationId": "read_users_users__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "Q", "type": "string"},
|
||||
"name": "q",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "Skip", "type": "integer", "default": 0},
|
||||
"name": "skip",
|
||||
"in": "query",
|
||||
},
|
||||
{
|
||||
"required": False,
|
||||
"schema": {"title": "Limit", "type": "integer", "default": 100},
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
|
|
@ -97,6 +139,7 @@ def test_openapi_schema():
|
|||
("/items?q=foo", 200, {"q": "foo", "skip": 0, "limit": 100}),
|
||||
("/items?q=foo&skip=5", 200, {"q": "foo", "skip": 5, "limit": 100}),
|
||||
("/items?q=foo&skip=5&limit=30", 200, {"q": "foo", "skip": 5, "limit": 30}),
|
||||
("/users", 200, {"q": None, "skip": 0, "limit": 100}),
|
||||
("/openapi.json", 200, openapi_schema),
|
||||
],
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue