Coming soon...
```Python
-{!./tutorial/src/application-configuration/tutorial001.py!}
+{!./src/application-configuration/tutorial001.py!}
```
```Python
-{!./tutorial/src/application-configuration/tutorial002.py!}
+{!./src/application-configuration/tutorial002.py!}
```
```Python
-{!./tutorial/src/application-configuration/tutorial003.py!}
+{!./src/application-configuration/tutorial003.py!}
```
Coming soon...
```Python
-{!./tutorial/src/bigger_applications/app/routers/tutorial001.py!}
+{!./src/bigger_applications/app/routers/tutorial001.py!}
```
```Python
-{!./tutorial/src/bigger_applications/app/routers/tutorial002.py!}
+{!./src/bigger_applications/app/routers/tutorial002.py!}
```
```Python
-{!./tutorial/src/bigger_applications/app/tutorial003.py!}
+{!./src/bigger_applications/app/tutorial003.py!}
```
And you can also declare body parameters as optional, by setting the default to `None`:
```Python hl_lines="17 18 19"
-{!./tutorial/src/body_multiple_params/tutorial001.py!}
+{!./src/body_multiple_params/tutorial001.py!}
```
!!! note
But you can also declare multiple body parameters, e.g. `item` and `user`:
```Python hl_lines="20"
-{!./tutorial/src/body_multiple_params/tutorial002.py!}
+{!./src/body_multiple_params/tutorial002.py!}
```
In this case, **FastAPI** will notice that there are more than one body parameter in the function (two parameters that are Pydantic models).
```Python hl_lines="21"
-{!./tutorial/src/body_multiple_params/tutorial003.py!}
+{!./src/body_multiple_params/tutorial003.py!}
```
In this case, **FastAPI** will expect a body like:
as in:
```Python hl_lines="25"
-{!./tutorial/src/body_multiple_params/tutorial004.py!}
+{!./src/body_multiple_params/tutorial004.py!}
```
!!! info
as in:
```Python hl_lines="15"
-{!./tutorial/src/body_multiple_params/tutorial005.py!}
+{!./src/body_multiple_params/tutorial005.py!}
```
In this case **FastAPI** will expect a body like:
You can define an attribute to be a subtype. For example, a Python `list`:
```Python hl_lines="12"
-{!./tutorial/src/body_nested_models/tutorial001.py!}
+{!./src/body_nested_models/tutorial001.py!}
```
This will make `tags` be a list of items. Although it doesn't declare the type of each of the items.
First, import `List` from standard Python's `typing` module:
```Python hl_lines="1"
-{!./tutorial/src/body_nested_models/tutorial002.py!}
+{!./src/body_nested_models/tutorial002.py!}
```
### Declare a `List` with a subtype
So, in our example, we can make `tags` be specifically a "list of strings":
```Python hl_lines="14"
-{!./tutorial/src/body_nested_models/tutorial002.py!}
+{!./src/body_nested_models/tutorial002.py!}
```
## Set types
Then we can import `Set` and declare `tags` as a `set` of `str`:
```Python hl_lines="1 14"
-{!./tutorial/src/body_nested_models/tutorial003.py!}
+{!./src/body_nested_models/tutorial003.py!}
```
With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
For example, we can define an `Image` model:
```Python hl_lines="9 10 11"
-{!./tutorial/src/body_nested_models/tutorial004.py!}
+{!./src/body_nested_models/tutorial004.py!}
```
### Use the submodel as a type
And then we can use it as the type of an attribute:
```Python hl_lines="20"
-{!./tutorial/src/body_nested_models/tutorial004.py!}
+{!./src/body_nested_models/tutorial004.py!}
```
This would mean that **FastAPI** would expect a body similar to:
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 `UrlStr`:
```Python hl_lines="5 11"
-{!./tutorial/src/body_nested_models/tutorial005.py!}
+{!./src/body_nested_models/tutorial005.py!}
```
The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
You can also use Pydantic models as subtypes of `list`, `set`, etc:
```Python hl_lines="21"
-{!./tutorial/src/body_nested_models/tutorial006.py!}
+{!./src/body_nested_models/tutorial006.py!}
```
This will expect (convert, validate, document, etc) a JSON body like:
You can define arbitrarily deeply nested models:
```Python hl_lines="10 15 21 24 28"
-{!./tutorial/src/body_nested_models/tutorial007.py!}
+{!./src/body_nested_models/tutorial007.py!}
```
!!! info
as in:
```Python hl_lines="16"
-{!./tutorial/src/body_nested_models/tutorial008.py!}
+{!./src/body_nested_models/tutorial008.py!}
```
## Editor support everywhere
First, you have to import it:
```Python hl_lines="2"
-{!./tutorial/src/body_schema/tutorial001.py!}
+{!./src/body_schema/tutorial001.py!}
```
!!! warning
You can then use `Schema` with model attributes:
```Python hl_lines="9 10"
-{!./tutorial/src/body_schema/tutorial001.py!}
+{!./src/body_schema/tutorial001.py!}
```
`Schema` works the same way as `Query`, `Path` and `Body`, it has all the same parameters, etc.
For example, you can use that functionality to pass a <a href="http://json-schema.org/latest/json-schema-validation.html#rfc.section.8.5" target="_blank">JSON Schema example</a> field to a body request JSON Schema:
```Python hl_lines="20 21 22 23 24 25"
-{!./tutorial/src/body_schema/tutorial002.py!}
+{!./src/body_schema/tutorial002.py!}
```
## Recap
First, you need to import `BaseModel` from `pydantic`:
```Python hl_lines="2"
-{!./tutorial/src/body/tutorial001.py!}
+{!./src/body/tutorial001.py!}
```
## Create your data model
Use standard Python types for all the attributes:
```Python hl_lines="5 6 7 8 9"
-{!./tutorial/src/body/tutorial001.py!}
+{!./src/body/tutorial001.py!}
```
The same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. Use `None` to make it just optional.
To add it to your path operation, declare it the same way you declared path and query parameters:
```Python hl_lines="16"
-{!./tutorial/src/body/tutorial001.py!}
+{!./src/body/tutorial001.py!}
```
...and declare its type as the model you created, `Item`.
Inside of the function, you can access all the attributes of the model object directly:
```Python hl_lines="19"
-{!./tutorial/src/body/tutorial002.py!}
+{!./src/body/tutorial002.py!}
```
## Request body + path parameters
**FastAPI** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared to be Pydantic models should be **taken from the request body**.
```Python hl_lines="15 16"
-{!./tutorial/src/body/tutorial003.py!}
+{!./src/body/tutorial003.py!}
```
## Request body + path + query parameters
**FastAPI** will recognize each of them and take the data from the correct place.
```Python hl_lines="16"
-{!./tutorial/src/body/tutorial004.py!}
+{!./src/body/tutorial004.py!}
```
The function parameters will be recognized as follows:
First import `Cookie`:
```Python hl_lines="1"
-{!./tutorial/src/cookie_params/tutorial001.py!}
+{!./src/cookie_params/tutorial001.py!}
```
## Declare `Cookie` parameteres
The first value is the default value, you can pass all the extra validation or annotation parameteres:
```Python hl_lines="7"
-{!./tutorial/src/cookie_params/tutorial001.py!}
+{!./src/cookie_params/tutorial001.py!}
```
!!! info
### Import `UJSONResponse`
```Python hl_lines="2"
-{!./tutorial/src/custom_response/tutorial001.py!}
+{!./src/custom_response/tutorial001.py!}
```
!!! note
Make your path operation use `UJSONResponse` as the response class using the parameter `content_type`:
```Python hl_lines="7"
-{!./tutorial/src/custom_response/tutorial001.py!}
+{!./src/custom_response/tutorial001.py!}
```
!!! info
### Import `HTMLResponse`
```Python hl_lines="2"
-{!./tutorial/src/custom_response/tutorial002.py!}
+{!./src/custom_response/tutorial002.py!}
```
!!! note
Pass `HTMLResponse` as the parameter `content_type` of your path operation:
```Python hl_lines="7"
-{!./tutorial/src/custom_response/tutorial002.py!}
+{!./src/custom_response/tutorial002.py!}
```
!!! info
The same example from above, returning an `HTMLResponse`, could look like:
```Python hl_lines="7"
-{!./tutorial/src/custom_response/tutorial003.py!}
+{!./src/custom_response/tutorial003.py!}
```
!!! info
For example, it could be something like:
```Python hl_lines="7 23"
-{!./tutorial/src/custom_response/tutorial004.py!}
+{!./src/custom_response/tutorial004.py!}
```
In this example, the function `generate_html_response()` already generates a Starlette `Response` instead of the HTML in a `str`.
But by declaring it also in the path operation decorator:
```Python hl_lines="21"
-{!./tutorial/src/custom_response/tutorial004.py!}
+{!./src/custom_response/tutorial004.py!}
```
#### OpenAPI knows how to document it
It is just a function that can take all the same parameters that a path operation function can take:
```Python hl_lines="6 7"
-{!./tutorial/src/dependencies/tutorial001.py!}
+{!./src/dependencies/tutorial001.py!}
```
That's it.
## Import `Depends`
```Python hl_lines="1"
-{!./tutorial/src/dependencies/tutorial001.py!}
+{!./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"
-{!./tutorial/src/dependencies/tutorial001.py!}
+{!./src/dependencies/tutorial001.py!}
```
Although you use it in the parameters of your function too, `Depends` works a bit differently.
In the previous example, we where returning a `dict` from our dependency ("dependable"):
```Python hl_lines="7"
-{!./tutorial/src/dependencies/tutorial001.py!}
+{!./src/dependencies/tutorial001.py!}
```
But then we get a `dict` in the parameter `commons` of the path operation function.
Create a model for the common parameters (and don't pay attention to the rest, for now):
```Python hl_lines="11 12 13 14"
-{!./tutorial/src/dependencies/tutorial002.py!}
+{!./src/dependencies/tutorial002.py!}
```
## Return a Pydantic model
Now we can return a Pydantic model from the dependency ("dependable") with the same data as the dict before:
```Python hl_lines="18"
-{!./tutorial/src/dependencies/tutorial002.py!}
+{!./src/dependencies/tutorial002.py!}
```
## Declare the Pydantic model
It won't be interpreted as a JSON request `Body` because we are using `Depends`:
```Python hl_lines="22"
-{!./tutorial/src/dependencies/tutorial002.py!}
+{!./src/dependencies/tutorial002.py!}
```
!!! info
And now we can use that model in our code, with all the lovable editor support:
```Python hl_lines="24 25 26"
-{!./tutorial/src/dependencies/tutorial002.py!}
+{!./src/dependencies/tutorial002.py!}
```
<img src="/img/tutorial/dependencies/image02.png">
Here's a general idea of how the models could look like with their password fields and the places where they are used:
```Python hl_lines="8 10 15 21 23 32 34 39 40"
-{!./tutorial/src/extra_models/tutorial001.py!}
+{!./src/extra_models/tutorial001.py!}
```
!!! warning
That way, we can declare just the differences between the models (with plaintext `password`, with `hashed_password` and without password):
```Python hl_lines="8 14 15 18 19 22 23"
-{!./tutorial/src/extra_models/tutorial002.py!}
+{!./src/extra_models/tutorial002.py!}
```
## Recap
The simplest FastAPI file could look like this:
```Python
-{!tutorial/src/first_steps/tutorial001.py!}
+{!./src/first_steps/tutorial001.py!}
```
Copy that to a file `main.py`.
### Step 1: import `FastAPI`
```Python hl_lines="1"
-{!tutorial/src/first_steps/tutorial001.py!}
+{!./src/first_steps/tutorial001.py!}
```
`FastAPI` is a Python class that provides all the functionality for your API.
### Step 2: create a `FastAPI` "instance"
```Python hl_lines="3"
-{!tutorial/src/first_steps/tutorial001.py!}
+{!./src/first_steps/tutorial001.py!}
```
Here the `app` variable will be an "instance" of the class `FastAPI`.
If you create your app like:
```Python hl_lines="3"
-{!tutorial/src/first_steps/tutorial002.py!}
+{!./src/first_steps/tutorial002.py!}
```
And put it in a file `main.py`, then you would call `uvicorn` like:
#### Define a path operation function
```Python hl_lines="6"
-{!tutorial/src/first_steps/tutorial001.py!}
+{!./src/first_steps/tutorial001.py!}
```
The `@app.get("/")` tells **FastAPI** that the function right below is in charge of handling requests that go to:
### Step 4: define the path operation function
```Python hl_lines="7"
-{!tutorial/src/first_steps/tutorial001.py!}
+{!./src/first_steps/tutorial001.py!}
```
This is a Python function.
You could also define it as a normal function instead of `async def`:
```Python hl_lines="7"
-{!tutorial/src/first_steps/tutorial003.py!}
+{!./src/first_steps/tutorial003.py!}
```
To know the difference, read the section about [Concurrency and `async` / `await`](/async/).
### Step 5: return the content
```Python hl_lines="8"
-{!tutorial/src/first_steps/tutorial001.py!}
+{!./src/first_steps/tutorial001.py!}
```
You can return a `dict`, `list`, singular values as `str`, `int`, etc.
First import `Header`:
```Python hl_lines="1"
-{!./tutorial/src/header_params/tutorial001.py!}
+{!./src/header_params/tutorial001.py!}
```
## Declare `Header` parameteres
The first value is the default value, you can pass all the extra validation or annotation parameteres:
```Python hl_lines="7"
-{!./tutorial/src/header_params/tutorial001.py!}
+{!./src/header_params/tutorial001.py!}
```
!!! info
If for some reason you need to disable automatic conversion of underscores to hyphens, set the parameter `convert_underscores` of `Header` to `False`:
```Python hl_lines="7"
-{!./tutorial/src/header_params/tutorial002.py!}
+{!./src/header_params/tutorial002.py!}
```
!!! warning
For now, don't pay attention to the rest, only the imports:
```Python hl_lines="6 7 8"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./src/nosql_databases/tutorial001.py!}
```
## Define a constant to use as a "document type"
This is not required by Couchbase, but is a good practice that will help you afterwards.
```Python hl_lines="10"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./src/nosql_databases/tutorial001.py!}
```
## Add a function to get a `Bucket`
* Return it.
```Python hl_lines="13 14 15 16 17 18 19 20"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./src/nosql_databases/tutorial001.py!}
```
## Create Pydantic models
First, let's create a `User` model:
```Python hl_lines="23 24 25 26 27"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./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 don't create it as a subclass of Pydantic's `BaseModel` but as a subclass of our own `User`, because it will have all the attributes in `User` plus a couple more:
```Python hl_lines="30 31 32"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./src/nosql_databases/tutorial001.py!}
```
!!! note
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="35 36 37 38 39 40 41"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./src/nosql_databases/tutorial001.py!}
```
### f-strings
### Create the `FastAPI` app
```Python hl_lines="45"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./src/nosql_databases/tutorial001.py!}
```
### Create the path operation function
Also, Couchbase recommends not using a single `Bucket` object in multiple "<abbr title="A sequence of code being executed by the program, while at the same time, or at intervals, there can be others being executed too.">thread</abbr>s", so, we can get just get the bucket directly and pass it to our utility functions:
```Python hl_lines="48 49 50 51 52"
-{!./tutorial/src/nosql_databases/tutorial001.py!}
+{!./src/nosql_databases/tutorial001.py!}
```
## Recap
You would have to make sure that it is unique for each operation.
```Python hl_lines="6"
-{!./tutorial/src/path_operation_advanced_configuration/tutorial001.py!}
+{!./src/path_operation_advanced_configuration/tutorial001.py!}
```
## 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`;
```Python hl_lines="6"
-{!./tutorial/src/path_operation_advanced_configuration/tutorial002.py!}
+{!./src/path_operation_advanced_configuration/tutorial002.py!}
```
But if you don't remember what each number code is for, you can use the shortcut constants from `starlette`:
```Python hl_lines="5 18"
-{!./tutorial/src/path_operation_configuration/tutorial001.py!}
+{!./src/path_operation_configuration/tutorial001.py!}
```
That status code will be used in the response and will be added to the OpenAPI schema.
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"
-{!./tutorial/src/path_operation_configuration/tutorial002.py!}
+{!./src/path_operation_configuration/tutorial002.py!}
```
They will be added to the OpenAPI schema and used by the automatic documentation interfaces:
You can add a `summary` and `description`:
```Python hl_lines="20 21"
-{!./tutorial/src/path_operation_configuration/tutorial003.py!}
+{!./src/path_operation_configuration/tutorial003.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.
```Python hl_lines="19 20 21 22 23 24 25 26 27"
-{!./tutorial/src/path_operation_configuration/tutorial004.py!}
+{!./src/path_operation_configuration/tutorial004.py!}
```
It will be used in the interactive docs:
You can specify the response description with the parameter `response_description`:
```Python hl_lines="21"
-{!./tutorial/src/path_operation_configuration/tutorial005.py!}
+{!./src/path_operation_configuration/tutorial005.py!}
```
!!! info
```Python hl_lines="16"
-{!./tutorial/src/path_operation_configuration/tutorial006.py!}
+{!./src/path_operation_configuration/tutorial006.py!}
```
It will be clearly marked as deprecated in the interactive docs:
First, import `Path` from `fastapi`:
```Python hl_lines="1"
-{!./tutorial/src/path_params_numeric_validations/tutorial001.py!}
+{!./src/path_params_numeric_validations/tutorial001.py!}
```
## Declare metadata
For example, to declare a `title` metadata value for the path parameter `item_id` you can type:
```Python hl_lines="8"
-{!./tutorial/src/path_params_numeric_validations/tutorial001.py!}
+{!./src/path_params_numeric_validations/tutorial001.py!}
```
!!! note
So, you can declare your function as:
```Python hl_lines="8"
-{!./tutorial/src/path_params_numeric_validations/tutorial002.py!}
+{!./src/path_params_numeric_validations/tutorial002.py!}
```
## Order the parameters as you need, tricks
Python won't do anything with that `*`, but it will know that all the following parameters should be called as keyword arguments (key-value pairs), also known as <abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Even if they don't have a default value.
```Python hl_lines="8"
-{!./tutorial/src/path_params_numeric_validations/tutorial003.py!}
+{!./src/path_params_numeric_validations/tutorial003.py!}
```
## Number validations: greater than or equal
Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`.
```Python hl_lines="8"
-{!./tutorial/src/path_params_numeric_validations/tutorial004.py!}
+{!./src/path_params_numeric_validations/tutorial004.py!}
```
## Number validations: greater than and less than or equal
* `le`: `l`ess than or `e`qual
```Python hl_lines="9"
-{!./tutorial/src/path_params_numeric_validations/tutorial005.py!}
+{!./src/path_params_numeric_validations/tutorial005.py!}
```
## Number validations: floats, greater than and less than
And the same for <abbr title="less than"><code>lt</code></abbr>.
```Python hl_lines="11"
-{!./tutorial/src/path_params_numeric_validations/tutorial006.py!}
+{!./src/path_params_numeric_validations/tutorial006.py!}
```
## Recap
You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
```Python hl_lines="6 7"
-{!./tutorial/src/path_params/tutorial001.py!}
+{!./src/path_params/tutorial001.py!}
```
The value of the path parameter `item_id` will be passed to your function as the argument `item_id`.
You can declare the type of a path parameter in the function, using standard Python type annotations:
```Python hl_lines="7"
-{!./tutorial/src/path_params/tutorial002.py!}
+{!./src/path_params/tutorial002.py!}
```
In this case, `item_id` is declared to be an `int`.
+++ /dev/null
-**Python 3.6+** has support for optional "type hints".
-
-These **"type hints"** are a new syntax (since Python 3.6+) that allow declaring the <abbr title="for example: str, int, float, bool">type</abbr> of a variable.
-
-By declaring types for your variables, editors and tools can give you better support.
-
-This is just a **quick tutorial / refresher** about Python type hints. It covers only the minimum necessary to use them with **FastAPI**... which is actually very little.
-
-**FastAPI** is all based on these type hints, they give it many advantages and benefits.
-
-But even if you never use **FastAPI**, you would benefit from learning a bit about them.
-
-!!! note
- If you are a Python expert, and you already know everything about type hints, skip to the next chapter.
-
-## Motivation
-
-Let's start with a simple example:
-
-```Python
-{!./tutorial/src/python_types/tutorial001.py!}
-```
-
-Calling this program outputs:
-
-```
-John Doe
-```
-
-The function does the following:
-
-* Takes a `fist_name` and `last_name`.
-* Converts the first letter of each one to upper case with `title()`.
-* <abbr title="Puts them together, as one. With the contents of one after the other.">Concatenates</abbr> them with a space in the middle.
-
-```Python hl_lines="2"
-{!./tutorial/src/python_types/tutorial001.py!}
-```
-
-### Edit it
-
-It's a very simple program.
-
-But now imagine that you were writing it from scratch.
-
-At some point you would have started the definition of the function, you had the parameters ready...
-
-But then you have to call "that method that converts the first letter to upper case".
-
-Was it `upper`? Was it `uppercase`? `first_uppercase`? `capitalize`?
-
-Then, you try with the old programer's friend, editor autocompletion.
-
-You type the first parameter of the function, `first_name`, then a dot (`.`) and then hit `Ctrl+Space` to trigger the completion.
-
-But, sadly, you get nothing useful:
-
-<img src="/img/tutorial/python-types/image01.png">
-
-### Add types
-
-Let's modify a single line from the previous version.
-
-We will change exactly this fragment, the parameters of the function, from:
-
-```Python
- first_name, last_name
-```
-
-to:
-
-```Python
- first_name: str, last_name: str
-```
-
-That's it.
-
-Those are the "type hints":
-
-```Python hl_lines="1"
-{!./tutorial/src/python_types/tutorial002.py!}
-```
-
-That is not the same as declaring default values like would be with:
-
-```Python
- first_name="john", last_name="doe"
-```
-
-It's a different thing.
-
-We are using colons (`:`), not equals (`=`).
-
-And adding type hints normally doesn't change what happens from what would happen without them.
-
-But now, imagine you are again in the middle of creating that function, but with type hints.
-
-At the same point, you try to trigger the autocomplete with `Ctrl+Space` and you see:
-
-<img src="/img/tutorial/python-types/image02.png">
-
-With that, you can scroll, seeing the options, until you find the one that "rings a bell":
-
-<img src="/img/tutorial/python-types/image03.png">
-
-## More motivation
-
-Check this function, it already has type hints:
-
-```Python hl_lines="1"
-{!./tutorial/src/python_types/tutorial003.py!}
-```
-
-Because the editor knows the types of the variables, you don't only get completion, you also get error checks:
-
-<img src="/img/tutorial/python-types/image04.png">
-
-Now you know that you have to fix it, convert `age` to a string with `str(age)`:
-
-```Python hl_lines="2"
-{!./tutorial/src/python_types/tutorial004.py!}
-```
-
-
-## Declaring types
-
-You just saw the main place to declare type hints. As function parameters.
-
-This is also the main place you would use them with **FastAPI**.
-
-### Simple types
-
-You can declare all the standard Python types, not only `str`.
-
-You can use, for example:
-
-* `int`
-* `float`
-* `bool`
-* `bytes`
-
-```Python hl_lines="1"
-{!./tutorial/src/python_types/tutorial005.py!}
-```
-
-### Types with subtypes
-
-There are some data structures that can contain other values, like `dict`, `list`, `set` and `tuple`. And the internal values can have their own type too.
-
-To declare those types and the subtypes, you can use the standard Python module `typing`.
-
-It exists specifically to support these type hints.
-
-#### Lists
-
-For example, let's define a variable to be a `list` of `str`.
-
-From `typing`, import `List` (with a capital `L`):
-
-```Python hl_lines="1"
-{!./tutorial/src/python_types/tutorial006.py!}
-```
-
-Declare the variable, with the same colon (`:`) syntax.
-
-As the type, put the `List`.
-
-As the list is a type that takes a "subtype", you put the subtype in square brackets:
-
-```Python hl_lines="4"
-{!./tutorial/src/python_types/tutorial006.py!}
-```
-
-That means: "the variable `items` is a `list`, and each of the items in this list is a `str`".
-
-By doing that, your editor can provide support even while processing items from the list.
-
-Without types, that's almost impossible to achieve:
-
-<img src="/img/tutorial/python-types/image05.png">
-
-Notice that the variable `item` is one of the elements in the list `items`.
-
-And still, the editor knows it is a `str`, and provides support for that.
-
-#### Tuples and Sets
-
-You would do the same to declare `tuple`s and `set`s:
-
-```Python hl_lines="1 4"
-{!./tutorial/src/python_types/tutorial007.py!}
-```
-
-This means:
-
-* The variable `items_t` is a `tuple`, and each of its items is an `int`.
-* The variable `items_s` is a `set`, and each of its items is of type `bytes`.
-
-#### Dicts
-
-To define a `dict`, you pass 2 subtypes, separated by commas.
-
-The first subtype is for the keys of the `dict`.
-
-The second subtype is for the values of the `dict`:
-
-```Python hl_lines="1 4"
-{!./tutorial/src/python_types/tutorial008.py!}
-```
-
-This means:
-
-* The variable `prices` is a `dict`:
- * 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.
-
-Let's say you have a class `Person`, with a name:
-
-```Python hl_lines="1 2 3"
-{!./tutorial/src/python_types/tutorial009.py!}
-```
-
-Then you can declare a variable to be of type `Person`:
-
-```Python hl_lines="6"
-{!./tutorial/src/python_types/tutorial009.py!}
-```
-
-And then, again, you get all the editor support:
-
-<img src="/img/tutorial/python-types/image06.png">
-
-
-## Pydantic models
-
-<a href="https://pydantic-docs.helpmanual.io/" target="_blank">Pydantic</a> is a Python library to perform data validation.
-
-You declare the "shape" of the data as classes with attributes.
-
-And each attribute has a type.
-
-Then you create an instance of that class with some values and it will validate the values, convert them to the appropriate type (if that's the case) and give you an object with all the data.
-
-And you get all the editor support with that resulting object.
-
-Taken from the official Pydantic docs:
-
-```Python
-{!./tutorial/src/python_types/tutorial010.py!}
-```
-
-!!! info
- To learn more about <a href="https://pydantic-docs.helpmanual.io/" target="_blank">Pydantic, check its docs</a>.
-
-**FastAPI** is all based on Pydantic.
-
-You will see a lot more of all this in practice in the next chapters.
-
-
-## Type hints in **FastAPI**
-
-**FastAPI** takes advantage of these type hints to do several things.
-
-With **FastAPI** you declare parameters with type hints and you get:
-
-* **Editor support**.
-* **Type checks**.
-
-...and **FastAPI** uses the same declarations to:
-
-* **Define requirements**: from request path parameters, query parameters, headers, bodies, dependencies, etc.
-* **Convert data**: from the request to the required type.
-* **Validate data**: coming from each request:
- * Generating **automatic errors** returned to the client when the data is invalid.
-* **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 next chapters.
-
-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.
-
-!!! info
- If you already went through all the tutorial and came back to see more about types, a good resource is <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" target="_blank">the "cheat sheet" from `mypy`</a>.
\ No newline at end of file
Let's take this application as example:
```Python hl_lines="7"
-{!./tutorial/src/query_params_str_validations/tutorial001.py!}
+{!./src/query_params_str_validations/tutorial001.py!}
```
The query parameter `q` is of type `str`, and by default is `None`, so it is optional.
To achieve that, first import `Query` from `fastapi`:
```Python hl_lines="1"
-{!./tutorial/src/query_params_str_validations/tutorial002.py!}
+{!./src/query_params_str_validations/tutorial002.py!}
```
## Use `Query` as the default value
And now use it as the default value of your parameter, setting the parameter `max_length` to 50:
```Python hl_lines="7"
-{!./tutorial/src/query_params_str_validations/tutorial002.py!}
+{!./src/query_params_str_validations/tutorial002.py!}
```
As we have to replace the default value `None` with `Query(None)`, the first parameter to `Query` serves the same purpose of defining that default value.
You can also add a parameter `min_length`:
```Python hl_lines="7"
-{!./tutorial/src/query_params_str_validations/tutorial003.py!}
+{!./src/query_params_str_validations/tutorial003.py!}
```
## Add regular expressions
You can define a <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">regular expression</abbr> that the parameter should match:
```Python hl_lines="8"
-{!./tutorial/src/query_params_str_validations/tutorial004.py!}
+{!./src/query_params_str_validations/tutorial004.py!}
```
This specific regular expression checks that the received parameter value:
Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
```Python hl_lines="7"
-{!./tutorial/src/query_params_str_validations/tutorial005.py!}
+{!./src/query_params_str_validations/tutorial005.py!}
```
!!! note
So, when you need to declare a value as required while using `Query`, you can use `...` as the first argument:
```Python hl_lines="7"
-{!./tutorial/src/query_params_str_validations/tutorial006.py!}
+{!./src/query_params_str_validations/tutorial006.py!}
```
!!! info
You can add a `title`:
```Python hl_lines="7"
-{!./tutorial/src/query_params_str_validations/tutorial007.py!}
+{!./src/query_params_str_validations/tutorial007.py!}
```
And a `description`:
```Python hl_lines="11"
-{!./tutorial/src/query_params_str_validations/tutorial008.py!}
+{!./src/query_params_str_validations/tutorial008.py!}
```
## Alias parameters
Then you can declare an `alias`, and that alias is what will be used to find the parameter value:
```Python hl_lines="7"
-{!./tutorial/src/query_params_str_validations/tutorial009.py!}
+{!./src/query_params_str_validations/tutorial009.py!}
```
## Deprecating parameters
Then pass the parameter `deprecated=True` to `Query`:
```Python hl_lines="16"
-{!./tutorial/src/query_params_str_validations/tutorial010.py!}
+{!./src/query_params_str_validations/tutorial010.py!}
```
The docs will show it like this:
When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.
```Python hl_lines="9"
-{!./tutorial/src/query_params/tutorial001.py!}
+{!./src/query_params/tutorial001.py!}
```
The query is the set of key-value pairs that go after the `?` in a URL, separated by `&` characters.
The same way, you can declare optional query parameters, by setting their default to `None`:
```Python hl_lines="7"
-{!./tutorial/src/query_params/tutorial002.py!}
+{!./src/query_params/tutorial002.py!}
```
In this case, the function parameter `q` will be optional, and will be `None` by default.
You can also declare `bool` types, and they will be converted:
```Python hl_lines="7"
-{!./tutorial/src/query_params/tutorial003.py!}
+{!./src/query_params/tutorial003.py!}
```
In this case, if you go to:
They will be detected by name:
```Python hl_lines="6 8"
-{!./tutorial/src/query_params/tutorial004.py!}
+{!./src/query_params/tutorial004.py!}
```
## Required query parameters
But when you want to make a query parameter required, you can just do not declare any default value:
```Python hl_lines="6 7"
-{!./tutorial/src/query_params/tutorial005.py!}
+{!./src/query_params/tutorial005.py!}
```
Here the query parameter `needy` is a required query parameter of type `str`.
And of course, you can define some parameters as required, some as having a default value, and some entirely optional:
```Python hl_lines="7"
-{!./tutorial/src/query_params/tutorial006.py!}
+{!./src/query_params/tutorial006.py!}
```
In this case, there are 3 query parameters:
Import `File` from `fastapi`:
```Python hl_lines="1"
-{!./tutorial/src/request_files/tutorial001.py!}
+{!./src/request_files/tutorial001.py!}
```
## Define `File` parameters
Create file parameters the same way you would for `Body` or `Form`:
```Python hl_lines="7"
-{!./tutorial/src/request_files/tutorial001.py!}
+{!./src/request_files/tutorial001.py!}
```
The files will be uploaded as form data and you will receive the contents as `bytes`.
## Import `File` and `Form`
```Python hl_lines="1"
-{!./tutorial/src/request_forms_and_files/tutorial001.py!}
+{!./src/request_forms_and_files/tutorial001.py!}
```
## Define `File` and `Form` parameters
Create file and form parameters the same way you would for `Body` or `Query`:
```Python hl_lines="7"
-{!./tutorial/src/request_forms_and_files/tutorial001.py!}
+{!./src/request_forms_and_files/tutorial001.py!}
```
The files and form fields will be uploaded as form data and you will receive the files and form fields.
Import `Form` from `fastapi`:
```Python hl_lines="1"
-{!./tutorial/src/request_forms/tutorial001.py!}
+{!./src/request_forms/tutorial001.py!}
```
## Define `Form` parameters
Create form parameters the same way you would for `Body` or `Query`:
```Python hl_lines="7"
-{!./tutorial/src/request_forms/tutorial001.py!}
+{!./src/request_forms/tutorial001.py!}
```
For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields.
* etc.
```Python hl_lines="17"
-{!./tutorial/src/response_model/tutorial001.py!}
+{!./src/response_model/tutorial001.py!}
```
!!! note
Here we are declaring a `UserIn` model, it will contain a plaintext password:
```Python hl_lines="8 10"
-{!./tutorial/src/response_model/tutorial002.py!}
+{!./src/response_model/tutorial002.py!}
```
And we are using this model to declare our input and the same model to declare our output:
```Python hl_lines="16 17"
-{!./tutorial/src/response_model/tutorial002.py!}
+{!./src/response_model/tutorial002.py!}
```
Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
We can instead create an input model with the plaintext password and an output model without it:
```Python hl_lines="8 10 15"
-{!./tutorial/src/response_model/tutorial003.py!}
+{!./src/response_model/tutorial003.py!}
```
Here, even though our path operation function is returning the same input user that contains the password:
```Python hl_lines="23"
-{!./tutorial/src/response_model/tutorial003.py!}
+{!./src/response_model/tutorial003.py!}
```
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
```Python hl_lines="21"
-{!./tutorial/src/response_model/tutorial003.py!}
+{!./src/response_model/tutorial003.py!}
```
So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
Coming soon...
```Python
-{!./tutorial/src/security/tutorial002.py!}
+{!./src/security/tutorial002.py!}
```
Coming soon...
```Python
-{!./tutorial/src/security/tutorial001.py!}
+{!./src/security/tutorial001.py!}
```
Coming soon...
```Python
-{!./tutorial/src/security/tutorial004.py!}
+{!./src/security/tutorial004.py!}
```
Coming soon...
```Python
-{!./tutorial/src/security/tutorial003.py!}
+{!./src/security/tutorial003.py!}
```
For now, don't pay attention to the rest, only the imports:
```Python hl_lines="3 4 5"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
## Define the database
Define the database that SQLAlchemy should connect to:
```Python hl_lines="8"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
!!! tip
## Create the SQLAlchemy `engine`
```Python hl_lines="10"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
## Create a `scoped_session`
```Python hl_lines="11 12 13"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
!!! note "Very Technical Details"
So, your models will behave very similarly to, for example, Flask-SQLAlchemy.
```Python hl_lines="15 16 17 18 19"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
## Create the SQLAlchemy `Base` model
```Python hl_lines="22"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
## Create your application data model
Here's a user model that will be a table in the database:
```Python hl_lines="25 26 27 28 29"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
## Get a user
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="32 33"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
## Create your **FastAPI** code
Create your app and path operation function:
```Python hl_lines="37 40 41 42 43"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
As we are using SQLAlchemy's `scoped_session`, we don't even have to create a dependency with `Depends`.
Then we should declare the path operation without `async def`, just with a normal `def`:
```Python hl_lines="41"
-{!./tutorial/src/sql_databases/tutorial001.py!}
+{!./src/sql_databases/tutorial001.py!}
```
## Migrations
#!/bin/sh -e
set -x
-autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place docs/tutorial/src/ fastapi tests --exclude=__init__.py
-black fastapi tests docs/tutorial/src
-isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --apply fastapi tests docs/tutorial/src
+autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place docs/src/ fastapi tests --exclude=__init__.py
+black fastapi tests docs/src
+isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --apply fastapi tests docs/src
from pathlib import Path, PurePath
from string import digits
-directory = Path("./docs/tutorial/src")
+directory = Path("./docs/src")
skip_names = {"bigger_applications"}
skip_dirs = {directory / name for name in skip_names}
dirs = sorted([Path(f) for f in directory.iterdir() if f not in skip_dirs])
export VERSION_SCRIPT="import sys; print('%s.%s' % sys.version_info[0:2])"
export PYTHON_VERSION=`python -c "$VERSION_SCRIPT"`
-export PYTHONPATH=./docs/tutorial/src
+export PYTHONPATH=./docs/src
# PYTHONPATH=. pytest --cov=fastapi --cov=tests --cov-fail-under=100 --cov-report=term-missing ${@} --cov-report=html
-pytest --cov=fastapi --cov=tests --cov=docs/tutorial/src --cov-report=term-missing ${@} --cov-report=html
+pytest --cov=fastapi --cov=tests --cov=docs/src --cov-report=term-missing ${@} --cov-report=html
mypy fastapi --disallow-untyped-defs
if [ "${PYTHON_VERSION}" = '3.7' ]; then
echo "Skipping 'black' on 3.7. See issue https://github.com/ambv/black/issues/494"