]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
📝 Use Optional in docs (#1644)
authorSebastián Ramírez <tiangolo@gmail.com>
Sun, 28 Jun 2020 18:13:30 +0000 (20:13 +0200)
committerGitHub <noreply@github.com>
Sun, 28 Jun 2020 18:13:30 +0000 (20:13 +0200)
* Updated .py files with Optional tag (up to body_nested_models)

* Update optionals

* docs_src/ all updates, few I was unsure of

* Updated markdown files with Optional param

* es: Add Optional typing to index.md

* Last of markdown files updated with Optional param

* Update highlight lines

* it: Add Optional typings

* README.md: Update with Optional typings

* Update more highlight increments

* Update highlights

* schema-extra-example.md: Update highlights

* updating highlighting on website to reflect .py changes

* Update highlighting for query-params & response-directly

* Address PR comments

* Get rid of unnecessary comment

* ⏪ Revert Optional in Chinese docs as it probably also requires changes in text

* 🎨 Apply format

* ⏪ Revert modified example

* ♻️ Simplify example in docs

* 📝 Update OpenAPI callback example to use Optional

* ✨ Add Optional types to tests

* 📝 Update docs about query params, default to using Optional

* 🎨 Update code examples line highlighting

* 📝 Update nested models docs to use "type parameters" instead of "subtypes"

* 📝 Add notes about FastAPI usage of None

including:

= None

and

= Query(None)

and clarify relationship with Optional[str]

* 📝 Add note about response_model_by_alias

* ♻️ Simplify query param list example

* 🔥 Remove test for removed example

* ✅ Update test for updated example

Co-authored-by: Christopher Nguyen <chrisngyn99@gmail.com>
Co-authored-by: yk396 <yk396@cornell.edu>
Co-authored-by: Kai Chen <kaichen120@gmail.com>
131 files changed:
README.md
docs/en/docs/advanced/additional-responses.md
docs/en/docs/advanced/additional-status-codes.md
docs/en/docs/advanced/openapi-callbacks.md
docs/en/docs/advanced/response-directly.md
docs/en/docs/advanced/testing-dependencies.md
docs/en/docs/advanced/websockets.md
docs/en/docs/deployment.md
docs/en/docs/index.md
docs/en/docs/tutorial/background-tasks.md
docs/en/docs/tutorial/body-fields.md
docs/en/docs/tutorial/body-multiple-params.md
docs/en/docs/tutorial/body-nested-models.md
docs/en/docs/tutorial/body.md
docs/en/docs/tutorial/cookie-params.md
docs/en/docs/tutorial/dependencies/classes-as-dependencies.md
docs/en/docs/tutorial/dependencies/index.md
docs/en/docs/tutorial/dependencies/sub-dependencies.md
docs/en/docs/tutorial/encoder.md
docs/en/docs/tutorial/extra-data-types.md
docs/en/docs/tutorial/extra-models.md
docs/en/docs/tutorial/handling-errors.md
docs/en/docs/tutorial/header-params.md
docs/en/docs/tutorial/path-params-numeric-validations.md
docs/en/docs/tutorial/query-params-str-validations.md
docs/en/docs/tutorial/query-params.md
docs/en/docs/tutorial/response-model.md
docs/en/docs/tutorial/schema-extra-example.md
docs/en/docs/tutorial/security/oauth2-jwt.md
docs/en/docs/tutorial/security/simple-oauth2.md
docs/es/docs/index.md
docs/it/docs/index.md
docs/pt/docs/index.md
docs/ru/docs/index.md
docs/zh/docs/deployment.md
docs/zh/docs/index.md
docs_src/additional_responses/tutorial002.py
docs_src/additional_responses/tutorial004.py
docs_src/additional_status_codes/tutorial001.py
docs_src/app_testing/main_b.py
docs_src/background_tasks/tutorial002.py
docs_src/body/tutorial001.py
docs_src/body/tutorial002.py
docs_src/body/tutorial003.py
docs_src/body/tutorial004.py
docs_src/body_fields/tutorial001.py
docs_src/body_multiple_params/tutorial001.py
docs_src/body_multiple_params/tutorial002.py
docs_src/body_multiple_params/tutorial003.py
docs_src/body_multiple_params/tutorial004.py
docs_src/body_multiple_params/tutorial005.py
docs_src/body_nested_models/tutorial001.py
docs_src/body_nested_models/tutorial002.py
docs_src/body_nested_models/tutorial003.py
docs_src/body_nested_models/tutorial004.py
docs_src/body_nested_models/tutorial005.py
docs_src/body_nested_models/tutorial006.py
docs_src/body_nested_models/tutorial007.py
docs_src/body_updates/tutorial001.py
docs_src/body_updates/tutorial002.py
docs_src/cookie_params/tutorial001.py
docs_src/dependencies/tutorial001.py
docs_src/dependencies/tutorial002.py
docs_src/dependencies/tutorial003.py
docs_src/dependencies/tutorial004.py
docs_src/dependencies/tutorial005.py
docs_src/dependency_testing/tutorial001.py
docs_src/encoder/tutorial001.py
docs_src/extra_data_types/tutorial001.py
docs_src/extra_models/tutorial001.py
docs_src/extra_models/tutorial002.py
docs_src/header_params/tutorial001.py
docs_src/header_params/tutorial002.py
docs_src/header_params/tutorial003.py
docs_src/openapi_callbacks/tutorial001.py
docs_src/path_operation_advanced_configuration/tutorial004.py
docs_src/path_operation_configuration/tutorial001.py
docs_src/path_operation_configuration/tutorial002.py
docs_src/path_operation_configuration/tutorial003.py
docs_src/path_operation_configuration/tutorial004.py
docs_src/path_operation_configuration/tutorial005.py
docs_src/path_params_numeric_validations/tutorial001.py
docs_src/query_params/tutorial002.py
docs_src/query_params/tutorial003.py
docs_src/query_params/tutorial004.py
docs_src/query_params/tutorial006.py
docs_src/query_params/tutorial007.py [deleted file]
docs_src/query_params_str_validations/tutorial001.py
docs_src/query_params_str_validations/tutorial002.py
docs_src/query_params_str_validations/tutorial003.py
docs_src/query_params_str_validations/tutorial004.py
docs_src/query_params_str_validations/tutorial007.py
docs_src/query_params_str_validations/tutorial008.py
docs_src/query_params_str_validations/tutorial009.py
docs_src/query_params_str_validations/tutorial010.py
docs_src/query_params_str_validations/tutorial011.py
docs_src/query_params_str_validations/tutorial013.py
docs_src/response_directly/tutorial001.py
docs_src/response_model/tutorial001.py
docs_src/response_model/tutorial002.py
docs_src/response_model/tutorial003.py
docs_src/response_model/tutorial004.py
docs_src/response_model/tutorial005.py
docs_src/response_model/tutorial006.py
docs_src/schema_extra_example/tutorial001.py
docs_src/schema_extra_example/tutorial002.py
docs_src/schema_extra_example/tutorial003.py
docs_src/security/tutorial003.py
docs_src/security/tutorial004.py
docs_src/security/tutorial005.py
docs_src/sql_databases/sql_app/schemas.py
docs_src/sql_databases_peewee/sql_app/schemas.py
docs_src/websockets/tutorial002.py
tests/main.py
tests/test_callable_endpoint.py
tests/test_dependency_overrides.py
tests/test_extra_routes.py
tests/test_filter_pydantic_sub_model.py
tests/test_infer_param_optionality.py
tests/test_invalid_sequence_param.py
tests/test_jsonable_encoder.py
tests/test_param_class.py
tests/test_serialize_response.py
tests/test_serialize_response_dataclass.py
tests/test_serialize_response_model.py
tests/test_skip_defaults.py
tests/test_sub_callbacks.py
tests/test_tutorial/test_query_params/test_tutorial007.py [deleted file]
tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
tests/test_validate_response.py
tests/test_validate_response_dataclass.py

index b74421fa9d5aa9b283ece62ee449871df05fd9b6..4c863c71fa61d66e6edfc2840a62e35cac9fff09 100644 (file)
--- a/README.md
+++ b/README.md
@@ -131,6 +131,8 @@ $ pip install uvicorn
 * Create a file `main.py` with:
 
 ```Python
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -142,7 +144,7 @@ def read_root():
 
 
 @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}
 ```
 
@@ -151,7 +153,9 @@ def read_item(item_id: int, q: str = None):
 
 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()
@@ -163,7 +167,7 @@ async def read_root():
 
 
 @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}
 ```
 
@@ -241,7 +245,9 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
 
 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
 
@@ -251,7 +257,7 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     price: float
-    is_offer: bool = None
+    is_offer: Optional[bool] = None
 
 
 @app.get("/")
@@ -260,7 +266,7 @@ def read_root():
 
 
 @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}
 
 
index 4b2abaada310941d7b4076bce7802f89c60e441d..c8d443c3ca57075281e2ba8363bf9243829698be 100644 (file)
@@ -168,7 +168,7 @@ You can use this same `responses` parameter to add different media types for the
 
 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!}
 ```
 
