* Create a file `main.py` with:
```Python
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="7 12"
+```Python hl_lines="9 14"
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: str = None):
+async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="2 7 8 9 10 23 24 25"
+```Python hl_lines="4 9 10 11 12 25 26 27"
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
- is_offer: bool = None
+ is_offer: Optional[bool] = None
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
For example, you can add an additional media type of `image/png`, declaring that your *path operation* can return a JSON object (with media type `application/json`) or a PNG image:
-```Python hl_lines="17 18 19 20 21 22 23 24 28"
+```Python hl_lines="19 20 21 22 23 24 28"
{!../../../docs_src/additional_responses/tutorial002.py!}
```
For example:
-```Python hl_lines="11 12 13 14 15 24"
+```Python hl_lines="13 14 15 16 17 26"
{!../../../docs_src/additional_responses/tutorial004.py!}
```
To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
-```Python hl_lines="2 19"
+```Python hl_lines="4 23"
{!../../../docs_src/additional_status_codes/tutorial001.py!}
```
This part is pretty normal, most of the code is probably already familiar to you:
-```Python hl_lines="8 9 10 11 12 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53"
+```Python hl_lines="10 11 12 13 14 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
But as we are never calling `app.include_router(some_router)`, we need to set the `default_response_class` during creation of the `APIRouter`.
-```Python hl_lines="3 24"
+```Python hl_lines="5 26"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`.
* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`.
-```Python hl_lines="15 16 17 20 21 27 28 29 30 31"
+```Python hl_lines="17 18 19 22 23 29 30 31 32 33"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` (that's actually just a `list` of routes/*path operations*) from that callback router:
-```Python hl_lines="34"
+```Python hl_lines="36"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
For those cases, you can use the `jsonable_encoder` to convert your data before passing it to a response:
-```Python hl_lines="4 6 20 21"
+```Python hl_lines="6 7 21 22"
{!../../../docs_src/response_directly/tutorial001.py!}
```
And then **FastAPI** will call that override instead of the original dependency.
-```Python hl_lines="24 25 28"
+```Python hl_lines="26 27 30"
{!../../../docs_src/dependency_testing/tutorial001.py!}
```
They work the same way as for other FastAPI endpoints/*path operations*:
-```Python hl_lines="56 57 58 59 60 61 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79"
+```Python hl_lines="58 59 60 61 62 63 64 65 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83"
{!../../../docs_src/websockets/tutorial002.py!}
```
* Create a `main.py` file with:
```Python
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
* Create a file `main.py` with:
```Python
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="7 12"
+```Python hl_lines="9 14"
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: str = None):
+async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="2 7 8 9 10 23 24 25"
+```Python hl_lines="4 9 10 11 12 25 26 27"
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
- is_offer: bool = None
+ is_offer: Optional[bool] = None
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
**FastAPI** knows what to do in each case and how to re-use the same object, so that all the background tasks are merged together and are run in the background afterwards:
-```Python hl_lines="11 14 20 23"
+```Python hl_lines="13 15 22 25"
{!../../../docs_src/background_tasks/tutorial002.py!}
```
First, you have to import it:
-```Python hl_lines="2"
+```Python hl_lines="4"
{!../../../docs_src/body_fields/tutorial001.py!}
```
You can then use `Field` with model attributes:
-```Python hl_lines="9 10"
+```Python hl_lines="11 12 13 14"
{!../../../docs_src/body_fields/tutorial001.py!}
```
And you can also declare body parameters as optional, by setting the default to `None`:
-```Python hl_lines="17 18 19"
+```Python hl_lines="19 20 21"
{!../../../docs_src/body_multiple_params/tutorial001.py!}
```
But you can also declare multiple body parameters, e.g. `item` and `user`:
-```Python hl_lines="20"
+```Python hl_lines="22"
{!../../../docs_src/body_multiple_params/tutorial002.py!}
```
But you can instruct **FastAPI** to treat it as another body key using `Body`:
-```Python hl_lines="21"
+```Python hl_lines="23"
{!../../../docs_src/body_multiple_params/tutorial003.py!}
```
As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
```Python
-q: str = None
+q: Optional[str] = None
```
as in:
-```Python hl_lines="25"
+```Python hl_lines="27"
{!../../../docs_src/body_multiple_params/tutorial004.py!}
```
as in:
-```Python hl_lines="15"
+```Python hl_lines="17"
{!../../../docs_src/body_multiple_params/tutorial005.py!}
```
You can define an attribute to be a subtype. For example, a Python `list`:
-```Python hl_lines="12"
+```Python hl_lines="14"
{!../../../docs_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.
-## List fields with subtype
+## List fields with type parameter
-But Python has a specific way to declare lists with subtypes:
+But Python has a specific way to declare lists with internal types, or "type parameters":
### Import typing's `List`
{!../../../docs_src/body_nested_models/tutorial002.py!}
```
-### Declare a `List` with a subtype
+### Declare a `List` with a type parameter
-To declare types that have subtypes, like `list`, `dict`, `tuple`:
+To declare types that have type parameters (internal types), like `list`, `dict`, `tuple`:
* Import them from the `typing` module
-* Pass the subtype(s) as "type arguments" using square brackets: `[` and `]`
+* Pass the internal type(s) as "type parameters" using square brackets: `[` and `]`
```Python
from typing import List
That's all standard Python syntax for type declarations.
-Use that same standard syntax for model attributes with subtypes.
+Use that same standard syntax for model attributes with internal types.
So, in our example, we can make `tags` be specifically a "list of strings":
But that type can itself be another Pydantic model.
-So, you can declare deeply nested JSON `object`s with specific attribute names, types and validations.
+So, you can declare deeply nested JSON "objects" with specific attribute names, types and validations.
All that, arbitrarily nested.
```
!!! info
- Notice how `Offer` as a list of `Item`s, which in turn have an optional list of `Image`s
+ Notice how `Offer` has a list of `Item`s, which in turn have an optional list of `Image`s
## Bodies of pure lists
First, you need to import `BaseModel` from `pydantic`:
-```Python hl_lines="2"
+```Python hl_lines="4"
{!../../../docs_src/body/tutorial001.py!}
```
Use standard Python types for all the attributes:
-```Python hl_lines="5 6 7 8 9"
+```Python hl_lines="7 8 9 10 11"
{!../../../docs_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="16"
+```Python hl_lines="18"
{!../../../docs_src/body/tutorial001.py!}
```
Inside of the function, you can access all the attributes of the model object directly:
-```Python hl_lines="19"
+```Python hl_lines="21"
{!../../../docs_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="15 16"
+```Python hl_lines="17 18"
{!../../../docs_src/body/tutorial003.py!}
```
**FastAPI** will recognize each of them and take the data from the correct place.
-```Python hl_lines="16"
+```Python hl_lines="18"
{!../../../docs_src/body/tutorial004.py!}
```
* If the parameter is of a **singular type** (like `int`, `float`, `str`, `bool`, etc) it will be interpreted as a **query** parameter.
* If the parameter is declared to be of the type of a **Pydantic model**, it will be interpreted as a request **body**.
+!!! note
+ FastAPI will know that the value of `q` is not required because of the default value `= None`.
+
+ The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
+
## Without Pydantic
If you don't want to use Pydantic models, you can also use **Body** parameters. See the docs for [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
First import `Cookie`:
-```Python hl_lines="1"
+```Python hl_lines="3"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
The first value is the default value, you can pass all the extra validation or annotation parameters:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
In the previous example, we were returning a `dict` from our dependency ("dependable"):
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/dependencies/tutorial001.py!}
```
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParameters`:
-```Python hl_lines="9 10 11 12 13"
+```Python hl_lines="11 12 13 14 15"
{!../../../docs_src/dependencies/tutorial002.py!}
```
Pay attention to the `__init__` method used to create the instance of the class:
-```Python hl_lines="10"
+```Python hl_lines="12"
{!../../../docs_src/dependencies/tutorial002.py!}
```
...it has the same parameters as our previous `common_parameters`:
-```Python hl_lines="6"
+```Python hl_lines="8"
{!../../../docs_src/dependencies/tutorial001.py!}
```
And as when **FastAPI** calls that class the value that will be passed as `commons` to your function will be an "instance" of the class, you can declare that parameter `commons` to be of type of the class, `CommonQueryParams`.
-```Python hl_lines="17"
+```Python hl_lines="19"
{!../../../docs_src/dependencies/tutorial002.py!}
```
..as in:
-```Python hl_lines="17"
+```Python hl_lines="19"
{!../../../docs_src/dependencies/tutorial003.py!}
```
So, the same example would look like:
-```Python hl_lines="17"
+```Python hl_lines="19"
{!../../../docs_src/dependencies/tutorial004.py!}
```
It is just a function that can take all the same parameters that a *path operation function* can take:
-```Python hl_lines="6 7"
+```Python hl_lines="8 9"
{!../../../docs_src/dependencies/tutorial001.py!}
```
### Import `Depends`
-```Python hl_lines="1"
+```Python hl_lines="3"
{!../../../docs_src/dependencies/tutorial001.py!}
```
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"
+```Python hl_lines="13 18"
{!../../../docs_src/dependencies/tutorial001.py!}
```
You could create a first dependency ("dependable") like:
-```Python hl_lines="6 7"
+```Python hl_lines="8 9"
{!../../../docs_src/dependencies/tutorial005.py!}
```
Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
-```Python hl_lines="11"
+```Python hl_lines="13"
{!../../../docs_src/dependencies/tutorial005.py!}
```
Then we can use the dependency with:
-```Python hl_lines="19"
+```Python hl_lines="21"
{!../../../docs_src/dependencies/tutorial005.py!}
```
It receives an object, like a Pydantic model, and returns a JSON compatible version:
-```Python hl_lines="4 21"
+```Python hl_lines="5 22"
{!../../../docs_src/encoder/tutorial001.py!}
```
Here's an example *path operation* with parameters using some of the above types.
-```Python hl_lines="1 2 11 12 13 14 15"
+```Python hl_lines="1 3 12 13 14 15 16"
{!../../../docs_src/extra_data_types/tutorial001.py!}
```
Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
-```Python hl_lines="17 18"
+```Python hl_lines="18 19"
{!../../../docs_src/extra_data_types/tutorial001.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="7 9 14 20 22 27 28 31 32 33 38 39"
+```Python hl_lines="9 11 16 22 24 29 30 33 34 35 40 41"
{!../../../docs_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="7 13 14 17 18 21 22"
+```Python hl_lines="9 15 16 19 20 23 24"
{!../../../docs_src/extra_models/tutorial002.py!}
```
You will receive a response telling you that the data is invalid containing the received body:
-```JSON hl_lines="13 14 15 16"
+```JSON hl_lines="12 13 14 15"
{
"detail": [
{
First import `Header`:
-```Python hl_lines="1"
+```Python hl_lines="3"
{!../../../docs_src/header_params/tutorial001.py!}
```
The first value is the default value, you can pass all the extra validation or annotation parameters:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/header_params/tutorial001.py!}
```
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"
+```Python hl_lines="10"
{!../../../docs_src/header_params/tutorial002.py!}
```
First, import `Path` from `fastapi`:
-```Python hl_lines="1"
+```Python hl_lines="3"
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
For example, to declare a `title` metadata value for the path parameter `item_id` you can type:
-```Python hl_lines="8"
+```Python hl_lines="10"
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
Let's take this application as example:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial001.py!}
```
-The query parameter `q` is of type `str`, and by default is `None`, so it is optional.
+The query parameter `q` is of type `Optional[str]`, that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
+
+!!! note
+ FastAPI will know that the value of `q` is not required because of the default value `= None`.
+
+ The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
## Additional validation
To achieve that, first import `Query` from `fastapi`:
-```Python hl_lines="1"
+```Python hl_lines="3"
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
And now use it as the default value of your parameter, setting the parameter `max_length` to 50:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
So:
```Python
-q: str = Query(None)
+q: Optional[str] = Query(None)
```
...makes the parameter optional, the same as:
```Python
-q: str = None
+q: Optional[str] = None
```
But it declares it explicitly as being a query parameter.
-And then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
+!!! info
+ Have in mind that FastAPI cares about the part:
+
+ ```Python
+ = None
+ ```
+
+ or the:
+
+ ```Python
+ = Query(None)
+ ```
+
+ and will use that `None` to detect that the query parameter is not required.
+
+ The `Optional` part is only to allow your editor to provide better support.
+
+Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
```Python
q: str = Query(None, max_length=50)
You can also add a parameter `min_length`:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial003.py!}
```
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"
+```Python hl_lines="10"
{!../../../docs_src/query_params_str_validations/tutorial004.py!}
```
instead of:
```Python
-q: str = None
+q: Optional[str] = None
```
But we are now declaring it with `Query`, for example like:
```Python
-q: str = Query(None, min_length=3)
+q: Optional[str] = Query(None, min_length=3)
```
So, when you need to declare a value as required while using `Query`, you can use `...` as the first argument:
You can add a `title`:
-```Python hl_lines="7"
+```Python hl_lines="10"
{!../../../docs_src/query_params_str_validations/tutorial007.py!}
```
And a `description`:
-```Python hl_lines="11"
+```Python hl_lines="13"
{!../../../docs_src/query_params_str_validations/tutorial008.py!}
```
Then you can declare an `alias`, and that alias is what will be used to find the parameter value:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial009.py!}
```
Then pass the parameter `deprecated=True` to `Query`:
-```Python hl_lines="16"
+```Python hl_lines="18"
{!../../../docs_src/query_params_str_validations/tutorial010.py!}
```
The same way, you can declare optional query parameters, by setting their default to `None`:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial002.py!}
```
!!! check
Also notice that **FastAPI** is smart enough to notice that the path parameter `item_id` is a path parameter and `q` is not, so, it's a query parameter.
+!!! note
+ FastAPI will know that `q` is optional because of the `= None`.
+
+ The `Optional` in `Optional[str]` is not used by FastAPI (FastAPI will only use the `str` part), but the `Optional[str]` will let your editor help you finding errors in your code.
+
## Query parameter type conversion
You can also declare `bool` types, and they will be converted:
-```Python hl_lines="7"
+```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial003.py!}
```
They will be detected by name:
-```Python hl_lines="6 8"
+```Python hl_lines="8 10"
{!../../../docs_src/query_params/tutorial004.py!}
```
And of course, you can define some parameters as required, some as having a default value, and some entirely optional:
-```Python hl_lines="7"
+```Python hl_lines="10"
{!../../../docs_src/query_params/tutorial006.py!}
```
!!! tip
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
-
-!!! warning
- This might be an advanced use case.
-
- You might want to skip it.
-
-If you are using `mypy` it could complain with type declarations like:
-
-```Python
-limit: int = None
-```
-
-With an error like:
-
-```
-Incompatible types in assignment (expression has type "None", variable has type "int")
-```
-
-In those cases you can use `Optional` to tell `mypy` that the value could be `None`, like:
-
-```Python
-from typing import Optional
-
-limit: Optional[int] = None
-```
-
-In a *path operation* that could look like:
-
-```Python hl_lines="9"
-{!../../../docs_src/query_params/tutorial007.py!}
-```
Here we are declaring a `UserIn` model, it will contain a plaintext password:
-```Python hl_lines="7 9"
+```Python hl_lines="9 11"
{!../../../docs_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="15 16"
+```Python hl_lines="17 18"
{!../../../docs_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="7 9 14"
+```Python hl_lines="9 11 16"
{!../../../docs_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="22"
+```Python hl_lines="24"
{!../../../docs_src/response_model/tutorial003.py!}
```
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
-```Python hl_lines="20"
+```Python hl_lines="22"
{!../../../docs_src/response_model/tutorial003.py!}
```
{!../../../docs_src/response_model/tutorial004.py!}
```
-* `description: str = None` has a default of `None`.
+* `description: Optional[str] = None` has a default of `None`.
* `tax: float = 10.5` has a default of `10.5`.
-* `tags: List[str] = []` has a default of an empty list: `[]`.
+* `tags: List[str] = []` as a default of an empty list: `[]`.
but you might want to omit them from the result if they were not actually stored.
This is because the JSON Schema generated in your app's OpenAPI (and the docs) will still be the one for the complete model, even if you use `response_model_include` or `response_model_exclude` to omit some attributes.
-```Python hl_lines="29 35"
+ This also applies to `response_model_by_alias` that works similarly.
+
+```Python hl_lines="31 37"
{!../../../docs_src/response_model/tutorial005.py!}
```
If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will still convert it to a `set` and it will work correctly:
-```Python hl_lines="29 35"
+```Python hl_lines="31 37"
{!../../../docs_src/response_model/tutorial006.py!}
```
You can declare an example for a Pydantic model using `Config` and `schema_extra`, as described in <a href="https://pydantic-docs.helpmanual.io/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic's docs: Schema customization</a>:
-```Python hl_lines="13 14 15 16 17 18 19 20 21"
+```Python hl_lines="15 16 17 18 19 20 21 22 23"
{!../../../docs_src/schema_extra_example/tutorial001.py!}
```
In `Field`, `Path`, `Query`, `Body` and others you'll see later, you can also declare extra info for the JSON Schema by passing any other arbitrary arguments to the function, for example, to add an `example`:
-```Python hl_lines="2 8 9 10 11"
+```Python hl_lines="4 10 11 12 13"
{!../../../docs_src/schema_extra_example/tutorial002.py!}
```
For example, you can pass an `example` for a body request to `Body`:
-```Python hl_lines="19 20 21 22 23 24"
+```Python hl_lines="21 22 23 24 25 26"
{!../../../docs_src/schema_extra_example/tutorial003.py!}
```
And another one to authenticate and return a user.
-```Python hl_lines="7 48 55 56 59 60 69 70 71 72 73 74 75"
+```Python hl_lines="8 49 56 57 60 61 70 71 72 73 74 75 76"
{!../../../docs_src/security/tutorial004.py!}
```
Create a utility function to generate a new access token.
-```Python hl_lines="3 6 12 13 14 28 29 30 78 79 80 81 82 83 84 85 86"
+```Python hl_lines="4 7 13 14 15 29 30 31 79 80 81 82 83 84 85 86 87"
{!../../../docs_src/security/tutorial004.py!}
```
If the token is invalid, return an HTTP error right away.
-```Python hl_lines="89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106"
+```Python hl_lines="90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107"
{!../../../docs_src/security/tutorial004.py!}
```
Create a real JWT access token and return it.
-```Python hl_lines="115 116 117 118 119 120 121 122 123 124 125 126 127 128"
+```Python hl_lines="116 117 118 119 120 121 122 123 124 125 126 127 128 129"
{!../../../docs_src/security/tutorial004.py!}
```
First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` for the path `/token`:
-```Python hl_lines="2 74"
+```Python hl_lines="4 76"
{!../../../docs_src/security/tutorial003.py!}
```
For the error, we use the exception `HTTPException`:
-```Python hl_lines="1 75 76 77"
+```Python hl_lines="3 77 78 79"
{!../../../docs_src/security/tutorial003.py!}
```
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="78 79 80 81"
+```Python hl_lines="80 81 82 83"
{!../../../docs_src/security/tutorial003.py!}
```
But for now, let's focus on the specific details we need.
-```Python hl_lines="83"
+```Python hl_lines="85"
{!../../../docs_src/security/tutorial003.py!}
```
So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
-```Python hl_lines="56 57 58 59 60 61 62 63 64 65 67 68 69 70 88"
+```Python hl_lines="58 59 60 61 62 63 64 65 66 67 69 70 71 72 90"
{!../../../docs_src/security/tutorial003.py!}
```
```Python
from fastapi import FastAPI
+from typing import Optional
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
```Python hl_lines="7 12"
from fastapi import FastAPI
+from typing import Optional
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: str = None):
+async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
```Python hl_lines="2 7 8 9 10 23 24 25"
from fastapi import FastAPI
from pydantic import BaseModel
+from typing import Optional
app = FastAPI()
class Item(BaseModel):
name: str
price: float
- is_offer: bool = None
+ is_offer: Optional[bool] = None
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```Python
from fastapi import FastAPI
+from typing import Optional
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: str = Optional[None]):
return {"item_id": item_id, "q": q}
```
```Python hl_lines="7 12"
from fastapi import FastAPI
+from typing import Optional
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: str = None):
+async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
```Python hl_lines="2 7 8 9 10 23 24 25"
from fastapi import FastAPI
from pydantic import BaseModel
+from typing import Optional
app = FastAPI()
class Item(BaseModel):
name: str
price: float
- is_offer: bool = None
+ is_offer: bool = Optional[None]
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
* Crie um arquivo `main.py` com:
```Python
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
Se seu código utiliza `async` / `await`, use `async def`:
-```Python hl_lines="7 12"
+```Python hl_lines="9 14"
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: str = None):
+async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
Declare o corpo utilizando tipos padrão Python, graças ao Pydantic.
-```Python hl_lines="2 7 8 9 10 23 24 25"
+```Python hl_lines="4 9 10 11 12 25 26 27"
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
- is_offer: bool = None
+ is_offer: Optional[bool] = None
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
* Create a file `main.py` with:
```Python
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
If your code uses `async` / `await`, use `async def`:
-```Python hl_lines="7 12"
+```Python hl_lines="9 14"
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: str = None):
+async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
Declare the body using standard Python types, thanks to Pydantic.
-```Python hl_lines="2 7 8 9 10 23 24 25"
+```Python hl_lines="4 9 10 11 12 25 26 27"
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
- is_offer: bool = None
+ is_offer: Optional[bool] = None
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
* 创建一个 `main.py` 文件,内容如下:
```Python
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
* 创建一个 `main.py` 文件并写入以下内容:
```Python
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
如果你的代码里会出现 `async` / `await`,请使用 `async def`:
-```Python hl_lines="7 12"
+```Python hl_lines="9 14"
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: int, q: str = None):
+async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
我们借助 Pydantic 来使用标准的 Python 类型声明请求体。
-```Python hl_lines="2 7 8 9 10 23 24 25"
+```Python hl_lines="4 9 10 11 12 25 26 27"
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
- is_offer: bool = None
+ is_offer: Optional[bool] = None
@app.get("/")
@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
+def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
+from typing import Optional
+
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel
}
},
)
-async def read_item(item_id: str, img: bool = None):
+async def read_item(item_id: str, img: Optional[bool] = None):
if img:
return FileResponse("image.png", media_type="image/png")
else:
+from typing import Optional
+
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel
response_model=Item,
responses={**responses, 200: {"content": {"image/png": {}}}},
)
-async def read_item(item_id: str, img: bool = None):
+async def read_item(item_id: str, img: Optional[bool] = None):
if img:
return FileResponse("image.png", media_type="image/png")
else:
+from typing import Optional
+
from fastapi import Body, FastAPI, status
from fastapi.responses import JSONResponse
@app.put("/items/{item_id}")
-async def upsert_item(item_id: str, name: str = Body(None), size: int = Body(None)):
+async def upsert_item(
+ item_id: str, name: Optional[str] = Body(None), size: Optional[int] = Body(None)
+):
if item_id in items:
item = items[item_id]
item["name"] = name
+from typing import Optional
+
from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel
class Item(BaseModel):
id: str
title: str
- description: str = None
+ description: Optional[str] = None
@app.get("/items/{item_id}", response_model=Item)
+from typing import Optional
+
from fastapi import BackgroundTasks, Depends, FastAPI
app = FastAPI()
log.write(message)
-def get_query(background_tasks: BackgroundTasks, q: str = None):
+def get_query(background_tasks: BackgroundTasks, q: Optional[str] = None):
if q:
message = f"found query: {q}\n"
background_tasks.add_task(write_log, message)
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
app = FastAPI()
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
app = FastAPI()
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
app = FastAPI()
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
app = FastAPI()
@app.put("/items/{item_id}")
-async def create_item(item_id: int, item: Item, q: str = None):
+async def create_item(item_id: int, item: Item, q: Optional[str] = None):
result = {"item_id": item_id, **item.dict()}
if q:
result.update({"q": q})
+from typing import Optional
+
from fastapi import Body, FastAPI
from pydantic import BaseModel, Field
class Item(BaseModel):
name: str
- description: str = Field(None, title="The description of the item", max_length=300)
+ description: Optional[str] = Field(
+ None, title="The description of the item", max_length=300
+ )
price: float = Field(..., gt=0, description="The price must be greater than zero")
- tax: float = None
+ tax: Optional[float] = None
@app.put("/items/{item_id}")
+from typing import Optional
+
from fastapi import FastAPI, Path
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
- q: str = None,
- item: Item = None,
+ q: Optional[str] = None,
+ item: Optional[Item] = None,
):
results = {"item_id": item_id}
if q:
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
class User(BaseModel):
username: str
- full_name: str = None
+ full_name: Optional[str] = None
@app.put("/items/{item_id}")
+from typing import Optional
+
from fastapi import Body, FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
class User(BaseModel):
username: str
- full_name: str = None
+ full_name: Optional[str] = None
@app.put("/items/{item_id}")
+from typing import Optional
+
from fastapi import Body, FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
class User(BaseModel):
username: str
- full_name: str = None
+ full_name: Optional[str] = None
@app.put("/items/{item_id}")
item: Item,
user: User,
importance: int = Body(..., gt=0),
- q: str = None
+ q: Optional[str] = None
):
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
if q:
+from typing import Optional
+
from fastapi import Body, FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
@app.put("/items/{item_id}")
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: list = []
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: List[str] = []
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = set()
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
- image: Image = None
+ image: Optional[Image] = None
@app.put("/items/{item_id}")
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
- image: Image = None
+ image: Optional[Image] = None
@app.put("/items/{item_id}")
-from typing import List, Set
+from typing import List, Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
- images: List[Image] = None
+ images: Optional[List[Image]] = None
@app.put("/items/{item_id}")
-from typing import List, Set
+from typing import List, Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrl
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
- images: List[Image] = None
+ images: Optional[List[Image]] = None
class Offer(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
items: List[Item]
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
class Item(BaseModel):
- name: str = None
- description: str = None
- price: float = None
+ name: Optional[str] = None
+ description: Optional[str] = None
+ price: Optional[float] = None
tax: float = 10.5
tags: List[str] = []
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
class Item(BaseModel):
- name: str = None
- description: str = None
- price: float = None
+ name: Optional[str] = None
+ description: Optional[str] = None
+ price: Optional[float] = None
tax: float = 10.5
tags: List[str] = []
+from typing import Optional
+
from fastapi import Cookie, FastAPI
app = FastAPI()
@app.get("/items/")
-async def read_items(ads_id: str = Cookie(None)):
+async def read_items(ads_id: Optional[str] = Cookie(None)):
return {"ads_id": ads_id}
+from typing import Optional
+
from fastapi import Depends, FastAPI
app = FastAPI()
-async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
+async def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
+from typing import Optional
+
from fastapi import Depends, FastAPI
app = FastAPI()
class CommonQueryParams:
- def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
+ def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
+from typing import Optional
+
from fastapi import Depends, FastAPI
app = FastAPI()
class CommonQueryParams:
- def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
+ def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
+from typing import Optional
+
from fastapi import Depends, FastAPI
app = FastAPI()
class CommonQueryParams:
- def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
+ def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100):
self.q = q
self.skip = skip
self.limit = limit
+from typing import Optional
+
from fastapi import Cookie, Depends, FastAPI
app = FastAPI()
-def query_extractor(q: str = None):
+def query_extractor(q: Optional[str] = None):
return q
def query_or_cookie_extractor(
- q: str = Depends(query_extractor), last_query: str = Cookie(None)
+ q: str = Depends(query_extractor), last_query: Optional[str] = Cookie(None)
):
if not q:
return last_query
+from typing import Optional
+
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
app = FastAPI()
-async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
+async def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
client = TestClient(app)
-async def override_dependency(q: str = None):
+async def override_dependency(q: Optional[str] = None):
return {"q": q, "skip": 5, "limit": 10}
from datetime import datetime
+from typing import Optional
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
class Item(BaseModel):
title: str
timestamp: datetime
- description: str = None
+ description: Optional[str] = None
app = FastAPI()
from datetime import datetime, time, timedelta
+from typing import Optional
from uuid import UUID
from fastapi import Body, FastAPI
@app.put("/items/{item_id}")
async def read_items(
item_id: UUID,
- start_datetime: datetime = Body(None),
- end_datetime: datetime = Body(None),
- repeat_at: time = Body(None),
- process_after: timedelta = Body(None),
+ start_datetime: Optional[datetime] = Body(None),
+ end_datetime: Optional[datetime] = Body(None),
+ repeat_at: Optional[time] = Body(None),
+ process_after: Optional[timedelta] = Body(None),
):
start_process = start_datetime + process_after
duration = end_datetime - start_process
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
username: str
password: str
email: EmailStr
- full_name: str = None
+ full_name: Optional[str] = None
class UserOut(BaseModel):
username: str
email: EmailStr
- full_name: str = None
+ full_name: Optional[str] = None
class UserInDB(BaseModel):
username: str
hashed_password: str
email: EmailStr
- full_name: str = None
+ full_name: Optional[str] = None
def fake_password_hasher(raw_password: str):
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
class UserBase(BaseModel):
username: str
email: EmailStr
- full_name: str = None
+ full_name: Optional[str] = None
class UserIn(UserBase):
+from typing import Optional
+
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
-async def read_items(user_agent: str = Header(None)):
+async def read_items(user_agent: Optional[str] = Header(None)):
return {"User-Agent": user_agent}
+from typing import Optional
+
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
-async def read_items(strange_header: str = Header(None, convert_underscores=False)):
+async def read_items(
+ strange_header: Optional[str] = Header(None, convert_underscores=False)
+):
return {"strange_header": strange_header}
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI, Header
@app.get("/items/")
-async def read_items(x_token: List[str] = Header(None)):
+async def read_items(x_token: Optional[List[str]] = Header(None)):
return {"X-Token values": x_token}
+from typing import Optional
+
from fastapi import APIRouter, FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel, HttpUrl
class Invoice(BaseModel):
id: str
- title: str = None
+ title: Optional[str] = None
customer: str
total: float
@app.post("/invoices/", callbacks=invoices_callback_router.routes)
-def create_invoice(invoice: Invoice, callback_url: HttpUrl = None):
+def create_invoice(invoice: Invoice, callback_url: Optional[HttpUrl] = None):
"""
Create an invoice.
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI, status
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
-from typing import Set
+from typing import Optional, Set
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: Set[str] = []
+from typing import Optional
+
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: int = Path(..., title="The ID of the item to get"),
- q: str = Query(None, alias="item-query"),
+ q: Optional[str] = Query(None, alias="item-query"),
):
results = {"item_id": item_id}
if q:
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: str, q: str = None):
+async def read_item(item_id: str, q: Optional[str] = None):
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_item(item_id: str, q: str = None, short: bool = False):
+async def read_item(item_id: str, q: Optional[str] = None, short: bool = False):
item = {"item_id": item_id}
if q:
item.update({"q": q})
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
- user_id: int, item_id: str, q: str = None, short: bool = False
+ user_id: int, item_id: str, q: Optional[str] = None, short: bool = False
):
item = {"item_id": item_id, "owner_id": user_id}
if q:
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
-async def read_user_item(item_id: str, needy: str, skip: int = 0, limit: int = None):
+async def read_user_item(
+ item_id: str, needy: str, skip: int = 0, limit: Optional[int] = None
+):
item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
return item
+++ /dev/null
-from typing import Optional
-
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/items/{item_id}")
-async def read_user_item(item_id: str, limit: Optional[int] = None):
- item = {"item_id": item_id, "limit": limit}
- return item
+from typing import Optional
+
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
-async def read_items(q: str = None):
+async def read_items(q: Optional[str] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
+from typing import Optional
+
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
-async def read_items(q: str = Query(None, max_length=50)):
+async def read_items(q: Optional[str] = Query(None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
+from typing import Optional
+
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
-async def read_items(q: str = Query(None, min_length=3, max_length=50)):
+async def read_items(q: Optional[str] = Query(None, min_length=3, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
+from typing import Optional
+
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
- q: str = Query(None, min_length=3, max_length=50, regex="^fixedquery$")
+ q: Optional[str] = Query(None, min_length=3, max_length=50, regex="^fixedquery$")
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
+from typing import Optional
+
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
-async def read_items(q: str = Query(None, title="Query string", min_length=3)):
+async def read_items(
+ q: Optional[str] = Query(None, title="Query string", min_length=3)
+):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
+from typing import Optional
+
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
- q: str = Query(
+ q: Optional[str] = Query(
None,
title="Query string",
description="Query string for the items to search in the database that have a good match",
+from typing import Optional
+
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
-async def read_items(q: str = Query(None, alias="item-query")):
+async def read_items(q: Optional[str] = Query(None, alias="item-query")):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
+from typing import Optional
+
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
- q: str = Query(
+ q: Optional[str] = Query(
None,
alias="item-query",
title="Query string",
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI, Query
@app.get("/items/")
-async def read_items(q: List[str] = Query(None)):
+async def read_items(q: Optional[List[str]] = Query(None)):
query_items = {"q": q}
return query_items
@app.get("/items/")
-async def read_items(q: list = Query(None)):
+async def read_items(q: list = Query([])):
query_items = {"q": q}
return query_items
from datetime import datetime
+from typing import Optional
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
class Item(BaseModel):
title: str
timestamp: datetime
- description: str = None
+ description: Optional[str] = None
app = FastAPI()
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
tags: List[str] = []
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
username: str
password: str
email: EmailStr
- full_name: str = None
+ full_name: Optional[str] = None
# Don't do this in production!
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
username: str
password: str
email: EmailStr
- full_name: str = None
+ full_name: Optional[str] = None
class UserOut(BaseModel):
username: str
email: EmailStr
- full_name: str = None
+ full_name: Optional[str] = None
@app.post("/user/", response_model=UserOut)
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
tax: float = 10.5
tags: List[str] = []
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
tax: float = 10.5
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
tax: float = 10.5
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
class Config:
schema_extra = {
+from typing import Optional
+
from fastapi import FastAPI
from pydantic import BaseModel, Field
class Item(BaseModel):
name: str = Field(..., example="Foo")
- description: str = Field(None, example="A very nice Item")
+ description: Optional[str] = Field(None, example="A very nice Item")
price: float = Field(..., example=35.4)
- tax: float = Field(None, example=3.2)
+ tax: Optional[float] = Field(None, example=3.2)
@app.put("/items/{item_id}")
+from typing import Optional
+
from fastapi import Body, FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
price: float
- tax: float = None
+ tax: Optional[float] = None
@app.put("/items/{item_id}")
+from typing import Optional
+
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
class User(BaseModel):
username: str
- email: str = None
- full_name: str = None
- disabled: bool = None
+ email: Optional[str] = None
+ full_name: Optional[str] = None
+ disabled: Optional[bool] = None
class UserInDB(User):
from datetime import datetime, timedelta
+from typing import Optional
import jwt
from fastapi import Depends, FastAPI, HTTPException, status
class TokenData(BaseModel):
- username: str = None
+ username: Optional[str] = None
class User(BaseModel):
username: str
- email: str = None
- full_name: str = None
- disabled: bool = None
+ email: Optional[str] = None
+ full_name: Optional[str] = None
+ disabled: Optional[bool] = None
class UserInDB(User):
return user
-def create_access_token(data: dict, expires_delta: timedelta = None):
+def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
from datetime import datetime, timedelta
-from typing import List
+from typing import List, Optional
import jwt
from fastapi import Depends, FastAPI, HTTPException, Security, status
class TokenData(BaseModel):
- username: str = None
+ username: Optional[str] = None
scopes: List[str] = []
class User(BaseModel):
username: str
- email: str = None
- full_name: str = None
- disabled: bool = None
+ email: Optional[str] = None
+ full_name: Optional[str] = None
+ disabled: Optional[bool] = None
class UserInDB(User):
return user
-def create_access_token(data: dict, expires_delta: timedelta = None):
+def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
-from typing import List
+from typing import List, Optional
from pydantic import BaseModel
class ItemBase(BaseModel):
title: str
- description: str = None
+ description: Optional[str] = None
class ItemCreate(ItemBase):
-from typing import Any, List
+from typing import Any, List, Optional
import peewee
from pydantic import BaseModel
class ItemBase(BaseModel):
title: str
- description: str = None
+ description: Optional[str] = None
class ItemCreate(ItemBase):
+from typing import Optional
+
from fastapi import Cookie, Depends, FastAPI, Query, WebSocket, status
from fastapi.responses import HTMLResponse
async def get_cookie_or_token(
- websocket: WebSocket, session: str = Cookie(None), token: str = Query(None)
+ websocket: WebSocket,
+ session: Optional[str] = Cookie(None),
+ token: Optional[str] = Query(None),
):
if session is None and token is None:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
async def websocket_endpoint(
websocket: WebSocket,
item_id: str,
- q: int = None,
+ q: Optional[int] = None,
cookie_or_token: str = Depends(get_cookie_or_token),
):
await websocket.accept()
import http
+from typing import Optional
from fastapi import FastAPI, Path, Query
@app.get("/path/param/{item_id}")
-def get_path_param_id(item_id: str = Path(None)):
+def get_path_param_id(item_id: Optional[str] = Path(None)):
return item_id
@app.get("/query/int/optional")
-def get_query_type_optional(query: int = None):
+def get_query_type_optional(query: Optional[int] = None):
if query is None:
return "foo bar"
return f"foo bar {query}"
from functools import partial
+from typing import Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
-def main(some_arg, q: str = None):
+def main(some_arg, q: Optional[str] = None):
return {"some_arg": some_arg, "q": q}
+from typing import Optional
+
import pytest
from fastapi import APIRouter, Depends, FastAPI
from fastapi.testclient import TestClient
client = TestClient(app)
-async def overrider_dependency_simple(q: str = None):
+async def overrider_dependency_simple(q: Optional[str] = None):
return {"q": q, "skip": 5, "limit": 10}
+from typing import Optional
+
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
class Item(BaseModel):
name: str
- price: float = None
+ price: Optional[float] = None
@app.api_route("/items/{item_id}", methods=["GET"])
+from typing import Optional
+
import pytest
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
class ModelA(BaseModel):
name: str
- description: str = None
+ description: Optional[str] = None
model_b: ModelB
@validator("name")
+from typing import Optional
+
from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient
@item_router.get("/")
-def get_items(user_id: str = None):
+def get_items(user_id: Optional[str] = None):
if user_id is None:
return [{"item_id": "i1", "user_id": "u1"}, {"item_id": "i2", "user_id": "u2"}]
else:
@item_router.get("/{item_id}")
-def get_item(item_id: str, user_id: str = None):
+def get_item(item_id: str, user_id: Optional[str] = None):
if user_id is None:
return {"item_id": item_id}
else:
-from typing import Dict, List, Tuple
+from typing import Dict, List, Optional, Tuple
import pytest
from fastapi import FastAPI, Query
title: str
@app.get("/items/")
- def read_items(q: dict = Query(None)):
+ def read_items(q: Optional[dict] = Query(None)):
pass # pragma: no cover
from datetime import datetime, timezone
from enum import Enum
from pathlib import PurePath, PurePosixPath, PureWindowsPath
+from typing import Optional
import pytest
from fastapi.encoders import jsonable_encoder
class ModelWithConfig(BaseModel):
- role: RoleEnum = None
+ role: Optional[RoleEnum] = None
class Config:
use_enum_values = True
+from typing import Optional
+
from fastapi import FastAPI
from fastapi.params import Param
from fastapi.testclient import TestClient
@app.get("/items/")
-def read_items(q: str = Param(None)):
+def read_items(q: Optional[str] = Param(None)):
return {"q": q}
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
class Item(BaseModel):
name: str
- price: float = None
+ price: Optional[float] = None
owner_ids: List[int] = None
-from typing import List
+from typing import List, Optional
from fastapi import FastAPI
from fastapi.testclient import TestClient
@dataclass
class Item:
name: str
- price: float = None
+ price: Optional[float] = None
owner_ids: List[int] = None
-from typing import Dict, List
+from typing import Dict, List, Optional
from fastapi import FastAPI
from pydantic import BaseModel, Field
class Item(BaseModel):
name: str = Field(..., alias="aliased_name")
- price: float = None
+ price: Optional[float] = None
owner_ids: List[int] = None
class ModelSubclass(Model):
y: int
z: int = 0
- w: int = None
+ w: Optional[int] = None
class ModelDefaults(BaseModel):
+from typing import Optional
+
from fastapi import APIRouter, FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
class Invoice(BaseModel):
id: str
- title: str = None
+ title: Optional[str] = None
customer: str
total: float
@subrouter.post("/invoices/", callbacks=invoices_callback_router.routes)
-def create_invoice(invoice: Invoice, callback_url: HttpUrl = None):
+def create_invoice(invoice: Invoice, callback_url: Optional[HttpUrl] = None):
"""
Create an invoice.
+++ /dev/null
-from fastapi.testclient import TestClient
-
-from query_params.tutorial007 import app
-
-client = TestClient(app)
-
-openapi_schema = {
- "openapi": "3.0.2",
- "info": {"title": "FastAPI", "version": "0.1.0"},
- "paths": {
- "/items/{item_id}": {
- "get": {
- "responses": {
- "200": {
- "description": "Successful Response",
- "content": {"application/json": {"schema": {}}},
- },
- "422": {
- "description": "Validation Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/HTTPValidationError"
- }
- }
- },
- },
- },
- "summary": "Read User Item",
- "operationId": "read_user_item_items__item_id__get",
- "parameters": [
- {
- "required": True,
- "schema": {"title": "Item Id", "type": "string"},
- "name": "item_id",
- "in": "path",
- },
- {
- "required": False,
- "schema": {"title": "Limit", "type": "integer"},
- "name": "limit",
- "in": "query",
- },
- ],
- }
- }
- },
- "components": {
- "schemas": {
- "ValidationError": {
- "title": "ValidationError",
- "required": ["loc", "msg", "type"],
- "type": "object",
- "properties": {
- "loc": {
- "title": "Location",
- "type": "array",
- "items": {"type": "string"},
- },
- "msg": {"title": "Message", "type": "string"},
- "type": {"title": "Error Type", "type": "string"},
- },
- },
- "HTTPValidationError": {
- "title": "HTTPValidationError",
- "type": "object",
- "properties": {
- "detail": {
- "title": "Detail",
- "type": "array",
- "items": {"$ref": "#/components/schemas/ValidationError"},
- }
- },
- },
- }
- },
-}
-
-
-def test_openapi():
- response = client.get("/openapi.json")
- assert response.status_code == 200, response.text
- assert response.json() == openapi_schema
-
-
-def test_read_item():
- response = client.get("/items/foo")
- assert response.status_code == 200, response.text
- assert response.json() == {"item_id": "foo", "limit": None}
-
-
-def test_read_item_query():
- response = client.get("/items/foo?limit=5")
- assert response.status_code == 200, response.text
- assert response.json() == {"item_id": "foo", "limit": 5}
"parameters": [
{
"required": False,
- "schema": {"title": "Q", "type": "array", "items": {}},
+ "schema": {
+ "title": "Q",
+ "type": "array",
+ "items": {},
+ "default": [],
+ },
"name": "q",
"in": "query",
}
url = "/items/"
response = client.get(url)
assert response.status_code == 200, response.text
- assert response.json() == {"q": None}
+ assert response.json() == {"q": []}
-from typing import List
+from typing import List, Optional
import pytest
from fastapi import FastAPI
class Item(BaseModel):
name: str
- price: float = None
+ price: Optional[float] = None
owner_ids: List[int] = None
-from typing import List
+from typing import List, Optional
import pytest
from fastapi import FastAPI
@dataclass
class Item:
name: str
- price: float = None
+ price: Optional[float] = None
owner_ids: List[int] = None