And you can also declare body parameters as optional, by setting the default to `None`:
-```Python hl_lines="18 19 20"
+```Python hl_lines="17 18 19"
{!./tutorial/src/body_multiple_params/tutorial001.py!}
```
But you can also declare multiple body parameters, e.g. `item` and `user`:
-```Python hl_lines="21"
+```Python hl_lines="20"
{!./tutorial/src/body_multiple_params/tutorial002.py!}
```
But you can instruct **FastAPI** to treat it as another body key using `Body`:
-```Python hl_lines="22"
+```Python hl_lines="21"
{!./tutorial/src/body_multiple_params/tutorial003.py!}
```
as in:
-```Python hl_lines="27"
+```Python hl_lines="25"
{!./tutorial/src/body_multiple_params/tutorial004.py!}
```
as in:
-```Python hl_lines="16"
+```Python hl_lines="15"
{!./tutorial/src/body_multiple_params/tutorial005.py!}
```
You can define an attribute to be a subtype. For example, a Python `list`:
-```Python hl_lines="13"
+```Python hl_lines="12"
{!./tutorial/src/body_nested_models/tutorial001.py!}
```
So, in our example, we can make `tags` be specifically a "list of strings":
-```Python hl_lines="15"
+```Python hl_lines="14"
{!./tutorial/src/body_nested_models/tutorial002.py!}
```
Then we can import `Set` and declare `tags` as a `set` of `str`:
-```Python hl_lines="1 15"
+```Python hl_lines="1 14"
{!./tutorial/src/body_nested_models/tutorial003.py!}
```
For example, we can define an `Image` model:
-```Python hl_lines="10 11 12"
+```Python hl_lines="9 10 11"
{!./tutorial/src/body_nested_models/tutorial004.py!}
```
And then we can use it as the type of an attribute:
-```Python hl_lines="21"
+```Python hl_lines="20"
{!./tutorial/src/body_nested_models/tutorial004.py!}
```
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="4 12"
+```Python hl_lines="5 11"
{!./tutorial/src/body_nested_models/tutorial005.py!}
```
You can also use Pydantic models as subtypes of `list`, `set`, etc:
-```Python hl_lines="22"
+```Python hl_lines="21"
{!./tutorial/src/body_nested_models/tutorial006.py!}
```
You can define arbitrarily deeply nested models:
-```Python hl_lines="11 16 22 25 29"
+```Python hl_lines="10 15 21 24 28"
{!./tutorial/src/body_nested_models/tutorial007.py!}
```
as in:
-```Python hl_lines="17"
+```Python hl_lines="16"
{!./tutorial/src/body_nested_models/tutorial008.py!}
```
First, you have to import it:
-```Python hl_lines="3"
+```Python hl_lines="2"
{!./tutorial/src/body_schema/tutorial001.py!}
```
You can then use `Schema` with model attributes:
-```Python hl_lines="10 11"
+```Python hl_lines="9 10"
{!./tutorial/src/body_schema/tutorial001.py!}
```
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="21 22 23 24 25 26"
+```Python hl_lines="20 21 22 23 24 25"
{!./tutorial/src/body_schema/tutorial002.py!}
```
First, you need to import `BaseModel` from `pydantic`:
-```Python hl_lines="1"
+```Python hl_lines="2"
{!./tutorial/src/body/tutorial001.py!}
```
Use standard Python types for all the attributes:
-```Python hl_lines="6 7 8 9 10"
+```Python hl_lines="5 6 7 8 9"
{!./tutorial/src/body/tutorial001.py!}
```
To add it to your path operation, declare it the same way you declared path and query parameters:
-```Python hl_lines="17"
+```Python hl_lines="16"
{!./tutorial/src/body/tutorial001.py!}
```
Inside of the function, you can access all the attributes of the model object directly:
-```Python hl_lines="20"
+```Python hl_lines="19"
{!./tutorial/src/body/tutorial002.py!}
```
**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="16 17"
+```Python hl_lines="15 16"
{!./tutorial/src/body/tutorial003.py!}
```
**FastAPI** will recognize each of them and take the data from the correct place.
-```Python hl_lines="17"
+```Python hl_lines="16"
{!./tutorial/src/body/tutorial004.py!}
```
### Import `UJSONResponse`
-```Python hl_lines="1"
+```Python hl_lines="2"
{!./tutorial/src/custom_response/tutorial001.py!}
```
Make your path operation use `UJSONResponse` as the response class using the parameter `content_type`:
-```Python hl_lines="8"
+```Python hl_lines="7"
{!./tutorial/src/custom_response/tutorial001.py!}
```
### Import `HTMLResponse`
-```Python hl_lines="1"
+```Python hl_lines="2"
{!./tutorial/src/custom_response/tutorial002.py!}
```
Pass `HTMLResponse` as the parameter `content_type` of your path operation:
-```Python hl_lines="8"
+```Python hl_lines="7"
{!./tutorial/src/custom_response/tutorial002.py!}
```
The same example from above, returning an `HTMLResponse`, could look like:
-```Python hl_lines="8 20"
+```Python hl_lines="7"
{!./tutorial/src/custom_response/tutorial003.py!}
```
For example, it could be something like:
-```Python hl_lines="8 19 22"
+```Python hl_lines="7 23"
{!./tutorial/src/custom_response/tutorial004.py!}
```
But by declaring it also in the path operation decorator:
-```Python hl_lines="22"
+```Python hl_lines="21"
{!./tutorial/src/custom_response/tutorial004.py!}
```
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="9 11 16 22 24 33 35 40 41"
+```Python hl_lines="8 10 15 21 23 32 34 39 40"
{!./tutorial/src/extra_models/tutorial001.py!}
```
That way, we can declare just the differences between the models (with plaintext `password`, with `hashed_password` and without password):
-```Python hl_lines="9 15 16 19 20 23 24"
+```Python hl_lines="8 14 15 18 19 22 23"
{!./tutorial/src/extra_models/tutorial002.py!}
```
For now, don't pay attention to the rest, only the imports:
-```Python hl_lines="5 6 7"
+```Python hl_lines="6 7 8"
{!./tutorial/src/nosql_databases/tutorial001.py!}
```
* Set defaults for timeouts.
* Return it.
-```Python hl_lines="13 14 15 16 17 18 19 20 21 22"
+```Python hl_lines="13 14 15 16 17 18 19 20"
{!./tutorial/src/nosql_databases/tutorial001.py!}
```
First, let's create a `User` model:
-```Python hl_lines="25 26 27 28 29"
+```Python hl_lines="23 24 25 26 27"
{!./tutorial/src/nosql_databases/tutorial001.py!}
```
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="32 33 34"
+```Python hl_lines="30 31 32"
{!./tutorial/src/nosql_databases/tutorial001.py!}
```
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"
+```Python hl_lines="35 36 37 38 39 40 41"
{!./tutorial/src/nosql_databases/tutorial001.py!}
```
### Create the `FastAPI` app
-```Python hl_lines="47"
+```Python hl_lines="45"
{!./tutorial/src/nosql_databases/tutorial001.py!}
```
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="50 51 52 53 54"
+```Python hl_lines="48 49 50 51 52"
{!./tutorial/src/nosql_databases/tutorial001.py!}
```
But if you don't remember what each number code is for, you can use the shortcut constants from `starlette`:
-```Python hl_lines="4 19"
+```Python hl_lines="5 18"
{!./tutorial/src/path_operation_configuration/tutorial001.py!}
```
You can add tags to your path operation, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
-```Python hl_lines="18 23 28"
+```Python hl_lines="17 22 27"
{!./tutorial/src/path_operation_configuration/tutorial002.py!}
```
You can add a `summary` and `description`:
-```Python hl_lines="21 22"
+```Python hl_lines="20 21"
{!./tutorial/src/path_operation_configuration/tutorial003.py!}
```
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="20 21 22 23 24 25 26 27 28"
+```Python hl_lines="19 20 21 22 23 24 25 26 27"
{!./tutorial/src/path_operation_configuration/tutorial004.py!}
```
You can specify the response description with the parameter `response_description`:
-```Python hl_lines="22"
+```Python hl_lines="21"
{!./tutorial/src/path_operation_configuration/tutorial005.py!}
```
* `@app.delete()`
* etc.
-```Python hl_lines="18"
+```Python hl_lines="17"
{!./tutorial/src/response_model/tutorial001.py!}
```
Here we are declaring a `UserIn` model, it will contain a plaintext password:
-```Python hl_lines="9 11"
+```Python hl_lines="8 10"
{!./tutorial/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="17 18"
+```Python hl_lines="16 17"
{!./tutorial/src/response_model/tutorial002.py!}
```
We can instead create an input model with the plaintext password and an output model without it:
-```Python hl_lines="9 11 16"
+```Python hl_lines="8 10 15"
{!./tutorial/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="24"
+```Python hl_lines="23"
{!./tutorial/src/response_model/tutorial003.py!}
```
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
-```Python hl_lines="22"
+```Python hl_lines="21"
{!./tutorial/src/response_model/tutorial003.py!}
```
For now, don't pay attention to the rest, only the imports:
-```Python hl_lines="2 3 4"
+```Python hl_lines="3 4 5"
{!./tutorial/src/sql_databases/tutorial001.py!}
```
Define the database that SQLAlchemy should connect to:
-```Python hl_lines="7"
+```Python hl_lines="8"
{!./tutorial/src/sql_databases/tutorial001.py!}
```
## Create the SQLAlchemy `engine`
-```Python hl_lines="9"
+```Python hl_lines="10"
{!./tutorial/src/sql_databases/tutorial001.py!}
```
## Create a `scoped_session`
-```Python hl_lines="10 11 12"
+```Python hl_lines="11 12 13"
{!./tutorial/src/sql_databases/tutorial001.py!}
```