@@ -228,7 +228,7 @@ You can use that technique to re-use some predefined responses in your *path ope
 
 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!}
 ```
 
index b9a32cfa3b661c55b99364bc2eaa47483bfc77c6..eb6031953abd5e48e4bc5c258c9054943dfd8f53 100644 (file)
@@ -14,7 +14,7 @@ But you also want it to accept new items. And when the items didn't exist before
 
 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!}
 ```
 
index 15c0ba2a1d45d49a4b321146536a10cdfd52fbff..4c3d97e385bd1b6cd34cdafe5df94a0c5ca8dd24 100644 (file)
@@ -31,7 +31,7 @@ It will have a *path operation* that will receive an `Invoice` body, and a query
 
 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!}
 ```
 
@@ -92,7 +92,7 @@ Because of that, you need to declare what will be the `default_response_class`,
 
     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!}
 ```
 
@@ -105,7 +105,7 @@ It should look just like a normal FastAPI *path operation*:
 * 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!}
 ```
 
@@ -172,7 +172,7 @@ At this point you have the *callback path operation(s)* needed (the one(s) that
 
 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!}
 ```
 
index f1dca1812b6d56e487130d55cc4aac480a6bd2be..f0ab2831d5a9cf0b15e7895a6f2fdb7588cabbda 100644 (file)
@@ -31,7 +31,7 @@ For example, you cannot put a Pydantic model in a `JSONResponse` without first c
 
 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!}
 ```
 
index f2c283947ff834fbee7cf8916cccdd91a06e6506..0dc20afff9bc0492a77d91b4973b5c46c978ffba 100644 (file)
@@ -28,7 +28,7 @@ To override a dependency for testing, you put as a key the original dependency (
 
 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!}
 ```
 
index 6cacc2e6f39f4ccb6aec68b337491807b8b0d8c6..083c75752a2012356c58f394775635e3c029a041 100644 (file)
@@ -98,7 +98,7 @@ In WebSocket endpoints you can import from `fastapi` and use:
 
 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!}
 ```
 
index 94ab1b90b9b0727e43e707f257c355ca9dbd507d..5e62d1e8d5b8f20d1bedfb62b07b2ece2fc54529 100644 (file)
@@ -161,6 +161,8 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
 * Create a `main.py` file with:
 
 ```Python
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -172,7 +174,7 @@ def read_root():
 
 
 @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}
 ```
 
index b74421fa9d5aa9b283ece62ee449871df05fd9b6..4c863c71fa61d66e6edfc2840a62e35cac9fff09 100644 (file)
@@ -131,6 +131,8 @@ $ pip install uvicorn
 * Create a file `main.py` with:
 
 ```Python
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -142,7 +144,7 @@ def read_root():
 
 
 @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}
 ```
 
@@ -151,7 +153,9 @@ def read_item(item_id: int, q: str = None):
 
 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()
@@ -163,7 +167,7 @@ async def read_root():
 
 
 @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}
 ```
 
@@ -241,7 +245,9 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
 
 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
 
@@ -251,7 +257,7 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     price: float
-    is_offer: bool = None
+    is_offer: Optional[bool] = None
 
 
 @app.get("/")
@@ -260,7 +266,7 @@ def read_root():
 
 
 @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}
 
 
index 3771eff7129a2e268bbaeb78b7f29c9d9138580b..7ee8d8a78ec9956fd23efa6ea04387971e639b2f 100644 (file)
@@ -57,7 +57,7 @@ Using `BackgroundTasks` also works with the dependency injection system, you can
 
 **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!}
 ```
 
index 91e6b1a101a8d6085b3fd9031b2d49da8b064cb2..444b90145044f24dfd48cd800ab8a5ef1493ea55 100644 (file)
@@ -6,7 +6,7 @@ The same way you can declare additional validation and metadata in *path operati
 
 First, you have to import it:
 
-```Python hl_lines="2"
+```Python hl_lines="4"
 {!../../../docs_src/body_fields/tutorial001.py!}
 ```
 
@@ -17,7 +17,7 @@ First, you have to import it:
 
 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!}
 ```
 
index 6d5e6e39deed39e8ad68307e5ba6b6a5dcce4ac9..48883e4cdacfe3fad99c76c57dafd3f1542327d4 100644 (file)
@@ -8,7 +8,7 @@ First, of course, you can mix `Path`, `Query` and request body parameter declara
 
 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!}
 ```
 
@@ -30,7 +30,7 @@ In the previous example, the *path operations* would expect a JSON body with the
 
 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!}
 ```
 
@@ -72,7 +72,7 @@ If you declare it as is, because it is a singular value, **FastAPI** will assume
 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!}
 ```
 
@@ -104,12 +104,12 @@ Of course, you can also declare additional query parameters whenever you need, a
 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!}
 ```
 
@@ -131,7 +131,7 @@ item: Item = Body(..., embed=True)
 
 as in:
 
-```Python hl_lines="15"
+```Python hl_lines="17"
 {!../../../docs_src/body_multiple_params/tutorial005.py!}
 ```
 
index 993389c903c961d612caad67c94172482bb3d44b..987de42a84dbb0ebe81e918013211703b0fd4b8f 100644 (file)
@@ -6,15 +6,15 @@ With **FastAPI**, you can define, validate, document, and use arbitrarily deeply
 
 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`
 
@@ -24,12 +24,12 @@ First, import `List` from standard Python's `typing` module:
 {!../../../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
@@ -39,7 +39,7 @@ my_list: List[str]
 
 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":
 
@@ -71,7 +71,7 @@ Each attribute of a Pydantic model has a type.
 
 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.
 
@@ -174,7 +174,7 @@ You can define arbitrarily deeply nested models:
 ```
 
 !!! 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
 
index b2cde0762cc3b549d73c40da5d85724bf0b69409..baa013809ef12db6ebaf355ac3a544cdb715b617 100644 (file)
@@ -17,7 +17,7 @@ To declare a **request** body, you use <a href="https://pydantic-docs.helpmanual
 
 First, you need to import `BaseModel` from `pydantic`:
 
-```Python hl_lines="2"
+```Python hl_lines="4"
 {!../../../docs_src/body/tutorial001.py!}
 ```
 
@@ -27,7 +27,7 @@ Then you declare your data model as a class that inherits from `BaseModel`.
 
 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!}
 ```
 
@@ -57,7 +57,7 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
 
 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!}
 ```
 
@@ -123,7 +123,7 @@ But you would get the same editor support with <a href="https://www.jetbrains.co
 
 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!}
 ```
 
@@ -133,7 +133,7 @@ You can declare path parameters and body requests at the same time.
 
 **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!}
 ```
 
@@ -143,7 +143,7 @@ You can also declare **body**, **path** and **query** parameters, all at the sam
 
 **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!}
 ```
 
@@ -153,6 +153,11 @@ The function parameters will be recognized as follows:
 * 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}.
index 658c52c4644bca321300ba13e5b8b6fdb489be47..9aa2300c4b29a3bf6bf076bb27565777e66bbfed 100644 (file)
@@ -6,7 +6,7 @@ You can define Cookie parameters the same way you define `Query` and `Path` para
 
 First import `Cookie`:
 
-```Python hl_lines="1"
+```Python hl_lines="3"
 {!../../../docs_src/cookie_params/tutorial001.py!}
 ```
 
@@ -16,7 +16,7 @@ Then declare the cookie parameters using the same structure as with `Path` and `
 
 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!}
 ```
 
index b4d78af84e4b4ebb4e5f1b49af3ee56124af1e88..3ae184d9557b9b6ddfe2c4c995360d668813bbb7 100644 (file)
@@ -6,7 +6,7 @@ Before diving deeper into the **Dependency Injection** system, let's upgrade the
 
 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!}
 ```
 
@@ -71,19 +71,19 @@ That also applies to callables with no parameters at all. The same as it would b
 
 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!}
 ```
 
@@ -103,7 +103,7 @@ Now you can declare your dependency using this class.
 
 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!}
 ```
 
@@ -143,7 +143,7 @@ commons = Depends(CommonQueryParams)
 
 ..as in:
 
-```Python hl_lines="17"
+```Python hl_lines="19"
 {!../../../docs_src/dependencies/tutorial003.py!}
 ```
 
@@ -179,7 +179,7 @@ So, you can declare the dependency as the type of the variable, and use `Depends
 
 So, the same example would look like:
 
-```Python hl_lines="17"
+```Python hl_lines="19"
 {!../../../docs_src/dependencies/tutorial004.py!}
 ```
 
index 5b8d11ea765ae6c81838583ad38604be587e7dd3..1b86e16791846c847f59efaeaad3b2c0b5ec8efe 100644 (file)
@@ -31,7 +31,7 @@ Let's first focus on the dependency.
 
 It is just a function that can take all the same parameters that a *path operation function* can take:
 
-```Python hl_lines="6 7"
+```Python hl_lines="8 9"
 {!../../../docs_src/dependencies/tutorial001.py!}
 ```
 
@@ -55,7 +55,7 @@ And then it just returns a `dict` containing those values.
 
 ### Import `Depends`
 
-```Python hl_lines="1"
+```Python hl_lines="3"
 {!../../../docs_src/dependencies/tutorial001.py!}
 ```
 
@@ -63,7 +63,7 @@ And then it just returns a `dict` containing those values.
 
 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!}
 ```
 
index 71b1404d6f860d954baa8ea82cac860dcb30c050..3ecccebaf71ae117345bdb4fd683cd5db0667bd7 100644 (file)
@@ -10,7 +10,7 @@ They can be as **deep** as you need them to be.
 
 You could create a first dependency ("dependable") like:
 
-```Python hl_lines="6 7"
+```Python hl_lines="8 9"
 {!../../../docs_src/dependencies/tutorial005.py!}
 ```
 
@@ -22,7 +22,7 @@ This is quite simple (not very useful), but will help us focus on how the sub-de
 
 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!}
 ```
 
@@ -37,7 +37,7 @@ Let's focus on the parameters declared:
 
 Then we can use the dependency with:
 
-```Python hl_lines="19"
+```Python hl_lines="21"
 {!../../../docs_src/dependencies/tutorial005.py!}
 ```
 
index 3879f976af6e17ac27d9edbbcc27a522aa801378..d1d59c43ce706ec6bbcbf5b75d047a71a01bb82d 100644 (file)
@@ -20,7 +20,7 @@ You can use `jsonable_encoder` for that.
 
 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!}
 ```
 
index 07c1ed06f792d0b5f068bbcf683a4d26ddd5e871..46ebc4b61b2ca010fbf8a02dda76abc693d2ace6 100644 (file)
@@ -54,12 +54,12 @@ Here are some of the additional data types you can use:
 
 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!}
 ```
index 5b8bf5a2b84ba3f066d5ee0594da41d70c02549d..67d4ec473020a7f2183886f810aa2b2adaabc766 100644 (file)
@@ -17,7 +17,7 @@ This is especially the case for user models, because:
 
 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!}
 ```
 
@@ -150,7 +150,7 @@ All the data conversion, validation, documentation, etc. will still work as norm
 
 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!}
 ```
 
index c5d36702ce50d493eee64b775d30df6fe26745db..c2a130a1276f5fae39f0d1c2cef25b15f378c687 100644 (file)
@@ -209,7 +209,7 @@ Now try sending an invalid item like:
 
 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": [
     {
index 738d2a559ea90331f39ba5ed2310dc37fb880a59..57570153ffd1a151e75381c79c232fb24b0d8f3c 100644 (file)
@@ -6,7 +6,7 @@ You can define Header parameters the same way you define `Query`, `Path` and `Co
 
 First import `Header`:
 
-```Python hl_lines="1"
+```Python hl_lines="3"
 {!../../../docs_src/header_params/tutorial001.py!}
 ```
 
@@ -16,7 +16,7 @@ Then declare the header parameters using the same structure as with `Path`, `Que
 
 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!}
 ```
 
@@ -44,7 +44,7 @@ So, you can use `user_agent` as you normally would in Python code, instead of ne
 
 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!}
 ```
 
index 9ae4c8b1a480b642bf70000262f6c2cc416241ab..1fcd9dbdbc685678304c546c747cfcb101db2f46 100644 (file)
@@ -6,7 +6,7 @@ The same way you can declare more validations and metadata for query parameters
 
 First, import `Path` from `fastapi`:
 
-```Python hl_lines="1"
+```Python hl_lines="3"
 {!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
 ```
 
@@ -16,7 +16,7 @@ You can declare all the same parameters as for `Query`.
 
 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!}
 ```
 
index abde56df4b9862c251ae6022195f9b1fc0d78a61..465ce3f88e0ae8459129a4de763df0a9076b2c19 100644 (file)
@@ -4,11 +4,16 @@
 
 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
 
@@ -18,7 +23,7 @@ We are going to enforce that even though `q` is optional, whenever it is provide
 
 To achieve that, first import `Query` from `fastapi`:
 
-```Python hl_lines="1"
+```Python hl_lines="3"
 {!../../../docs_src/query_params_str_validations/tutorial002.py!}
 ```
 
@@ -26,7 +31,7 @@ To achieve that, first import `Query` from `fastapi`:
 
 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!}
 ```
 
@@ -35,18 +40,35 @@ As we have to replace the default value `None` with `Query(None)`, the first par
 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)
@@ -58,7 +80,7 @@ This will validate the data, show a clear error when the data is not valid, and
 
 You can also add a parameter `min_length`:
 
-```Python hl_lines="7"
+```Python hl_lines="9"
 {!../../../docs_src/query_params_str_validations/tutorial003.py!}
 ```
 
@@ -66,7 +88,7 @@ You can also add a parameter `min_length`:
 
 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!}
 ```
 
@@ -104,13 +126,13 @@ q: str
 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:
@@ -211,13 +233,13 @@ That information will be included in the generated OpenAPI and used by the docum
 
 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!}
 ```
 
@@ -239,7 +261,7 @@ But you still need it to be exactly `item-query`...
 
 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!}
 ```
 
@@ -251,7 +273,7 @@ You have to leave it there a while because there are clients using it, but you w
 
 Then pass the parameter `deprecated=True` to `Query`:
 
-```Python hl_lines="16"
+```Python hl_lines="18"
 {!../../../docs_src/query_params_str_validations/tutorial010.py!}
 ```
 
index 0efc57e1b87e1b8f7a94b9891fd7825b241f70c8..d5dec36def3248985a00beba31334759159cdb4a 100644 (file)
@@ -63,7 +63,7 @@ The parameter values in your function will be:
 
 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!}
 ```
 
@@ -72,11 +72,16 @@ In this case, the function parameter `q` will be optional, and will be `None` by
 !!! 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!}
 ```
 
@@ -121,7 +126,7 @@ And you don't have to declare them in any specific order.
 
 They will be detected by name:
 
-```Python hl_lines="6 8"
+```Python hl_lines="8 10"
 {!../../../docs_src/query_params/tutorial004.py!}
 ```
 
@@ -179,7 +184,7 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
 
 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!}
 ```
 
@@ -191,36 +196,3 @@ In this case, there are 3 query parameters:
 
 !!! 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!}
-```
index dd76eca6ef18ce56b1a443ee87be40b5a211ea05..b7201ee77d723235e5faadcf8c69caa4796b9475 100644 (file)
@@ -35,13 +35,13 @@ But most importantly:
 
 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!}
 ```
 
@@ -58,19 +58,19 @@ But if we use the same model for another *path operation*, we could be sending o
 
 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!}
 ```
 
@@ -94,9 +94,9 @@ Your response model could have default values, like:
 {!../../../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.
 
@@ -183,7 +183,9 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
 
     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!}
 ```
 
@@ -196,7 +198,7 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
 
 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!}
 ```
 
index 8a497ccd54403bf75045cee961259a7a99948220..d0f1b843e57ee05f9b53ebcaa7c9e7af9bcbc765 100644 (file)
@@ -10,7 +10,7 @@ There are several ways you can declare extra JSON Schema information.
 
 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!}
 ```
 
@@ -20,7 +20,7 @@ That extra info will be added as-is to the output JSON Schema.
 
 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!}
 ```
 
@@ -33,7 +33,7 @@ The same way you can pass extra info to `Field`, you can do the same with `Path`
 
 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!}
 ```
 
index 18b4e0e300c1a3e285fbba1dfa96c269cb48d2fd..b1147cb4c53ca2ed826b21878290d47525e1b3a6 100644 (file)
@@ -100,7 +100,7 @@ And another utility to verify if a received password matches the hash stored.
 
 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!}
 ```
 
@@ -135,7 +135,7 @@ Define a Pydantic Model that will be used in the token endpoint for the response
 
 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!}
 ```
 
@@ -147,7 +147,7 @@ Decode the received token, verify it, and return the current user.
 
 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!}
 ```
 
@@ -157,7 +157,7 @@ Create a `timedelta` with the expiration time of the token.
 
 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!}
 ```
 
index c95c6aa6b62c6ddb5492df84c6392ff3b3dec382..2f58a6d109395cf5182ea97f2cf0e66d8d445288 100644 (file)
@@ -49,7 +49,7 @@ Now let's use the utilities provided by **FastAPI** to handle this.
 
 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!}
 ```
 
@@ -90,7 +90,7 @@ If there is no such user, we return an error saying "incorrect username or passw
 
 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!}
 ```
 
@@ -118,7 +118,7 @@ If your database is stolen, the thief won't have your users' plaintext passwords
 
 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!}
 ```
 
@@ -156,7 +156,7 @@ For this simple example, we are going to just be completely insecure and return
 
     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!}
 ```
 
@@ -181,7 +181,7 @@ Both of these dependencies will just return an HTTP error if the user doesn't ex
 
 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!}
 ```
 
index e795f9578a7ac3b59d27ced9ea7bc2cfee8abeb4..c2690b140a85961c7c26e5c521ceb2bdd19d3f87 100644 (file)
@@ -131,6 +131,7 @@ $ pip install uvicorn
 
 ```Python
 from fastapi import FastAPI
+from typing import Optional
 
 app = FastAPI()
 
@@ -141,7 +142,7 @@ def read_root():
 
 
 @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}
 ```
 
@@ -152,6 +153,7 @@ Si tu código usa `async` / `await`, usa `async def`:
 
 ```Python hl_lines="7 12"
 from fastapi import FastAPI
+from typing import Optional
 
 app = FastAPI()
 
@@ -162,7 +164,7 @@ async def read_root():
 
 
 @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}
 ```
 
@@ -243,6 +245,7 @@ Declara el body usando las declaraciones de tipo estándares de Python gracias a
 ```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()
 
@@ -250,7 +253,7 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     price: float
-    is_offer: bool = None
+    is_offer: Optional[bool] = None
 
 
 @app.get("/")
@@ -259,7 +262,7 @@ def read_root():
 
 
 @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}
 
 
index 20dd403ab7c3c9d71e59f25f37b4e9c1e25d7719..88d0c0e3d217d75cce7162d9d1d71fca34d9a00a 100644 (file)
@@ -136,6 +136,7 @@ $ pip install uvicorn
 
 ```Python
 from fastapi import FastAPI
+from typing import Optional
 
 app = FastAPI()
 
@@ -146,7 +147,7 @@ def read_root():
 
 
 @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}
 ```
 
@@ -157,6 +158,7 @@ If your code uses `async` / `await`, use `async def`:
 
 ```Python hl_lines="7 12"
 from fastapi import FastAPI
+from typing import Optional
 
 app = FastAPI()
 
@@ -167,7 +169,7 @@ async def read_root():
 
 
 @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}
 ```
 
@@ -248,6 +250,7 @@ Declare the body using standard Python types, thanks to Pydantic.
 ```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()
 
@@ -255,7 +258,7 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     price: float
-    is_offer: bool = None
+    is_offer: bool = Optional[None]
 
 
 @app.get("/")
@@ -264,7 +267,7 @@ def read_root():
 
 
 @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}
 
 
index 10b2d6855f72fd299f35465acabfb414990227dc..20600eeadb8d9d81412612ad4d073c04de0814f3 100644 (file)
@@ -124,6 +124,8 @@ $ pip install uvicorn
 * Crie um arquivo `main.py` com:
 
 ```Python
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -135,7 +137,7 @@ def read_root():
 
 
 @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}
 ```
 
@@ -144,7 +146,9 @@ def read_item(item_id: int, q: str = None):
 
 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()
@@ -156,7 +160,7 @@ async def read_root():
 
 
 @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}
 ```
 
@@ -234,7 +238,7 @@ Agora modifique o arquivo `main.py` para receber um corpo para uma requisição
 
 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
 
@@ -244,7 +248,7 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     price: float
-    is_offer: bool = None
+    is_offer: Optional[bool] = None
 
 
 @app.get("/")
@@ -253,7 +257,7 @@ def read_root():
 
 
 @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}
 
 
index 20dd403ab7c3c9d71e59f25f37b4e9c1e25d7719..5d5e806e58e84a73b6c6ab6959cfb620f503e9e4 100644 (file)
@@ -135,6 +135,8 @@ $ pip install uvicorn
 * Create a file `main.py` with:
 
 ```Python
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -146,7 +148,7 @@ def read_root():
 
 
 @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}
 ```
 
@@ -155,7 +157,9 @@ def read_item(item_id: int, q: str = None):
 
 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()
@@ -167,7 +171,7 @@ async def read_root():
 
 
 @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}
 ```
 
@@ -245,7 +249,9 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
 
 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
 
@@ -255,7 +261,7 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     price: float
-    is_offer: bool = None
+    is_offer: Optional[bool] = None
 
 
 @app.get("/")
@@ -264,7 +270,7 @@ def read_root():
 
 
 @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}
 
 
index 6eb25824a7c42d5c77139606f57d2c1bccabbd33..8cca1091edd50f2173abf958361a5bde08cd2fda 100644 (file)
@@ -162,6 +162,8 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
 * 创建一个 `main.py` 文件,内容如下:
 
 ```Python
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -173,7 +175,7 @@ def read_root():
 
 
 @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}
 ```
 
index e8427c90bb5508d83daeb22f17484dde5e535378..f3fac28d9d1cf139a9eba83e2c194f85def046c4 100644 (file)
@@ -131,6 +131,8 @@ $ pip install uvicorn
 * 创建一个 `main.py` 文件并写入以下内容:
 
 ```Python
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -142,7 +144,7 @@ def read_root():
 
 
 @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}
 ```
 
@@ -151,7 +153,9 @@ def read_item(item_id: int, q: str = None):
 
 如果你的代码里会出现 `async` / `await`,请使用 `async def`:
 
-```Python hl_lines="7 12"
+```Python hl_lines="9 14"
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -163,7 +167,7 @@ async def read_root():
 
 
 @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}
 ```
 
@@ -241,7 +245,9 @@ INFO:     Application startup complete.
 
 我们借助 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
 
@@ -251,7 +257,7 @@ app = FastAPI()
 class Item(BaseModel):
     name: str
     price: float
-    is_offer: bool = None
+    is_offer: Optional[bool] = None
 
 
 @app.get("/")
@@ -260,7 +266,7 @@ def read_root():
 
 
 @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}
 
 
index 28bdb9b2a4ac2696e7d0358fc5fe7f61ea080535..a46e959596df28ab586a2496ea6161e65f27a826 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from fastapi.responses import FileResponse
 from pydantic import BaseModel
@@ -21,7 +23,7 @@ app = FastAPI()
         }
     },
 )
-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:
index f1b15fee1399a988f30ebcca05cc8ea06e7d4b64..361aecb8e7e847ba69235751abe7f25ec75f0a83 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from fastapi.responses import FileResponse
 from pydantic import BaseModel
@@ -23,7 +25,7 @@ app = FastAPI()
     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:
index c1b88828dd0e736421a7316831d3026090089127..ae101e0a090cdc4e656b26b2ab095009b1bdd513 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Body, FastAPI, status
 from fastapi.responses import JSONResponse
 
@@ -7,7 +9,9 @@ items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "siz
 
 
 @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
index cb9ced094e4770b58cddc088ef6da1403c227298..df43db8060515e358f81cace7fff539051d59a0d 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI, Header, HTTPException
 from pydantic import BaseModel
 
@@ -14,7 +16,7 @@ app = FastAPI()
 class Item(BaseModel):
     id: str
     title: str
-    description: str = None
+    description: Optional[str] = None
 
 
 @app.get("/items/{item_id}", response_model=Item)
index 9fe737012389e245d0cc1d1b3acf4589a98a0a3d..e7517e8cde686d5eb8cfd0914675047e82ffd451 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import BackgroundTasks, Depends, FastAPI
 
 app = FastAPI()
@@ -8,7 +10,7 @@ def write_log(message: str):
         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)
index e99a46ccc8925607eadefa5ae28a3ba295f5e982..52144bd2b0d078f1d9cda36260b53b007ec35bf5 100644 (file)
@@ -1,12 +1,14 @@
+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()
index cce5eca49fb1633b260e012115f6a6a392d969b3..644fabae99dc3112312c80dd69306e6b28bbf7c5 100644 (file)
@@ -1,12 +1,14 @@
+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()
index 1d3e902400d103bf399ac71492f05668ae170bd9..c99ea694b65ab9bb251bbd5e8cf3d0a002cc56bb 100644 (file)
@@ -1,12 +1,14 @@
+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()
index c389af241971da0e6c3aa433b468d9d550a71be7..7a222a390e7ffcfae7f330e0a870b6e484461f70 100644 (file)
@@ -1,19 +1,21 @@
+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})
index dcd5b9764af9c51feffbfe12f9ee773ebb4ff117..dabc48a0f5a64c7a8b27766f52c2904d7762ac39 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Body, FastAPI
 from pydantic import BaseModel, Field
 
@@ -6,9 +8,11 @@ app = FastAPI()
 
 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}")
index fbd368207cfd96f83ea92ee5164d7027ed292534..7ce0ae6f28483ed9b7a037d6a407498958b05bad 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI, Path
 from pydantic import BaseModel
 
@@ -6,17 +8,17 @@ app = FastAPI()
 
 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:
index 54f6d9138b91063e71100e3d75930a49451f45e4..6b874842034102591f78b0298417c7f008f3eedc 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel
 
@@ -6,14 +8,14 @@ app = FastAPI()
 
 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}")
index 691fe848b64d777e6ed6405cc4b6f3fcbeb088f1..7e9e2437481255d83531e76c8a0356c5337e9b84 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Body, FastAPI
 from pydantic import BaseModel
 
@@ -6,14 +8,14 @@ app = FastAPI()
 
 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}")
index 359b33cccb1e81181dd10172cc26b8699b3359b5..8dc0d374dedddebea249813e4301607e6fda1f9d 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Body, FastAPI
 from pydantic import BaseModel
 
@@ -6,14 +8,14 @@ app = FastAPI()
 
 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}")
@@ -23,7 +25,7 @@ async def update_item(
     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:
index 606d3bbbb0dd715d5f5c87b1570edddb1cd61bb3..4657b4144e4c60464d01513f447f981bb91b48bc 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Body, FastAPI
 from pydantic import BaseModel
 
@@ -6,9 +8,9 @@ app = FastAPI()
 
 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}")
index 56db2a09386391f112437c232d7b58fd4e7947d5..fe14fdf93e615a73c0897c10d4533383edbeddbb 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel
 
@@ -6,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: list = []
 
 
index db33e483f4a1d618f2a240dc2ba8b6457f4400da..1770516a45d2e2a1769fb8a9b324a25c9d46baa2 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: List[str] = []
 
 
index f65195b620c01e20ba394fb3dc39be36e4eebef0..33dbbe3a9e696056a878889a3719a02240a7c715 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 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()
 
 
index 6c2ca25eb7536a13d3a3e19654792b6f43aa837e..6037b32b77d375de049ba77dd3b47773e2f95edc 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -13,11 +13,11 @@ class Image(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}")
index d6d9d6479ec5700f4e284f9ea7216f3cedbc1aee..0c076d4f9fa177548b56a6c4d79048b33c65f3ef 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel, HttpUrl
@@ -13,11 +13,11 @@ class Image(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}")
index d64668518e477866f79304b31d0d3a05b1c86fee..1d2b4ce47094d5d3838a5dd886b17b7e79b7585f 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List, Set
+from typing import List, Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel, HttpUrl
@@ -13,11 +13,11 @@ class Image(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] = []
-    images: List[Image] = None
+    images: Optional[List[Image]] = None
 
 
 @app.put("/items/{item_id}")
index f4b699dbfb8c42d046366bae9f7364572d8bbab3..9f321643cebe09d3cc2c5824a0531c537af2d105 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List, Set
+from typing import List, Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel, HttpUrl
@@ -13,16 +13,16 @@ class Image(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] = []
-    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]
 
index bf92493273be3eaa4260a3c8d9b29dc1f46029d0..9b8f3ccf1b718af04e994e3d0ab7a44af67c9721 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI
 from fastapi.encoders import jsonable_encoder
@@ -8,9 +8,9 @@ app = FastAPI()
 
 
 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] = []
 
index 56cb8c4dce663809c681f84e0a3abc5e114e4973..46d27e67e74a6ba3c577f7491538d8fe4022e725 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI
 from fastapi.encoders import jsonable_encoder
@@ -8,9 +8,9 @@ app = FastAPI()
 
 
 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] = []
 
index bee934b0674d16e7238ca880eb70827b45115210..67d03b13366a2ef5628f4152e0a3988700635e6b 100644 (file)
@@ -1,8 +1,10 @@
+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}
index 131a471a1d62122f8793fb34348c71785102ecac..a9da971dc0c50b0c8d116228489bcbfc87fa2b27 100644 (file)
@@ -1,9 +1,11 @@
+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}
 
 
index 9733c60c8bbcbbdb9cae8103520e690827cc4bc5..458f6b5bb2e515a54b71bf8287c13243b8b7dcd3 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Depends, FastAPI
 
 app = FastAPI()
@@ -7,7 +9,7 @@ fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"
 
 
 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
index 3f73619682dea9e10515f9b6753563575c654860..3f3e940f8149b717a67ddadb162aab88f7832698 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Depends, FastAPI
 
 app = FastAPI()
@@ -7,7 +9,7 @@ fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"
 
 
 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
index 6c7ca482109f649f6db88cad15f584cf18fd79ad..daa7b46703cab3673bf5cfff5bd112162404f3b3 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Depends, FastAPI
 
 app = FastAPI()
@@ -7,7 +9,7 @@ fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"
 
 
 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
index 36b312352d93b84680acb4d599a470fc4b137034..c8923d143dcdb2090987c3a196f5fd74396ee714 100644 (file)
@@ -1,14 +1,16 @@
+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
index 67c3874a369eea6e4596c735b1272b7e2023829b..237d3b2310b5787701d1f0edd22d10f34ff25937 100644 (file)
@@ -1,10 +1,12 @@
+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}
 
 
@@ -21,7 +23,7 @@ async def read_users(commons: dict = Depends(common_parameters)):
 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}
 
 
index 11984dd96a2f4e3ba0da4789188432bc4c31fc2c..a918fdd64a987b9109f7b4a26793a3844473a8b3 100644 (file)
@@ -1,4 +1,5 @@
 from datetime import datetime
+from typing import Optional
 
 from fastapi import FastAPI
 from fastapi.encoders import jsonable_encoder
@@ -10,7 +11,7 @@ fake_db = {}
 class Item(BaseModel):
     title: str
     timestamp: datetime
-    description: str = None
+    description: Optional[str] = None
 
 
 app = FastAPI()
index 2b6d2f7b9943277ca8cc109ad6f9126120458da6..e8d7e1ea3247562c491931343a13298e13dd0465 100644 (file)
@@ -1,4 +1,5 @@
 from datetime import datetime, time, timedelta
+from typing import Optional
 from uuid import UUID
 
 from fastapi import Body, FastAPI
@@ -9,10 +10,10 @@ app = 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
index 7ff4bba7ea4fb24094c4c0d782dafcb4d45329d4..e95844f608ee2bfa8e1c2db4ad17bc776d795199 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel, EmailStr
 
@@ -8,20 +10,20 @@ class UserIn(BaseModel):
     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):
index 03069911402534512c1242ae3b3e886929476f97..5bc6e707fa18a419f312dcf21cd5973f6c50e65c 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel, EmailStr
 
@@ -7,7 +9,7 @@ app = FastAPI()
 class UserBase(BaseModel):
     username: str
     email: EmailStr
-    full_name: str = None
+    full_name: Optional[str] = None
 
 
 class UserIn(UserBase):
index e871de68d7f529194f12112fcce362668ccb37c3..7d69b027eec5b606a59cc4493ae6f0d5fe9aca52 100644 (file)
@@ -1,8 +1,10 @@
+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}
index ba6cef1dedc23578b5ff83c2b585b260dfd58eec..2de3dddd70ac6fda000571a9967a9217caf00b88 100644 (file)
@@ -1,8 +1,12 @@
+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}
index 85d0fb3a280ee87b86360df3acc52865be4f4b7d..6d0eefdd2141a2c626bff785b562bd3ecf37eb88 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI, Header
 
@@ -6,5 +6,5 @@ app = FastAPI()
 
 
 @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}
index c9ca4eb96a9ad686c83af83041cca63b585b1d2b..dea7e89b43d59757cf927800e4dd2da724b0d955 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import APIRouter, FastAPI
 from fastapi.responses import JSONResponse
 from pydantic import BaseModel, HttpUrl
@@ -7,7 +9,7 @@ app = FastAPI()
 
 class Invoice(BaseModel):
     id: str
-    title: str = None
+    title: Optional[str] = None
     customer: str
     total: float
 
@@ -32,7 +34,7 @@ def invoice_notification(body: InvoiceEvent):
 
 
 @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.
 
index 24be0cb940868370fe9eac9f27ab8d6000c85b78..fa867e794bf1f5b9de580778bd5a0012692cf462 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: Set[str] = []
 
 
index 77437cd08a9ac2b6863e41c704eb940a3d05bb1f..66ea442ea9c9888d6bd84144a99dd5b4492eda7a 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI, status
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: Set[str] = []
 
 
index ed29ea014ff6dabd826982e2cb62869f3c0b963b..01df041b83a61094e0912bb0dbc8d705d5a053a5 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: Set[str] = []
 
 
index 4c4b048c7c56e7acf9ea86151f263e8c029b62c9..29bcb4a223f669414b2030fe080a5a89ae2f19d5 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: Set[str] = []
 
 
index f9822aae423d5a18a3675594d09ee3cb241431b6..ac95cc4bb943f093172ae0c077ae504f2bdbde73 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: Set[str] = []
 
 
index 7ae2acafc33bb2975d0fe854ae739049965db6cb..c1b809887261a0c022ea86222e8e1a1aa7494bba 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Set
+from typing import Optional, Set
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: Set[str] = []
 
 
index fc1911872ccaf80d45d9ba386ad0b9219ff48285..11777bba77b9934a2903b145342b117dfbe4c6ac 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI, Path, Query
 
 app = FastAPI()
@@ -6,7 +8,7 @@ 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:
index 6e934881768f79401e5471ea771483f3f5df98cf..32918465e50f3779e77f07a2e16b459c2a9faf5f 100644 (file)
@@ -1,10 +1,12 @@
+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}
index bba18c410698eb2f59cd5ae834872b32a85103eb..c81a9678562a4119dd40c117b2563df817f1175e 100644 (file)
@@ -1,10 +1,12 @@
+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})
index 4407baf9aa8fea20c6b86a44f968043718d7e64d..37f97fa2ac93224b5f755b4e72f90081a04f7ea9 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -5,7 +7,7 @@ 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:
index d764c2a863e0809462be935bbc57ab24d2df9b29..ffe32834030116f3cde049adfd603a24e0bd57a8 100644 (file)
@@ -1,9 +1,13 @@
+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
diff --git a/docs_src/query_params/tutorial007.py b/docs_src/query_params/tutorial007.py
deleted file mode 100644 (file)
index 8ef5b30..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-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
index b06c33c3eebfe5aa53bb263df86bd9a2cc5f91d8..5d7bfb0ee5dba76f6394b1a3ac2485803643bb6c 100644 (file)
@@ -1,10 +1,12 @@
+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})
index 183180cd742b03fa1152ab5bf207f85d01051eaf..68ea582061a00740a7c74eb5c4cda3a2ff82147d 100644 (file)
@@ -1,10 +1,12 @@
+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})
index 311ece816a59bc45a89ee3c3e2d9c66ff31c4089..e52acc72f0fea091704abab8676b995564542fd6 100644 (file)
@@ -1,10 +1,12 @@
+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})
index 785db44c0d6307629dead7f1a21116b469837599..d2c30331f63a00e61b3ac95e26103e85e90e5647 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI, Query
 
 app = FastAPI()
@@ -5,7 +7,7 @@ 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:
index 76b9ea811da824f473ac3d77b9f2ec442e900e89..e360feda9f07a1852ef98847541a83fdfcf3e6a0 100644 (file)
@@ -1,10 +1,14 @@
+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})
index 339f80e933fc7734eb159f467a583a29d9240895..238add47104259bfb3aa74a4dc900614a37b980b 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI, Query
 
 app = FastAPI()
@@ -5,7 +7,7 @@ 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",
index 7f5010014432f1d59807acb84c0e088a624599ab..7e5c0b81a8a8421ee4f9af2b2e591442ea080a60 100644 (file)
@@ -1,10 +1,12 @@
+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})
index 051656c768b62435b608c58824f622fd0d662b0f..7921506b653d47152199894f722bad4954d84c65 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI, Query
 
 app = FastAPI()
@@ -5,7 +7,7 @@ app = FastAPI()
 
 @app.get("/items/")
 async def read_items(
-    q: str = Query(
+    q: Optional[str] = Query(
         None,
         alias="item-query",
         title="Query string",
index f1c0e5b5b15fd407c172852be2fe2cde9fac0ec7..7fda267edd59db649b1c9aa23df72e3643d365b0 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI, Query
 
@@ -6,6 +6,6 @@ app = FastAPI()
 
 
 @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
index a433b3a16ebab60884e0b6f891946e6f529ebc64..95dd6999dd0f4ca7d71f477b3ad850e06acb51e3 100644 (file)
@@ -4,6 +4,6 @@ app = FastAPI()
 
 
 @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
index 89c5968b143beda2f4c2bed5a5d5e349f9bb49f0..6acdc0fc8d4785d5a36f7d33c8a38ca957b0bee5 100644 (file)
@@ -1,4 +1,5 @@
 from datetime import datetime
+from typing import Optional
 
 from fastapi import FastAPI
 from fastapi.encoders import jsonable_encoder
@@ -9,7 +10,7 @@ from pydantic import BaseModel
 class Item(BaseModel):
     title: str
     timestamp: datetime
-    description: str = None
+    description: Optional[str] = None
 
 
 app = FastAPI()
index 4fe9aeb504a256fff82b970605fd2485004947f3..57992ecfc5142473f89bbc94440275b5ff027025 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,9 +8,9 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
-    tax: float = None
+    tax: Optional[float] = None
     tags: List[str] = []
 
 
index 67084b45e9787bfa97b8d14e3dca1efb30d8845e..373317eb932b5f35a86ea8c0943e04f2decb1dfc 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel, EmailStr
 
@@ -8,7 +10,7 @@ class UserIn(BaseModel):
     username: str
     password: str
     email: EmailStr
-    full_name: str = None
+    full_name: Optional[str] = None
 
 
 # Don't do this in production!
index 8450723c24909047731a5372bc1f6025f8688514..e14026dd8cd2959bb7c0e49b4adf20e02ccf5da0 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel, EmailStr
 
@@ -8,13 +10,13 @@ class UserIn(BaseModel):
     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)
index 7a2373e0cf61f11c42c5c6b37441243796b32fd6..1e18f989dc3d57e3a820037e2448fd5c18fb9583 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI
 from pydantic import BaseModel
@@ -8,7 +8,7 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
     tax: float = 10.5
     tags: List[str] = []
index 65343f0723237fd949d5f92fd4292212b8609b9b..03933d1f71efcdf02c8788b1a32dc76c8599c8a6 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel
 
@@ -6,7 +8,7 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
     tax: float = 10.5
 
index 127c6f7cf6e544b942b7e1bbd014a227c209b1dc..629ab8a3aa3f7dfb4daf6c786c089d650be1dcdb 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel
 
@@ -6,7 +8,7 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     price: float
     tax: float = 10.5
 
index 59a58375035ceb57e9fba7c4f84c02c7936d8256..fab4d7a4454097d2746193dede719afc34169660 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel
 
@@ -6,9 +8,9 @@ app = FastAPI()
 
 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 = {
index 0a567bd79e43da5e7c4194261cd41ad2d3d8330d..df3df8854719ade24d04229ee7148eb8873de4f9 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from pydantic import BaseModel, Field
 
@@ -6,9 +8,9 @@ app = FastAPI()
 
 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}")
index 87fbefbb6f53f5892d37ef00af89eb4daefafbd7..58c79f55439f2dba843ce08b5781067759fc7e87 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Body, FastAPI
 from pydantic import BaseModel
 
@@ -6,9 +8,9 @@ app = FastAPI()
 
 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}")
index 5dabb393f193d9409815d79c170fae5f60dfc7cf..0fd15ae3c76b7751df93ecd8c9e8f6ea6159be79 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Depends, FastAPI, HTTPException, status
 from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
 from pydantic import BaseModel
@@ -31,9 +33,9 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token")
 
 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):
index 56f0eb0ea45dfea107ea9e1dbf7bf678df8fe8b2..f3cb6a905b554923fb3c061863f0186a3b899ce7 100644 (file)
@@ -1,4 +1,5 @@
 from datetime import datetime, timedelta
+from typing import Optional
 
 import jwt
 from fastapi import Depends, FastAPI, HTTPException, status
@@ -31,14 +32,14 @@ class Token(BaseModel):
 
 
 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):
@@ -75,7 +76,7 @@ def authenticate_user(fake_db, username: str, password: str):
     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
index 489404d6f302a2f071ee61764e4a484ce951380a..05c29deb19699daddbc8ab7a313eb922f26e1cb8 100644 (file)
@@ -1,5 +1,5 @@
 from datetime import datetime, timedelta
-from typing import List
+from typing import List, Optional
 
 import jwt
 from fastapi import Depends, FastAPI, HTTPException, Security, status
@@ -43,15 +43,15 @@ class Token(BaseModel):
 
 
 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):
@@ -91,7 +91,7 @@ def authenticate_user(fake_db, username: str, password: str):
     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
index 5f964f0a6fc4c32161c84d1013e11ed0885ca29f..51655663a0bfa6d91307a84df0c491ab9e958a5d 100644 (file)
@@ -1,11 +1,11 @@
-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):
index 0bb9215a83d46217d85d5b6731f19a675db38a67..b715604eec698118678328641ce1fd90fcbdba67 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Any, List
+from typing import Any, List, Optional
 
 import peewee
 from pydantic import BaseModel
@@ -15,7 +15,7 @@ class PeeweeGetterDict(GetterDict):
 
 class ItemBase(BaseModel):
     title: str
-    description: str = None
+    description: Optional[str] = None
 
 
 class ItemCreate(ItemBase):
index 5be199cd668f46d0406908bb5ee437271da31579..53cdb41ff1b54e910b539246401f4b0fa75d396f 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import Cookie, Depends, FastAPI, Query, WebSocket, status
 from fastapi.responses import HTMLResponse
 
@@ -54,7 +56,9 @@ async def get():
 
 
 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)
@@ -65,7 +69,7 @@ async def get_cookie_or_token(
 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()
index f32856cb6c3a27dafc3780a5f3c853ff28d248c7..35b7870560af43ab5a4432120faadb9aae5d2d88 100644 (file)
@@ -1,4 +1,5 @@
 import http
+from typing import Optional
 
 from fastapi import FastAPI, Path, Query
 
@@ -48,7 +49,7 @@ def get_bool_id(item_id: bool):
 
 
 @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
 
 
@@ -160,7 +161,7 @@ def get_query_type(query: int):
 
 
 @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}"
index 8aaf4488498e19a15b15fa9b18b5357d4bd0d2f5..1882e9053a21344dc26539560807bae0b3c08d97 100644 (file)
@@ -1,10 +1,11 @@
 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}
 
 
index 3cee6f8ad815ac9576087931957766976f665ac3..8bb307971bd559932ad55075d5bb3e826f2e2254 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 import pytest
 from fastapi import APIRouter, Depends, FastAPI
 from fastapi.testclient import TestClient
@@ -36,7 +38,7 @@ app.include_router(router)
 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}
 
 
index a2459b3588d273cf1190c241e8844c57886a3e54..6aba3e8dda535ea297bf490079ae2794e6f3b667 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from fastapi.responses import JSONResponse
 from fastapi.testclient import TestClient
@@ -8,7 +10,7 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    price: float = None
+    price: Optional[float] = None
 
 
 @app.api_route("/items/{item_id}", methods=["GET"])
index 9ce753d1e2179a5cbaca206522d060922c2ee7a2..90a372976313e0f32170c1dc8dac1967ac438d0a 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 import pytest
 from fastapi import Depends, FastAPI
 from fastapi.testclient import TestClient
@@ -16,7 +18,7 @@ class ModelC(ModelB):
 
 class ModelA(BaseModel):
     name: str
-    description: str = None
+    description: Optional[str] = None
     model_b: ModelB
 
     @validator("name")
index 166c3fcc780b72e44fc21b8a01256f3fe46b9d61..5e673d9c4d796cf9fb6266eef04f409351ac873b 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import APIRouter, FastAPI
 from fastapi.testclient import TestClient
 
@@ -19,7 +21,7 @@ def get_user(user_id: str):
 
 
 @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:
@@ -27,7 +29,7 @@ def get_items(user_id: str = None):
 
 
 @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:
index 069337f79b860d93c3c3c5b48d6bbfb39594ed1d..f00dd7b9343c198db7c312ea1c8bc43421adba49 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Dict, List, Tuple
+from typing import Dict, List, Optional, Tuple
 
 import pytest
 from fastapi import FastAPI, Query
@@ -49,5 +49,5 @@ def test_invalid_simple_dict():
             title: str
 
         @app.get("/items/")
-        def read_items(q: dict = Query(None)):
+        def read_items(q: Optional[dict] = Query(None)):
             pass  # pragma: no cover
index d4ae3444211d8c3f7c4f2c08c813f0f128c37859..2514edfde9b26f506682a588c83e14b6e60456de 100644 (file)
@@ -1,6 +1,7 @@
 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
@@ -60,7 +61,7 @@ class RoleEnum(Enum):
 
 
 class ModelWithConfig(BaseModel):
-    role: RoleEnum = None
+    role: Optional[RoleEnum] = None
 
     class Config:
         use_enum_values = True
index bbb9eefcc3d7dac1cf0fd0327298e262bffb138f..c2a9096d47bff0ce27baa5a940a16ac222b5b997 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import FastAPI
 from fastapi.params import Param
 from fastapi.testclient import TestClient
@@ -6,7 +8,7 @@ app = FastAPI()
 
 
 @app.get("/items/")
-def read_items(q: str = Param(None)):
+def read_items(q: Optional[str] = Param(None)):
     return {"q": q}
 
 
index 1ec957177d60aded612285e527ec3d86cf3119b5..31c08f50df79f6176badb6056adb86d4083db335 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI
 from fastapi.testclient import TestClient
@@ -9,7 +9,7 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    price: float = None
+    price: Optional[float] = None
     owner_ids: List[int] = None
 
 
index 4bbb0c2c15e7e25595ddc0f1afc451ad16fd1c77..ea048127a80a705a8c8d87b515fd5a8d241c8a83 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 from fastapi import FastAPI
 from fastapi.testclient import TestClient
@@ -10,7 +10,7 @@ app = FastAPI()
 @dataclass
 class Item:
     name: str
-    price: float = None
+    price: Optional[float] = None
     owner_ids: List[int] = None
 
 
index adb7fda344f6a377090d23a2ca1cc19ca9f9ddde..056e9c4b04f3c0e088c1ad4316b5658f8595325e 100644 (file)
@@ -1,4 +1,4 @@
-from typing import Dict, List
+from typing import Dict, List, Optional
 
 from fastapi import FastAPI
 from pydantic import BaseModel, Field
@@ -9,7 +9,7 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str = Field(..., alias="aliased_name")
-    price: float = None
+    price: Optional[float] = None
     owner_ids: List[int] = None
 
 
index ed84df66c40b2fa0d8118155fe102af0a7f98fc1..e41d1a286ce3df16cddd385defcaff386c569ab9 100644 (file)
@@ -19,7 +19,7 @@ class Model(BaseModel):
 class ModelSubclass(Model):
     y: int
     z: int = 0
-    w: int = None
+    w: Optional[int] = None
 
 
 class ModelDefaults(BaseModel):
index 3de3cea9939d654f219d516f074579db58381701..dc0e3424a93ac1db9c2ccaf7d0d4e39582278ad9 100644 (file)
@@ -1,3 +1,5 @@
+from typing import Optional
+
 from fastapi import APIRouter, FastAPI
 from fastapi.responses import JSONResponse
 from fastapi.testclient import TestClient
@@ -8,7 +10,7 @@ app = FastAPI()
 
 class Invoice(BaseModel):
     id: str
-    title: str = None
+    title: Optional[str] = None
     customer: str
     total: float
 
@@ -36,7 +38,7 @@ subrouter = APIRouter()
 
 
 @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.
 
diff --git a/tests/test_tutorial/test_query_params/test_tutorial007.py b/tests/test_tutorial/test_query_params/test_tutorial007.py
deleted file mode 100644 (file)
index 335c103..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-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}
index 7b1eab2b7def2bd0d599a73fa203f9e560abea4f..f2293105c9ba566707b51faa2c14a314e4312e3d 100644 (file)
@@ -31,7 +31,12 @@ openapi_schema = {
                 "parameters": [
                     {
                         "required": False,
-                        "schema": {"title": "Q", "type": "array", "items": {}},
+                        "schema": {
+                            "title": "Q",
+                            "type": "array",
+                            "items": {},
+                            "default": [],
+                        },
                         "name": "q",
                         "in": "query",
                     }
@@ -88,4 +93,4 @@ def test_query_no_values():
     url = "/items/"
     response = client.get(url)
     assert response.status_code == 200, response.text
-    assert response.json() == {"q": None}
+    assert response.json() == {"q": []}
index 25499e8f9381f1f6a980a5977f1ed6a2adb995d2..e9a17e542f2b6b5f0f9af587da5b094c58919015 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 import pytest
 from fastapi import FastAPI
@@ -10,7 +10,7 @@ app = FastAPI()
 
 class Item(BaseModel):
     name: str
-    price: float = None
+    price: Optional[float] = None
     owner_ids: List[int] = None
 
 
index 9d78f65ec21f96c9b1f8d0cf387fbcc892e6b8a0..1765dcb4347040f02929ac9f2c6e20934816869e 100644 (file)
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
 
 import pytest
 from fastapi import FastAPI
@@ -12,7 +12,7 @@ app = FastAPI()
 @dataclass
 class Item:
     name: str
-    price: float = None
+    price: Optional[float] = None
     owner_ids: List[int] = None