]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:memo: Refactor docs, "Tutorial - User Guide" and "Advanced User Guide" (#887)
authorSebastián Ramírez <tiangolo@gmail.com>
Sat, 18 Jan 2020 15:21:54 +0000 (16:21 +0100)
committerGitHub <noreply@github.com>
Sat, 18 Jan 2020 15:21:54 +0000 (16:21 +0100)
78 files changed:
README.md
docs/advanced/additional-responses.md [moved from docs/tutorial/additional-responses.md with 100% similarity]
docs/advanced/additional-status-codes.md [moved from docs/tutorial/additional-status-codes.md with 90% similarity]
docs/advanced/advanced-dependencies.md [moved from docs/tutorial/dependencies/advanced-dependencies.md with 92% similarity]
docs/advanced/async-sql-databases.md [moved from docs/tutorial/async-sql-databases.md with 94% similarity]
docs/advanced/custom-request-and-route.md [moved from docs/tutorial/custom-request-and-route.md with 94% similarity]
docs/advanced/custom-response.md [moved from docs/tutorial/custom-response.md with 81% similarity]
docs/advanced/events.md [moved from docs/tutorial/events.md with 100% similarity]
docs/advanced/extending-openapi.md [moved from docs/tutorial/extending-openapi.md with 97% similarity]
docs/advanced/graphql.md [moved from docs/tutorial/graphql.md with 93% similarity]
docs/advanced/index.md [new file with mode: 0644]
docs/advanced/nosql-databases.md [moved from docs/tutorial/nosql-databases.md with 92% similarity]
docs/advanced/openapi-callbacks.md [moved from docs/tutorial/openapi-callbacks.md with 97% similarity]
docs/advanced/path-operation-advanced-configuration.md [moved from docs/tutorial/path-operation-advanced-configuration.md with 83% similarity]
docs/advanced/response-change-status-code.md [moved from docs/tutorial/response-change-status-code.md with 89% similarity]
docs/advanced/response-cookies.md [moved from docs/tutorial/response-cookies.md with 86% similarity]
docs/advanced/response-directly.md [moved from docs/tutorial/response-directly.md with 85% similarity]
docs/advanced/response-headers.md [moved from docs/tutorial/response-headers.md with 66% similarity]
docs/advanced/security/http-basic-auth.md [moved from docs/tutorial/security/http-basic-auth.md with 100% similarity]
docs/advanced/security/index.md [new file with mode: 0644]
docs/advanced/security/oauth2-scopes.md [moved from docs/tutorial/security/oauth2-scopes.md with 90% similarity]
docs/advanced/sql-databases-peewee.md [moved from docs/tutorial/sql-databases-peewee.md with 95% similarity]
docs/advanced/sub-applications-proxy.md [moved from docs/tutorial/sub-applications-proxy.md with 97% similarity]
docs/advanced/templates.md [moved from docs/tutorial/templates.md with 100% similarity]
docs/advanced/testing-dependencies.md [moved from docs/tutorial/testing-dependencies.md with 100% similarity]
docs/advanced/testing-events.md [new file with mode: 0644]
docs/advanced/testing-websockets.md [new file with mode: 0644]
docs/advanced/using-request-directly.md [moved from docs/tutorial/using-request-directly.md with 100% similarity]
docs/advanced/websockets.md [moved from docs/tutorial/websockets.md with 100% similarity]
docs/alternatives.md
docs/async.md
docs/contributing.md
docs/css/custom.css
docs/deployment.md
docs/features.md
docs/history-design-future.md
docs/index.md
docs/project-generation.md
docs/python-types.md
docs/tutorial/background-tasks.md
docs/tutorial/bigger-applications.md
docs/tutorial/body-fields.md
docs/tutorial/body-multiple-params.md
docs/tutorial/body-nested-models.md
docs/tutorial/body-updates.md
docs/tutorial/body.md
docs/tutorial/cookie-params.md
docs/tutorial/dependencies/classes-as-dependencies.md
docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md
docs/tutorial/dependencies/dependencies-with-yield.md
docs/tutorial/dependencies/index.md [moved from docs/tutorial/dependencies/first-steps.md with 77% similarity]
docs/tutorial/dependencies/sub-dependencies.md
docs/tutorial/extra-data-types.md
docs/tutorial/extra-models.md
docs/tutorial/first-steps.md
docs/tutorial/handling-errors.md
docs/tutorial/header-params.md
docs/tutorial/index.md [moved from docs/tutorial/intro.md with 68% similarity]
docs/tutorial/middleware.md
docs/tutorial/path-operation-configuration.md
docs/tutorial/path-params-numeric-validations.md
docs/tutorial/path-params.md
docs/tutorial/query-params-str-validations.md
docs/tutorial/query-params.md
docs/tutorial/request-files.md
docs/tutorial/request-forms-and-files.md
docs/tutorial/request-forms.md
docs/tutorial/response-model.md
docs/tutorial/response-status-code.md
docs/tutorial/security/first-steps.md
docs/tutorial/security/get-current-user.md
docs/tutorial/security/index.md [moved from docs/tutorial/security/intro.md with 100% similarity]
docs/tutorial/security/oauth2-jwt.md
docs/tutorial/security/simple-oauth2.md
docs/tutorial/sql-databases.md
docs/tutorial/static-files.md
docs/tutorial/testing.md
mkdocs.yml

index 80b9a193820bf18970593a902eef7d50a72dacae..69bd6a3385561d6d2c3ead0d3792b2b2cfe58bb9 100644 (file)
--- a/README.md
+++ b/README.md
@@ -92,7 +92,7 @@ FastAPI stands on the shoulders of giants:
 pip install fastapi
 ```
 
-You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" target="_blank">Hypercorn</a>.
+You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
 
 ```bash
 pip install uvicorn
@@ -354,7 +354,7 @@ Try changing the line with:
 
 ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
 
-For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/intro/">Tutorial - User Guide</a>.
+For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
 
 **Spoiler alert**: the tutorial - user guide includes:
 
@@ -375,7 +375,7 @@ For a more complete example including more features, see the <a href="https://fa
 
 Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
 
-To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" target="_blank">Benchmarks</a>.
+To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
 
 ## Optional Dependencies
 
similarity index 90%
rename from docs/tutorial/additional-status-codes.md
rename to docs/advanced/additional-status-codes.md
index 88b633a007ec19ba380d0b5a383cfaac65f7e248..f93dbfca3bfd932f0d8209e6ee4c2c24a65c1d07 100644 (file)
@@ -27,4 +27,4 @@ To achieve that, import `JSONResponse`, and return your content there directly,
 
 If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know before hand what you are going to return.
 
-But you can document that in your code, using: <a href="https://fastapi.tiangolo.com/tutorial/additional-responses/" target="_blank">Additional Responses</a>.
\ No newline at end of file
+But you can document that in your code, using: [Additional Responses](additional-responses.md){.internal-link target=_blank}.
similarity index 92%
rename from docs/tutorial/dependencies/advanced-dependencies.md
rename to docs/advanced/advanced-dependencies.md
index 5a664db33c207b11184997af3968a9c62ba4fab0..a7b9cb4f7791e5833598a03098ca41c17b26a4cc 100644 (file)
@@ -57,7 +57,7 @@ And when solving the dependency, **FastAPI** will call this `checker` like:
 checker(q="somequery")
 ```
 
-...and pass whatever that returns as the value of the dependency in our path operation function as the parameter `fixed_content_included`:
+...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`:
 
 ```Python hl_lines="20"
 {!./src/dependencies/tutorial011.py!}
@@ -68,6 +68,6 @@ checker(q="somequery")
 
     These examples are intentionally simple, but show how it all works.
 
-    In the chapters about security, you will be using utility functions that are implemented in this same way.
+    In the chapters about security, there are utility functions that are implemented in this same way.
 
     If you understood all this, you already know how those utility tools for security work underneath.
similarity index 94%
rename from docs/tutorial/async-sql-databases.md
rename to docs/advanced/async-sql-databases.md
index e8cd3724f016150ead8990739eb083e3598c0365..c7d0b86dff3ede2fa52a3adf355961116c61fbd7 100644 (file)
@@ -11,7 +11,7 @@ In this example, we'll use **SQLite**, because it uses a single file and Python
 Later, for your production application, you might want to use a database server like **PostgreSQL**.
 
 !!! tip
-    You could adopt ideas from the previous section about <a href="/tutorial/sql-databases/" target="_blank">SQLAlchemy ORM</a>, like using utility functions to perform operations in the database, independent of your **FastAPI** code.
+    You could adopt ideas from the section about SQLAlchemy ORM ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}), like using utility functions to perform operations in the database, independent of your **FastAPI** code.
 
     This section doesn't apply those ideas, to be equivalent to the counterpart in <a href="https://www.starlette.io/database/" class="external-link" target="_blank">Starlette</a>.
 
similarity index 94%
rename from docs/tutorial/custom-request-and-route.md
rename to docs/advanced/custom-request-and-route.md
index 9385b0249d0af7f4e50581b36e1c2776085237d4..9f2b604fb658a2784e85682a15559cc1c8ac6596 100644 (file)
@@ -71,7 +71,7 @@ But because of our changes in `GzipRequest.body`, the request body will be autom
 ## Accessing the request body in an exception handler
 
 !!! tip
-    To solve this same problem, it's probably a lot easier to [use the `body` in a custom handler for `RequestValidationError`](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-the-requestvalidationerror-body).
+    To solve this same problem, it's probably a lot easier to use the `body` in a custom handler for `RequestValidationError` ([Handling Errors](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}).
 
     But this example is still valid and it shows how to interact with the internal components.
 
similarity index 81%
rename from docs/tutorial/custom-response.md
rename to docs/advanced/custom-response.md
index 2ab2b512cbcd9597de0dd450a04acb15ef3598d5..a6413374475aa6242fe916e2ad44570ee9e45bef 100644 (file)
@@ -5,7 +5,7 @@
 
 By default, **FastAPI** will return the responses using Starlette's `JSONResponse`.
 
-You can override it by returning a `Response` directly, <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">as seen in a previous section</a>.
+You can override it by returning a `Response` directly as seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}.
 
 But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type`).
 
@@ -43,7 +43,7 @@ Import the `Response` class (sub-class) you want to use and declare it in the *p
 To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
 
 * Import `HTMLResponse`.
-* Pass `HTMLResponse` as the parameter `content_type` of your path operation.
+* Pass `HTMLResponse` as the parameter `content_type` of your *path operation*.
 
 ```Python hl_lines="2 7"
 {!./src/custom_response/tutorial002.py!}
@@ -61,7 +61,7 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
 
 ### Return a Starlette `Response`
 
-As seen in <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">another section</a>, you can also override the response directly in your path operation, by returning it.
+As seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}, you can also override the response directly in your *path operation*, by returning it.
 
 The same example from above, returning an `HTMLResponse`, could look like:
 
@@ -70,7 +70,7 @@ The same example from above, returning an `HTMLResponse`, could look like:
 ```
 
 !!! warning
-    A `Response` returned directly by your path operation function won't be documented in OpenAPI (for example, the `Content-Type` won't be documented) and won't be visible in the automatic interactive docs.
+    A `Response` returned directly by your *path operation function* won't be documented in OpenAPI (for example, the `Content-Type` won't be documented) and won't be visible in the automatic interactive docs.
 
 !!! info
     Of course, the actual `Content-Type` header, status code, etc, will come from the `Response` object your returned.
@@ -79,7 +79,7 @@ The same example from above, returning an `HTMLResponse`, could look like:
 
 If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `response_class` parameter AND return a `Response` object.
 
-The `response_class` will then be used only to document the OpenAPI path operation, but your `Response` will be used as is.
+The `response_class` will then be used only to document the OpenAPI *path operation*, but your `Response` will be used as is.
 
 #### Return an `HTMLResponse` directly
 
@@ -99,4 +99,4 @@ But as you passed the `HTMLResponse` in the `response_class`, **FastAPI** will k
 
 ## Additional documentation
 
-You can also declare the media type and many other details in OpenAPI using `responses`: <a href="https://fastapi.tiangolo.com/tutorial/additional-responses/" target="_blank">Additional Responses in OpenAPI</a>.
+You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
similarity index 97%
rename from docs/tutorial/extending-openapi.md
rename to docs/advanced/extending-openapi.md
index c074ff712bdad3d2f470ac841371ae50114eacba..fa1998ce4d6a7c16b45bb5ab9afcd3de24aab9d5 100644 (file)
@@ -162,7 +162,7 @@ pip install aiofiles
 ### Serve the static files
 
 * Import `StaticFiles` from Starlette.
-* "Mount" it the same way you would <a href="https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/" target="_blank">mount a Sub-Application</a>.
+* "Mount" a `StaticFiles()` instance in a specific path.
 
 ```Python hl_lines="7 11"
 {!./src/extending_openapi/tutorial002.py!}
@@ -229,7 +229,7 @@ And similarly for ReDoc...
 
 ### Create a *path operation* to test it
 
-Now, to be able to test that everything works, create a path operation:
+Now, to be able to test that everything works, create a *path operation*:
 
 ```Python hl_lines="39 40 41"
 {!./src/extending_openapi/tutorial002.py!}
similarity index 93%
rename from docs/tutorial/graphql.md
rename to docs/advanced/graphql.md
index 9746bda064999e3119d892582561f759cae2d6e8..faeabf2d310b0a1f8a1baedb33ad26669c31b308 100644 (file)
@@ -1,7 +1,7 @@
 
 **FastAPI** has optional support for GraphQL (provided by Starlette directly), using the `graphene` library.
 
-You can combine normal FastAPI path operations with GraphQL on the same application.
+You can combine normal FastAPI *path operations* with GraphQL on the same application.
 
 ## Import and use `graphene`
 
diff --git a/docs/advanced/index.md b/docs/advanced/index.md
new file mode 100644 (file)
index 0000000..4e9b65c
--- /dev/null
@@ -0,0 +1,16 @@
+## Additional Features
+
+The main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank} should be enough to give you a tour through all the main features of **FastAPI**.
+
+In the next sections you will see other options, configurations, and additional features.
+
+!!! tip
+    The next sections are **not necessarily "advanced"**.
+
+    And it's possible that for your use case, the solution is in one of them.
+
+## Read the Tutorial first
+
+You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/){.internal-link target=_blank}.
+
+And the next sections assume you already read it, and assume that you know those main ideas.
similarity index 92%
rename from docs/tutorial/nosql-databases.md
rename to docs/advanced/nosql-databases.md
index 0c695d0422ce42d318029bb03423c3e8a36e4535..a01921cb7cb27f487339347c8d81daaa4846412a 100644 (file)
@@ -68,7 +68,7 @@ First, let's create a `User` model:
 {!./src/nosql_databases/tutorial001.py!}
 ```
 
-We will use this model in our path operation function, so, we don't include in it the `hashed_password`.
+We will use this model in our *path operation function*, so, we don't include in it the `hashed_password`.
 
 ### `UserInDB` model
 
@@ -85,7 +85,7 @@ We don't create it as a subclass of Pydantic's `BaseModel` but as a subclass of
 !!! note
     Notice that we have a `hashed_password` and a `type` field that will be stored in the database.
 
-    But it is not part of the general `User` model (the one we will return in the path operation).
+    But it is not part of the general `User` model (the one we will return in the *path operation*).
 
 ## Get the user
 
@@ -96,7 +96,7 @@ Now create a function that will:
 * Get the document with that ID.
 * Put the contents of the document in a `UserInDB` model.
 
-By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your path operation function, you can more easily re-use it in multiple parts and also add <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
+By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your *path operation function*, you can more easily re-use it in multiple parts and also add <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
 
 ```Python hl_lines="37 38 39 40 41 42 43"
 {!./src/nosql_databases/tutorial001.py!}
@@ -137,7 +137,7 @@ UserInDB(username="johndoe", hashed_password="some_hash")
 {!./src/nosql_databases/tutorial001.py!}
 ```
 
-### Create the path operation function
+### Create the *path operation function*
 
 As our code is calling Couchbase and we are not using the <a href="https://docs.couchbase.com/python-sdk/2.5/async-programming.html#asyncio-python-3-5" class="external-link" target="_blank">experimental Python <code>await</code> support</a>, we should declare our function with normal `def` instead of `async def`.
 
similarity index 97%
rename from docs/tutorial/openapi-callbacks.md
rename to docs/advanced/openapi-callbacks.md
index b7e48c5e3999e899407f68148fb527b7468abe37..8d3b0ac9e87d8d74dc9da3c914684e924676b709 100644 (file)
@@ -62,7 +62,7 @@ This example doesn't implement the callback itself (that could be just a line of
 !!! tip
     The actual callback is just an HTTP request.
 
-    When implementing the callback yourself, you could use something like <a href="https://www.encode.io/httpx/" target="_blank">HTTPX</a> or <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
+    When implementing the callback yourself, you could use something like <a href="https://www.encode.io/httpx/" class="external-link" target="_blank">HTTPX</a> or <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
 
 ## Write the callback documentation code
 
similarity index 83%
rename from docs/tutorial/path-operation-advanced-configuration.md
rename to docs/advanced/path-operation-advanced-configuration.md
index 7e17bcd1b3cc854cc4219b348fcde770f1ba3dd6..eb5cc6a1200752f3bc526d07a15e8d4f58ed7257 100644 (file)
@@ -1,9 +1,9 @@
 ## OpenAPI operationId
 
-!!! danger
+!!! warning
     If you are not an "expert" in OpenAPI, you probably don't need this.
 
-You can set the OpenAPI `operationId` to be used in your path operation with the parameter `operation_id`.
+You can set the OpenAPI `operationId` to be used in your *path operation* with the parameter `operation_id`.
 
 You would have to make sure that it is unique for each operation.
 
@@ -31,7 +31,7 @@ You should do it after adding all your *path operations*.
 
 ## Exclude from OpenAPI
 
-To exclude a path operation from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`;
+To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`;
 
 ```Python hl_lines="6"
 {!./src/path_operation_advanced_configuration/tutorial003.py!}
similarity index 89%
rename from docs/tutorial/response-change-status-code.md
rename to docs/advanced/response-change-status-code.md
index 2c3655cd33e429afce7063434bb1b555c5e07855..ac3692a991451cab26fe3b1f5135698cbb640b7b 100644 (file)
@@ -1,4 +1,4 @@
-You probably read before that you can set a <a href="https://fastapi.tiangolo.com/tutorial/response-status-code/" target="_blank">default Response Status Code</a>.
+You probably read before that you can set a default [Response Status Code](../tutorial/response-status-code.md){.internal-link target=_blank}.
 
 But in some cases you need to return a different status code than the default.
 
similarity index 86%
rename from docs/tutorial/response-cookies.md
rename to docs/advanced/response-cookies.md
index 7d4c15be77a892ef62e0f077dd8f020e17cf1437..a73d54622cc65b991b8ffe590e355a5c7a022e17 100644 (file)
@@ -1,6 +1,6 @@
 ## Use a `Response` parameter
 
-You can declare a parameter of type `Response` in your *path operation function*, the same way you can declare a `Request` parameter.
+You can declare a parameter of type `Response` in your *path operation function*.
 
 And then you can set headers in that *temporal* response object.
 
@@ -20,7 +20,7 @@ You can also declare the `Response` parameter in dependencies, and set cookies (
 
 You can also create cookies when returning a `Response` directly in your code.
 
-To do that, you can create a response as described in <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">Return a Response directly</a>.
+To do that, you can create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank}.
 
 Then set Cookies in it, and then return it:
 
similarity index 85%
rename from docs/tutorial/response-directly.md
rename to docs/advanced/response-directly.md
index 348a6f9781a20fdac5eb304370d26f6b07bd8bdc..b4027105065f7c94e727a4eba2e29ee351be6054 100644 (file)
@@ -1,6 +1,6 @@
 When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc.
 
-By default, **FastAPI** would automatically convert that return value to JSON using the <a href="https://fastapi.tiangolo.com/tutorial/encoder/" target="_blank">`jsonable_encoder`</a>.
+By default, **FastAPI** would automatically convert that return value to JSON using the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
 
 Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a Starlette `JSONResponse` that would be used to send the response to the client.
 
@@ -56,8 +56,6 @@ You could put your XML content in a string, put it in a Starlette Response, and
 
 When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically.
 
-But you can still <a href="https://fastapi.tiangolo.com/tutorial/additional-responses/" target="_blank">document it</a>.
+But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
 
-In the next sections you will see how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc.
-
-You will also see how to use them to set response Headers and Cookies.
+You can see in later sections how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc.
similarity index 66%
rename from docs/tutorial/response-headers.md
rename to docs/advanced/response-headers.md
index 7926e4e2f76ee48a4f8dd5dad5317df9d3639d60..55affc5cda2b6ebf0e76d816be996b81ae1a004d 100644 (file)
@@ -1,6 +1,6 @@
 ## Use a `Response` parameter
 
-You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies), the same way you can declare a `Request` parameter.
+You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies).
 
 And then you can set headers in that *temporal* response object.
 
@@ -20,7 +20,7 @@ You can also declare the `Response` parameter in dependencies, and set headers (
 
 You can also add headers when you return a `Response` directly.
 
-Create a response as described in <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">Return a Response directly</a> and pass the headers as an additional parameter:
+Create a response as described in [Return a Response Directly](response-directly.md){.internal-link target=_blank} and pass the headers as an additional parameter:
 
 ```Python hl_lines="10 11 12"
 {!./src/response_headers/tutorial001.py!}
@@ -30,4 +30,4 @@ Create a response as described in <a href="https://fastapi.tiangolo.com/tutorial
 
 Have in mind that custom proprietary headers can be added <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">using the 'X-' prefix</a>.
 
-But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your <a href="https://fastapi.tiangolo.com/tutorial/cors/" target="_blank">CORS configurations</a>, using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
+But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
diff --git a/docs/advanced/security/index.md b/docs/advanced/security/index.md
new file mode 100644 (file)
index 0000000..560af5a
--- /dev/null
@@ -0,0 +1,14 @@
+## Additional Features
+
+There are some extra features to handle security apart from the ones covered in the [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
+
+!!! tip
+    The next sections are **not necessarily "advanced"**.
+
+    And it's possible that for your use case, the solution is in one of them.
+
+## Read the Tutorial first
+
+The next sections assume you already read the main [Tutorial - User Guide: Security](../../tutorial/security/){.internal-link target=_blank}.
+
+They are all based on the same concepts, but allow some extra functionalities.
similarity index 90%
rename from docs/tutorial/security/oauth2-scopes.md
rename to docs/advanced/security/oauth2-scopes.md
index 456d5373711bd43fb4e6c6bb2366f77c71701657..671e38d7fb953b78370933cd18eaf9ac021e66f7 100644 (file)
@@ -29,13 +29,30 @@ The content of each of these strings can have any format, but should not contain
 
 These scopes represent "permissions".
 
-In OpenAPI (e.g. the API docs), you can define "security schemes", the same as you saw in the previous sections.
+In OpenAPI (e.g. the API docs), you can define "security schemes".
 
 When one of these security schemes uses OAuth2, you can also declare and use scopes.
 
+Each "scope" is just a string (without spaces).
+
+They are normally used to declare specific security permissions, for example:
+
+* `users:read` or `users:write` are common examples.
+* `instagram_basic` is used by Facebook / Instagram.
+* `https://www.googleapis.com/auth/drive` is used by Google.
+
+!!! info
+    In OAuth2 a "scope" is just a string that declares a specific permission required.
+
+    It doesn't matter if it has other characters like `:` or if it is a URL.
+    
+    Those details are implementation specific.
+
+    For OAuth2 they are just strings.
+
 ## Global view
 
-First, let's quickly see the parts that change from the previous section about OAuth2 and JWT. Now using OAuth2 scopes:
+First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
 
 ```Python hl_lines="2 5 9 13 48 66 107 109 110 111 112 113 114 115 116 117 123 124 125 126 130 131 132 133 134 135 136 141 155"
 {!./src/security/tutorial005.py!}
@@ -108,7 +125,7 @@ In this case, it requires the scope `me` (it could require more than one scope).
 
     But by using `Security` instead of `Depends`, **FastAPI** will know that it can declare security scopes, use them internally, and document the API with OpenAPI.
 
-    But when you import `Query`, `Path`, `Depends`, `Security` and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+    But when you import `Query`, `Path`, `Depends`, `Security` and others from `fastapi`, those are actually functions that return special classes.
 
 ## Use `SecurityScopes`
 
@@ -200,7 +217,7 @@ Here's how the hierarchy of dependencies and scopes looks like:
 !!! tip
     The important and "magic" thing here is that `get_current_user` will have a different list of `scopes` to check for each *path operation*.
 
-    All depending on the `scopes` declared in each *path operation* and each dependency in the dependency tree for that specific path operation.
+    All depending on the `scopes` declared in each *path operation* and each dependency in the dependency tree for that specific *path operation*.
 
 ## More details about `SecurityScopes`
 
@@ -210,7 +227,7 @@ It will always have the security scopes declared in the current `Security` depen
 
 Because the `SecurityScopes` will have all the scopes declared by dependants, you can use it to verify that a token has the required scopes in a central dependency function, and then declare different scope requirements in different *path operations*.
 
-They will be checked independently for each path operation.
+They will be checked independently for each *path operation*.
 
 ## Check it
 
@@ -247,4 +264,4 @@ The most secure is the code flow, but is more complex to implement as it require
 
 ## `Security` in decorator `dependencies`
 
-The same way you can define a `list` of <a href="https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/" target="_blank">`Depends` in the decorator's `dependencies` parameter</a>, you could also use `Security` with `scopes` there.
+The same way you can define a `list` of `Depends` in the decorator's `dependencies` parameter (as explained in [Dependencies in path operation decorators](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), you could also use `Security` with `scopes` there.
similarity index 95%
rename from docs/tutorial/sql-databases-peewee.md
rename to docs/advanced/sql-databases-peewee.md
index 63df28672a1a924eb3386f91fb5f265e478d9a43..ce5c62c9a5851fd53d5813f701adde25b0b974e1 100644 (file)
@@ -1,9 +1,9 @@
 !!! warning
-    If you are just starting, the <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQLAlchemy tutorial</a> should be enough.
+    If you are just starting, the tutorial [SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank} that uses SQLAlchemy should be enough.
 
     Feel free to skip this.
 
-If you are starting a project from scratch, you are probably better off with <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQLAlchemy ORM</a>, or any other async ORM.
+If you are starting a project from scratch, you are probably better off with SQLAlchemy ORM ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}), or any other async ORM.
 
 If you already have a code base that uses <a href="http://docs.peewee-orm.com/en/latest/" class="external-link" target="_blank">Peewee ORM</a>, you can check here how to use it with **FastAPI**.
 
@@ -23,11 +23,11 @@ But if you need to change some of the defaults, support more than one predefined
 Nevertheless, it's possible to do it, and here you'll see exactly what code you have to add to be able to use Peewee with FastAPI.
 
 !!! note "Technical Details"
-    You can read more about Peewee's stand about async in Python <a href="http://docs.peewee-orm.com/en/latest/peewee/database.html#async-with-gevent" target="_blank">in the docs</a>, <a href="https://github.com/coleifer/peewee/issues/263#issuecomment-517347032" target="_blank">an issue</a>, <a href="https://github.com/coleifer/peewee/pull/2072#issuecomment-563215132" class="external-link" target="_blank">a PR</a>.
+    You can read more about Peewee's stand about async in Python <a href="http://docs.peewee-orm.com/en/latest/peewee/database.html#async-with-gevent" class="external-link" target="_blank">in the docs</a>, <a href="https://github.com/coleifer/peewee/issues/263#issuecomment-517347032" class="external-link" target="_blank">an issue</a>, <a href="https://github.com/coleifer/peewee/pull/2072#issuecomment-563215132" class="external-link" target="_blank">a PR</a>.
 
 ## The same app
 
-We are going to create the same application as in the <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQLAlchemy tutorial</a>.
+We are going to create the same application as in the SQLAlchemy tutorial ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}).
 
 Most of the code is actually the same.
 
@@ -84,7 +84,7 @@ connect_args={"check_same_thread": False}
 
 !!! info "Technical Details"
 
-    Exactly the same technical details as in the <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/#note" target="_blank">SQLAlchemy tutorial</a> apply.
+    Exactly the same technical details as in [SQL (Relational) Databases](../tutorial/sql-databases.md#note){.internal-link target=_blank} apply.
 
 ### Make Peewee async-compatible `PeeweeConnectionState`
 
@@ -247,7 +247,7 @@ Aso, when returning several objects, like in `get_users`, we directly call `list
 list(models.User.select())
 ```
 
-This is for the same reason that we had to create a custom `PeeweeGetterDict`. But by returning something that is already a `list` instead of the `peewee.ModelSelect` the `response_model` in the path operation with `List[models.User]` (that we'll see later) will work correctly.
+This is for the same reason that we had to create a custom `PeeweeGetterDict`. But by returning something that is already a `list` instead of the `peewee.ModelSelect` the `response_model` in the *path operation* with `List[models.User]` (that we'll see later) will work correctly.
 
 ## Main **FastAPI** app
 
similarity index 97%
rename from docs/tutorial/sub-applications-proxy.md
rename to docs/advanced/sub-applications-proxy.md
index c8d5df4aa2bedf6a457ab29fcebdfc67e555f678..e75a4e9d3aaf813724c869fb10ad222c815342fa 100644 (file)
@@ -41,7 +41,7 @@ You could want to do this if you have several "independent" applications that yo
 
 ### Top-level application
 
-First, create the main, top-level, **FastAPI** application, and its path operations:
+First, create the main, top-level, **FastAPI** application, and its *path operations*:
 
 ```Python hl_lines="3 6 7 8"
 {!./src/sub_applications/tutorial001.py!}
@@ -49,7 +49,7 @@ First, create the main, top-level, **FastAPI** application, and its path operati
 
 ### Sub-application
 
-Then, create your sub-application, and its path operations.
+Then, create your sub-application, and its *path operations*.
 
 This sub-application is just another standard FastAPI application, but this is the one that will be "mounted".
 
diff --git a/docs/advanced/testing-events.md b/docs/advanced/testing-events.md
new file mode 100644 (file)
index 0000000..a52aabe
--- /dev/null
@@ -0,0 +1,7 @@
+## Testing Events, `startup` and `shutdown`
+
+When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement:
+
+```Python hl_lines="9 10 11 12 20 21 22 23 24"
+{!./src/app_testing/tutorial003.py!}
+```
\ No newline at end of file
diff --git a/docs/advanced/testing-websockets.md b/docs/advanced/testing-websockets.md
new file mode 100644 (file)
index 0000000..8e9ecf3
--- /dev/null
@@ -0,0 +1,9 @@
+## Testing WebSockets
+
+You can use the same `TestClient` to test WebSockets.
+
+For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket:
+
+```Python hl_lines="27 28 29 30 31"
+{!./src/app_testing/tutorial002.py!}
+```
index 6303888778fb551a30ca3d324bbd08da167fc52f..f14e8964b4a672e6a085cd939ae25fc4cc3f6055 100644 (file)
@@ -79,7 +79,7 @@ The way you use it is very simple. For example, to do a `GET` request, you would
 response = requests.get("http://example.com/some/url")
 ```
 
-The FastAPI counterpart API path operation could look like:
+The FastAPI counterpart API *path operation* could look like:
 
 ```Python hl_lines="1"
 @app.get("/some/url")
@@ -195,7 +195,7 @@ Using it led to the creation of several Flask full-stack generators. These are t
 * <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
 * <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
 
-And these same full-stack generators were the base of the <a href="/project-generation/" target="_blank">**FastAPI** project generator</a>.
+And these same full-stack generators were the base of the [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}.
 
 !!! info
     Flask-apispec was created by the same Marshmallow developers.
@@ -408,8 +408,8 @@ It is the recommended server for Starlette and **FastAPI**.
 
     You can combine it with Gunicorn, to have an asynchronous multi-process server.
 
-    Check more details in the <a href="/deployment/" target="_blank">Deployment</a> section.
+    Check more details in the [Deployment](deployment.md){.internal-link target=_blank} section.
 
 ## Benchmarks and speed
 
-To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](/benchmarks/).
\ No newline at end of file
+To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](benchmarks.md){.internal-link target=_blank}.
index ff0d8c7fb4540be1ef519b84e614f50f8a08089e..005dc65c80cb35466e54893a891a7c8ff8cba850 100644 (file)
@@ -1,5 +1,4 @@
-Details about the `async def` syntax for path operation functions and some background about asynchronous code, concurrency, and parallelism.
-
+Details about the `async def` syntax for *path operation functions* and some background about asynchronous code, concurrency, and parallelism.
 
 ## In a hurry?
 
@@ -7,12 +6,11 @@ Details about the `async def` syntax for path operation functions and some backg
 
 If you are using third party libraries that tell you to call them with `await`, like:
 
-
 ```Python
 results = await some_library()
 ```
 
-Then, declare your path operation functions with `async def` like:
+Then, declare your *path operation functions* with `async def` like:
 
 ```Python hl_lines="2"
 @app.get('/')
@@ -26,7 +24,7 @@ async def read_results():
 
 ---
 
-If you are using a third party library that communicates with something (a database, an API, the file system, etc) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your path operation functions as normally, with just `def`, like:
+If you are using a third party library that communicates with something (a database, an API, the file system, etc) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like:
 
 ```Python hl_lines="2"
 @app.get('/')
@@ -45,13 +43,12 @@ If you just don't know, use normal `def`.
 
 ---
 
-**Note**: you can mix `def` and `async def` in your path operation functions as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
+**Note**: you can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
 
 Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast.
 
 But by following the steps above, it will be able to do some performance optimizations.
 
-
 ## Technical Details
 
 Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax.
@@ -62,7 +59,6 @@ Let's see that phrase by parts in the sections below, below:
 * **`async` and `await`**
 * **Coroutines**
 
-
 ## Asynchronous Code
 
 Asynchronous code just means that the language has a way to tell the computer / program that at some point in the code, he will have to wait for *something else* to finish somewhere else. Let's say that *something else* is called "slow-file". 
@@ -92,7 +88,6 @@ Instead of that, by being an "asynchronous" system, once finished, the task can
 
 For "synchronous" (contrary to "asynchronous") they commonly also use the term "sequential", because the computer / program follows all the steps in sequence before switching to a different task, even if those steps involve waiting.
 
-
 ### Concurrency and Burgers
 
 This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**.
@@ -103,7 +98,6 @@ But the details between *concurrency* and *parallelism* are quite different.
 
 To see the difference, imagine the following story about burgers:
 
-
 ### Concurrent Burgers
 
 You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you.
@@ -144,7 +138,6 @@ So you wait for your crush to finish the story (finish the current work / task b
 
 Then you go to the counter, to the initial task that is now finished, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter. That in turn, creates a new task, of "eating burgers", but the previous one of "getting burgers" is finished.
 
-
 ### Parallel Burgers
 
 You go with your crush to get parallel fast food.
@@ -195,7 +188,6 @@ And you have to wait in the line for a long time or you lose your turn.
 
 You probably wouldn't want to take your crush with you to do errands at the bank.
 
-
 ### Burger Conclusion
 
 In this scenario of "fast food burgers with your crush", as there is a lot of waiting, it makes a lot more sense to have a concurrent system.
@@ -220,7 +212,6 @@ And that's the same level of performance</a> you get with **FastAPI**.
 
 And as you can have parallelism and asynchronicity at the same time, you get higher performance than most of the tested NodeJS frameworks and on par with Go, which is a compiled language closer to C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(all thanks to Starlette)</a>.
 
-
 ### Is concurrency better than parallelism?
 
 Nope! That's not the moral of the story.
@@ -258,7 +249,6 @@ For example:
 * **Machine Learning**: it normally requires lots of "matrix" and "vector" multiplications. Think of a huge spreadsheet with numbers and multiplying all of them together at the same time.
 * **Deep Learning**: this is a sub-field of Machine Learning, so, the same applies. It's just that there is not a single spreadsheet of numbers to multiply, but a huge set of them, and in many cases, you use a special processor to build and / or use those models.
 
-
 ### Concurrency + Parallelism: Web + Machine Learning
 
 With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attractive of NodeJS).
@@ -267,8 +257,7 @@ But you can also exploit the benefits of parallelism and multiprocessing (having
 
 That, plus the simple fact that Python is the main language for **Data Science**, Machine Learning and especially Deep Learning, make FastAPI a very good match for Data Science / Machine Learning web APIs and applications (among many others).
 
-To see how to achieve this parallelism in production see the section about [Deployment](deployment.md).
-
+To see how to achieve this parallelism in production see the section about [Deployment](deployment.md){.internal-link target=_blank}.
 
 ## `async` and `await`
 
@@ -310,7 +299,7 @@ burgers = get_burgers(2)
 
 ---
 
-So, if you are using a library that tells you that you can call it with `await`, you need to create the path operation functions that uses it with `async def`, like in:
+So, if you are using a library that tells you that you can call it with `await`, you need to create the *path operation functions* that uses it with `async def`, like in:
 
 ```Python hl_lines="2 3"
 @app.get('/burgers')
@@ -327,11 +316,10 @@ But at the same time, functions defined with `async def` have to be "awaited". S
 
 So, about the egg and the chicken, how do you call the first `async` function?
 
-If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your path operation function, and FastAPI will know how to do the right thing.
+If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your *path operation function*, and FastAPI will know how to do the right thing.
 
 But if you want to use `async` / `await` without FastAPI, <a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" class="external-link" target="_blank">check the official Python docs</a>.
 
-
 ### Other forms of asynchronous code
 
 This style of using `async` and `await` is relatively new in the language.
@@ -346,7 +334,6 @@ In previous versions of Python, you could have used threads or <a href="http://w
 
 In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which lead to <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
 
-
 ## Coroutines
 
 **Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function that it can start and that it will end at some point, but that it might be paused internally too, whenever there is an `await` inside of it.
@@ -363,7 +350,6 @@ That should make more sense now.
 
 All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance.
 
-
 ## Very Technical Details
 
 !!! warning
@@ -379,7 +365,7 @@ When you declare a *path operation function* with normal `def` instead of `async
 
 If you are coming from another async framework that does not work in the way described above and you are used to define trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">IO</abbr>.
 
-Still, in both situations, chances are that **FastAPI** will <a href="https://fastapi.tiangolo.com/#performance" target="_blank">still be faster</a> than (or at least comparable to) your previous framework.
+Still, in both situations, chances are that **FastAPI** will [still be faster](/#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework.
 
 ### Dependencies
 
index cffa473205f1f92b55b2a3599213036248d891f6..9cf663605bc8582f637b72d29f3ceab7452f594d 100644 (file)
@@ -1,4 +1,4 @@
-First, you might want to see the basic ways to <a href="https://fastapi.tiangolo.com/help-fastapi/" target="_blank">help FastAPI and get help</a>.
+First, you might want to see the basic ways to [help FastAPI and get help](help-fastapi.md){.internal-link target=_blank}.
 
 ## Developing
 
index 674cfdb206f0c44d24ba4b5cd62ebc4eb088e619..94bdbed43e807580a0c717a7dbb539c869867f5a 100644 (file)
@@ -1,3 +1,13 @@
 a.external-link::after {
-    content: " [↪]";
+    /* \00A0 is a non-breaking space
+        to make the mark be on the same line as the link
+    */
+    content: "\00A0[↪]";
+}
+
+a.internal-link::after {
+    /* \00A0 is a non-breaking space
+        to make the mark be on the same line as the link
+    */
+    content: "\00A0↪";
 }
index eaa593d3565b6fe82bcba7cdb407d4ea91ea8677..8a326c721c2dd2b6f6005a9dd5a6c9a7d593924d 100644 (file)
@@ -37,8 +37,7 @@ COPY ./app /app
 
 #### Bigger Applications
 
-If you followed the section about creating <a href="https://fastapi.tiangolo.com/tutorial/bigger-applications/" target="_blank">Bigger Applications with Multiple Files
-</a>, your `Dockerfile` might instead look like:
+If you followed the section about creating [Bigger Applications with Multiple Files](tutorial/bigger-applications.md){.internal-link target=_blank}, your `Dockerfile` might instead look like:
 
 ```Dockerfile
 FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
@@ -214,7 +213,7 @@ To set up a Docker Swarm Mode cluster with Traefik and HTTPS handling, follow th
 
 ### Deploy a FastAPI application
 
-The easiest way to set everything up, would be using the <a href="/project-generation/" target="_blank">FastAPI project generator</a>.
+The easiest way to set everything up, would be using the [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}.
 
 It is designed to be integrated with this Docker Swarm cluster with Traefik and HTTPS described above.
 
index cddff7b704de8bf4cb453739a0bbc3f4fa646ce3..69c62cbced1f6c389a248dcea448adc68144fbd9 100644 (file)
@@ -26,7 +26,7 @@ Interactive API documentation and exploration web user interfaces. As the framew
 
 It's all based on standard **Python 3.6 type** declarations (thanks to Pydantic). No new syntax to learn. Just standard modern Python.
 
-If you need a 2 minute refresher of how to use Python types (even if you don't use FastAPI), check the tutorial section: [Python types](python-types.md).
+If you need a 2 minute refresher of how to use Python types (even if you don't use FastAPI), check the short tutorial: [Python Types](python-types.md){.internal-link target=_blank}.
 
 You write standard Python with types:
 
@@ -121,7 +121,7 @@ Security and authentication integrated. Without any compromise with databases or
 All the security schemes defined in OpenAPI, including:
 
 * HTTP Basic.
-* **OAuth2** (also with **JWT tokens**). Check the [tutorial on OAuth2 with JWT](tutorial/security/oauth2-jwt.md).
+* **OAuth2** (also with **JWT tokens**). Check the tutorial on [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
 * API keys in:
     * Headers.
     * Query parameters.
@@ -136,9 +136,9 @@ All built as reusable tools and components that are easy to integrate with your
 FastAPI includes an extremely easy to use, but extremely powerful <abbr title='also known as "components", "resources", "services", "providers"'><strong>Dependency Injection</strong></abbr> system.
 
 * Even dependencies can have dependencies, creating a hierarchy or **"graph" of dependencies**.
-* All **automatically handled** by the framework. 
+* All **automatically handled** by the framework.
 * All the dependencies can require data from requests and **augment the path operation** constraints and automatic documentation.
-* **Automatic validation** even for path operation parameters defined in dependencies.
+* **Automatic validation** even for *path operation* parameters defined in dependencies.
 * Support for complex user authentication systems, **database connections**, etc.
 * **No compromise** with databases, frontends, etc. But easy integration with all of them.
 
@@ -146,7 +146,7 @@ FastAPI includes an extremely easy to use, but extremely powerful <abbr title='a
 
 Or in other way, no need for them, import and use the code you need.
 
-Any integration is designed to be so simple to use (with dependencies) that you can create a "plug-in" for your application in 2 lines of code using the same structure and syntax used for your path operations.
+Any integration is designed to be so simple to use (with dependencies) that you can create a "plug-in" for your application in 2 lines of code using the same structure and syntax used for your *path operations*.
 
 ### Tested
 
index 7f3ec8cf9926444421afa73cb9c6f83ae87e9cf6..08067e3c201bc9e3f4806007c48d52219010aaf7 100644 (file)
@@ -12,7 +12,7 @@ As part of that, I needed to investigate, test and use many alternatives.
 
 The history of **FastAPI** is in great part the history of its predecessors.
 
-As said in the section <a href="https://fastapi.tiangolo.com/alternatives/" target="_blank">Alternatives</a>:
+As said in the section [Alternatives](alternatives.md){.internal-link target=_blank}:
 
 <blockquote markdown="1">
 
@@ -74,4 +74,4 @@ But still, there are many improvements and features to come.
 
 **FastAPI** has a great future ahead.
 
-And <a href="https://fastapi.tiangolo.com/help-fastapi/" target="_blank">your help</a> is greatly appreciated.
+And [your help](help-fastapi.md){.internal-link target=_blank} is greatly appreciated.
index 80b9a193820bf18970593a902eef7d50a72dacae..69bd6a3385561d6d2c3ead0d3792b2b2cfe58bb9 100644 (file)
@@ -92,7 +92,7 @@ FastAPI stands on the shoulders of giants:
 pip install fastapi
 ```
 
-You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" target="_blank">Hypercorn</a>.
+You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
 
 ```bash
 pip install uvicorn
@@ -354,7 +354,7 @@ Try changing the line with:
 
 ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
 
-For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/intro/">Tutorial - User Guide</a>.
+For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
 
 **Spoiler alert**: the tutorial - user guide includes:
 
@@ -375,7 +375,7 @@ For a more complete example including more features, see the <a href="https://fa
 
 Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
 
-To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" target="_blank">Benchmarks</a>.
+To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
 
 ## Optional Dependencies
 
index 9dc0aa0f668761b8202bf0a97edd2357997d6c62..4562d6204a873d0f198744619286bbc6129e52d9 100644 (file)
@@ -10,14 +10,14 @@ GitHub: <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" clas
 * Docker Swarm Mode deployment.
 * **Docker Compose** integration and optimization for local development
 * **Production ready** Python web server using Uvicorn and Gunicorn.
-* Python **[FastAPI](https://github.com/tiangolo/fastapi)** backend:
+* Python <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">**FastAPI**</a> backend:
     * **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic).
     * **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
     * **Easy**: Designed to be easy to use and learn. Less time reading docs.
     * **Short**: Minimize code duplication. Multiple features from each parameter declaration.
     * **Robust**: Get production-ready code. With automatic interactive documentation.
     * **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
-    * [**Many other features**](https://github.com/tiangolo/fastapi) including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
+    * Many other features including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
 * **Secure password** hashing by default.
 * **JWT token** authentication.
 * **SQLAlchemy** models (independent of Flask extensions, so they can be used with Celery workers directly).
@@ -58,14 +58,14 @@ GitHub: <a href="https://github.com/tiangolo/full-stack-fastapi-couchbase" class
 * Docker Swarm Mode deployment.
 * **Docker Compose** integration and optimization for local development.
 * **Production ready** Python web server using Uvicorn and Gunicorn.
-* Python **[FastAPI](https://github.com/tiangolo/fastapi)** backend:
+* Python <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">**FastAPI**</a> backend:
     * **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic).
     * **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
     * **Easy**: Designed to be easy to use and learn. Less time reading docs.
     * **Short**: Minimize code duplication. Multiple features from each parameter declaration.
     * **Robust**: Get production-ready code. With automatic interactive documentation.
     * **Standards-based**: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
-    * [**Many other features**](https://github.com/tiangolo/fastapi) including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
+    * Many other features including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
 * **Secure password** hashing by default.
 * **JWT token** authentication.
 * **CORS** (Cross Origin Resource Sharing).
index 175e0e3aaa257c7888060f4f53324eed20627f5e..1ab66a1eaf578f188a8dc3e15ae193ee298c3028 100644 (file)
@@ -121,7 +121,6 @@ Now you know that you have to fix it, convert `age` to a string with `str(age)`:
 {!./src/python_types/tutorial004.py!}
 ```
 
-
 ## Declaring types
 
 You just saw the main place to declare type hints. As function parameters.
@@ -214,7 +213,6 @@ This means:
     * The keys of this `dict` are of type `str` (let's say, the name of each item).
     * The values of this `dict` are of type `float` (let's say, the price of each item).
 
-
 ### Classes as types
 
 You can also declare a class as the type of a variable.
@@ -235,7 +233,6 @@ And then, again, you get all the editor support:
 
 <img src="/img/python-types/image06.png">
 
-
 ## Pydantic models
 
 <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> is a Python library to perform data validation.
@@ -259,8 +256,7 @@ Taken from the official Pydantic docs:
 
 **FastAPI** is all based on Pydantic.
 
-You will see a lot more of all this in practice in the <a href="/tutorial/intro/" target="_blank">Tutorial - User Guide</a> (the next section).
-
+You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/){.internal-link target=_blank}.
 
 ## Type hints in **FastAPI**
 
@@ -280,7 +276,7 @@ With **FastAPI** you declare parameters with type hints and you get:
 * **Document** the API using OpenAPI:
     * which is then used by the automatic interactive documentation user interfaces.
 
-This might all sound abstract. Don't worry. You'll see all this in action in the <a href="/tutorial/intro/" target="_blank">Tutorial - User Guide</a> (the next section).
+This might all sound abstract. Don't worry. You'll see all this in action in the [Tutorial - User Guide](tutorial/){.internal-link target=_blank}.
 
 The important thing is that by using standard Python types, in a single place (instead of adding more classes, decorators, etc), **FastAPI** will do a lot of the work for you.
 
index 1b50dd423ebc1e15a501c157b90a68a9256cf5d5..15b92e8f5ae0f910dfe7b0290cf4026dc460d134 100644 (file)
@@ -19,9 +19,6 @@ First, import `BackgroundTasks` and define a parameter in your *path operation f
 
 **FastAPI** will create the object of type `BackgroundTasks` for you and pass it as that parameter.
 
-!!! tip
-    You declare a parameter of `BackgroundTasks` and use it in a very similar way as to when <a href="/tutorial/using-request-directly/" target="_blank">using the `Request` directly</a>.
-
 ## Create a task function
 
 Create a function to be run as the background task.
@@ -86,7 +83,7 @@ If you need to perform heavy background computation and you don't necessarily ne
 
 They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers.
 
-To see an example, check the <a href="https://fastapi.tiangolo.com/project-generation/" target="_blank">Project Generators</a>, they all include Celery already configured.
+To see an example, check the [Project Generators](../project-generation.md){.internal-link target=_blank}, they all include Celery already configured.
 
 But if you need to access variables and objects from the same **FastAPI** app, or you need to perform small background tasks (like sending an email notification), you can simply just use `BackgroundTasks`.
 
index 79156e5c9183f3d753aebd0d4c6332e75261d1a5..6ee298337fe4f855b49dba40ae205fda9ce2eb23 100644 (file)
@@ -62,7 +62,7 @@ You import it and create an "instance" the same way you would with the class `Fa
 {!./src/bigger_applications/app/routers/users.py!}
 ```
 
-### Path operations with `APIRouter`
+### *Path operations* with `APIRouter`
 
 And then you use it to declare your *path operations*.
 
@@ -87,7 +87,7 @@ We are going to include this `APIrouter` in the main `FastAPI` app, but first, l
 
 Let's say you also have the endpoints dedicated to handling "Items" from your application in the module at `app/routers/items.py`.
 
-You have path operations for:
+You have *path operations* for:
 
 * `/items/`
 * `/items/{item_id}`
@@ -223,9 +223,9 @@ Now, let's include the router from the `items` submodule.
 
 But, remember that we were lazy and didn't add `/items/` nor `tags` to all the *path operations*?
 
-We can add a prefix to all the path operations using the parameter `prefix` of `app.include_router()`.
+We can add a prefix to all the *path operations* using the parameter `prefix` of `app.include_router()`.
 
-As the path of each path operation has to start with `/`, like in:
+As the path of each *path operation* has to start with `/`, like in:
 
 ```Python hl_lines="1"
 @router.get("/{item_id}")
@@ -261,8 +261,8 @@ The end result is that the item paths are now:
 * The *path operation* that declared a custom `403` response will have both the predefined responses (`404`) and the `403` declared in it directly.
 * All these *path operations* will have the list of `dependencies` evaluated/executed before them.
     * If you also declare dependencies in a specific *path operation*, **they will be executed too**.
-    * The router dependencies are executed first, then the <a href="https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-decorator/" target="_blank">`dependencies` in the decorator</a>, and then the normal parameter dependencies.
-    * You can also add <a href="https://fastapi.tiangolo.com/tutorial/security/oauth2-scopes/" target="_blank">`Security` dependencies with `scopes`</a>.
+    * The router dependencies are executed first, then the [`dependencies` in the decorator](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, and then the normal parameter dependencies.
+    * You can also add [`Security` dependencies with `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}.
 
 !!! tip
     Having `dependencies` in a decorator can be used, for example, to require authentication for a whole group of *path operations*. Even if the dependencies are not added individually to each one of them.
@@ -271,7 +271,7 @@ The end result is that the item paths are now:
     The `prefix`, `tags`, `responses` and `dependencies` parameters are (as in many other cases) just a feature from **FastAPI** to help you avoid code duplication.
 
 !!! tip
-    You could also add path operations directly, for example with: `@app.get(...)`.
+    You could also add *path operations* directly, for example with: `@app.get(...)`.
 
     Apart from `app.include_router()`, in the same **FastAPI** app.
 
@@ -284,9 +284,9 @@ The end result is that the item paths are now:
 
     The `APIRouter`s are not "mounted", they are not isolated from the rest of the application.
 
-    This is because we want to include their path operations in the OpenAPI schema and the user interfaces.
+    This is because we want to include their *path operations* in the OpenAPI schema and the user interfaces.
 
-    As we cannot just isolate them and "mount" them independently of the rest, the path operations are "cloned" (re-created), not included directly.
+    As we cannot just isolate them and "mount" them independently of the rest, the *path operations* are "cloned" (re-created), not included directly.
 
 ## Check the automatic API docs
 
index fdb4ee53319504dc25220c436496b4644380a55f..f54ed4eb83f38fbf957991f8abb6f5bc79161582 100644 (file)
@@ -1,4 +1,4 @@
-The same way you can declare additional validation and metadata in path operation function parameters with `Query`, `Path` and `Body`, you can declare validation and metadata inside of Pydantic models using Pydantic's `Field`.
+The same way you can declare additional validation and metadata in *path operation function* parameters with `Query`, `Path` and `Body`, you can declare validation and metadata inside of Pydantic models using Pydantic's `Field`.
 
 ## Import `Field`
 
@@ -28,10 +28,10 @@ You can then use `Field` with model attributes:
 
     `Body` also returns objects of a subclass of `FieldInfo` directly. And there are others you will see later that are subclasses of the `Body` class.
 
-    Remember that when you import `Query`, `Path`, and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+    Remember that when you import `Query`, `Path`, and others from `fastapi`, those are actually functions that return special classes.
 
 !!! tip
-    Notice how each model's attribute with a type, default value and `Field` has the same structure as a path operation function's parameter, with `Field` instead of `Path`, `Query` and `Body`.
+    Notice how each model's attribute with a type, default value and `Field` has the same structure as a *path operation function's* parameter, with `Field` instead of `Path`, `Query` and `Body`.
 
 ## JSON Schema extras
 
index 23ad4fad5765319e422e956b4b9d697dd5277662..5009c21bfdb22976d1899b61f942b3d5c30167bf 100644 (file)
@@ -13,10 +13,9 @@ And you can also declare body parameters as optional, by setting the default to
 !!! note
     Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value.
 
-
 ## Multiple body parameters
 
-In the previous example, the path operations would expect a JSON body with the attributes of an `Item`, like:
+In the previous example, the *path operations* would expect a JSON body with the attributes of an `Item`, like:
 
 ```JSON
 {
@@ -160,9 +159,9 @@ instead of:
 
 ## Recap
 
-You can add multiple body parameters to your path operation function, even though a request can only have a single body.
+You can add multiple body parameters to your *path operation function*, even though a request can only have a single body.
 
-But **FastAPI** will handle it, give you the correct data in your function, and validate and document the correct schema in the path operation.
+But **FastAPI** will handle it, give you the correct data in your function, and validate and document the correct schema in the *path operation*.
 
 You can also declare singular values to be received as part of the body.
 
index c70e5f3ff9f3d5990b405e2923466389c52bd5f2..d5c5c95756e55f8d37b429b9a0c95771e462e731 100644 (file)
@@ -116,7 +116,7 @@ Again, doing just that declaration, with **FastAPI** you get:
 
 Apart from normal singular types like `str`, `int`, `float`, etc. You can use more complex singular types that inherit from `str`.
 
-To see all the options you have, checkout the docs for <a href="https://pydantic-docs.helpmanual.io/#exotic-types" class="external-link" target="_blank">Pydantic's exotic types</a>. You will see some examples in the next chapter.
+To see all the options you have, checkout the docs for <a href="https://pydantic-docs.helpmanual.io/usage/types/" class="external-link" target="_blank">Pydantic's exotic types</a>. You will see some examples in the next chapter.
 
 For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `HttpUrl`:
 
index 2d4961dd4ab8b6927ac6ef6d0050b4c19efe0eba..b951f16fb846886e60a060523797c72fc8e42144 100644 (file)
@@ -94,4 +94,4 @@ In summary, to apply partial updates you would:
 
     So, if you want to receive partial updates that can omit all the attributes, you need to have a model with all the attributes marked as optional (with default values or `None`).
 
-    To distinguish from the models with all optional values for **updates** and models with required values for **creation**, you can use the ideas described in <a href="https://fastapi.tiangolo.com/tutorial/extra-models/" target="_blank">Extra Models</a>.
+    To distinguish from the models with all optional values for **updates** and models with required values for **creation**, you can use the ideas described in [Extra Models](extra-models.md){.internal-link target=_blank}.
index 6cb95d0dcb89e7474c18607558eb372a4ce4c607..301caaf273f619c38676deab747e5d64fbcdaab3 100644 (file)
@@ -53,7 +53,7 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
 
 ## Declare it as a parameter
 
-To add it to your path operation, declare it the same way you declared path and query parameters:
+To add it to your *path operation*, declare it the same way you declared path and query parameters:
 
 ```Python hl_lines="16"
 {!./src/body/tutorial001.py!}
@@ -80,7 +80,7 @@ The JSON Schemas of your models will be part of your OpenAPI generated schema, a
 
 <img src="/img/tutorial/body/image01.png">
 
-And will be also used in the API docs inside each path operation that needs them:
+And will be also used in the API docs inside each *path operation* that needs them:
 
 <img src="/img/tutorial/body/image02.png">
 
index 62d93ce6ce28f5fabdfc81121bf89970f411fbfb..80999bc070e09caea82d20e11446c73d9fdbc1ab 100644 (file)
@@ -21,7 +21,7 @@ The first value is the default value, you can pass all the extra validation or a
 !!! note "Technical Details"
     `Cookie` is a "sister" class of `Path` and `Query`. It also inherits from the same common `Param` class.
 
-    But remember that when you import `Query`, `Path`, `Cookie` and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+    But remember that when you import `Query`, `Path`, `Cookie` and others from `fastapi`, those are actually functions that return special classes.
 
 !!! info
     To declare cookies, you need to use `Cookie`, because otherwise the parameters would be interpreted as query parameters.
index 3f872186bc412bbf3e85c4e792954a7415be8454..674615410832ae0c6d44c393ea646dba8b765ed8 100644 (file)
@@ -2,13 +2,13 @@ Before diving deeper into the **Dependency Injection** system, let's upgrade the
 
 ## A `dict` from the previous example
 
-In the previous example, we are returning a `dict` from our dependency ("dependable"):
+In the previous example, we were returning a `dict` from our dependency ("dependable"):
 
 ```Python hl_lines="7"
 {!./src/dependencies/tutorial001.py!}
 ```
 
-But then we get a `dict` in the parameter `commons` of the path operation function.
+But then we get a `dict` in the parameter `commons` of the *path operation function*.
 
 And we know that editors can't provide a lot of support (like completion) for `dict`s, because they can't know their keys and value types.
 
@@ -63,9 +63,9 @@ Then, in **FastAPI**, you could use a Python class as a dependency.
 
 What FastAPI actually checks is that it is a "callable" (function, class or anything else) and the parameters defined.
 
-If you pass a "callable" as a dependency in **FastAPI**, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a path operation function. Including sub-dependencies.
+If you pass a "callable" as a dependency in **FastAPI**, it will analyze the parameters for that "callable", and process them in the same way as the parameters for a *path operation function*. Including sub-dependencies.
 
-That also applies to callables with no parameters at all. The same as it would be for path operation functions with no parameters.
+That also applies to callables with no parameters at all. The same as it would be for *path operation functions* with no parameters.
 
 Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParameters`:
 
@@ -173,7 +173,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
 commons: CommonQueryParams = Depends()
 ```
 
-So, you can declare the dependency as the type of the variable, and use `Depends()` as the "default" value, without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
+So, you can declare the dependency as the type of the variable, and use `Depends()` as the "default" value (the value after the `=`) for that function's parameter, without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
 
 So, the same example would look like:
 
index 477bb3d1e828f763834234c29f1c0d879a47af88..7e774d5209ce180da1cb2fe1c55bf60ec5e0e5f7 100644 (file)
@@ -57,4 +57,4 @@ So, you can re-use a normal dependency (that returns a value) you already use so
 
 ## Dependencies for a group of *path operations*
 
-Later, when reading about how to <a href="https://fastapi.tiangolo.com/tutorial/bigger-applications/" target="_blank">structure bigger applications</a>, possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
+Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
index 73a8c808150f9da094cee79bbabac3dd11b59b31..31c77a589540b15279a35515f9b7ab9a7d18917a 100644 (file)
@@ -10,11 +10,11 @@ To do this, use `yield` instead of `return`, and write the extra steps after.
 !!! info
     For this to work, you need to use **Python 3.7** or above, or in **Python 3.6**, install the "backports":
 
-    ```bash
+    ```
     pip install async-exit-stack async-generator
     ```
 
-    This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" target="_blank">async-generator</a>.
+    This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
 
 !!! note "Technical Details"
     Any function that is valid to use with:
@@ -116,7 +116,7 @@ with open("./somefile.txt") as f:
     print(contents)
 ```
 
-Underneath, the `open("./somefile.txt")` returns an object that is a called a "Context Manager".
+Underneath, the `open("./somefile.txt")` creates an object that is a called a "Context Manager".
 
 When the `with` block finishes, it makes sure to close the file, even if there were exceptions.
 
@@ -129,9 +129,9 @@ When you create a dependency with `yield`, **FastAPI** will internally convert i
 
     If you are just starting with **FastAPI** you might want to skip it for now.
 
-In Python, you can create context managers by <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank">creating a class with two methods: `__enter__()` and `__exit__()`</a>.
+In Python, you can create Context Managers by <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank">creating a class with two methods: `__enter__()` and `__exit__()`</a>.
 
-You can also use them with **FastAPI** dependencies with `yield` by using
+You can also use them inside of **FastAPI** dependencies with `yield` by using
 `with` or `async with` statements inside of the dependency function:
 
 ```Python hl_lines="1 2 3 4 5 6 7 8 9 13"
similarity index 77%
rename from docs/tutorial/dependencies/first-steps.md
rename to docs/tutorial/dependencies/index.md
index 601fa6245b11ab12d45e77e626fd7c579bb7b650..f9cb4dd4a7b3627028a8bf95ef8c2f504d33612d 100644 (file)
@@ -2,9 +2,9 @@
 
 It is designed to be very simple to use, and to make it very easy for any developer to integrate other components with **FastAPI**.
 
-## "Dependency Injection"?
+## What is "Dependency Injection"
 
-**"Dependency Injection"** means, in programming, that there is a way for your code (in this case, your path operation functions) to declare things that it requires to work and use: "dependencies".
+**"Dependency Injection"** means, in programming, that there is a way for your code (in this case, your *path operation functions*) to declare things that it requires to work and use: "dependencies".
 
 And then, that system (in this case **FastAPI**) will take care of doing whatever is needed to provide your code with those needed dependencies ("inject" the dependencies).
 
@@ -13,7 +13,7 @@ This is very useful when you need to:
 * Have shared logic (the same code logic again and again).
 * Share database connections.
 * Enforce security, authentication, role requirements, etc.
-* etc.
+* And many other things...
 
 All these, while minimizing code repetition.
 
@@ -27,7 +27,7 @@ But this way we can focus on how the **Dependency Injection** system works.
 
 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:
+It is just a function that can take all the same parameters that a *path operation function* can take:
 
 ```Python hl_lines="6 7"
 {!./src/dependencies/tutorial001.py!}
@@ -37,9 +37,9 @@ That's it.
 
 **2 lines**.
 
-And it has the same shape and structure that all your path operation functions.
+And it has the same shape and structure that all your *path operation functions*.
 
-You can think of it as a path operation function without the "decorator" (without the `@app.get("/some-path")`).
+You can think of it as a *path operation function* without the "decorator" (without the `@app.get("/some-path")`).
 
 And it can return anything you want.
 
@@ -59,7 +59,7 @@ And then it just returns a `dict` containing those values.
 
 ### Declare the dependency, in the "dependant"
 
-The same way you use `Body`, `Query`, etc. with your path operation function parameters, use `Depends` with a new parameter:
+The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
 
 ```Python hl_lines="11 16"
 {!./src/dependencies/tutorial001.py!}
@@ -71,7 +71,7 @@ You only give `Depends` a single parameter.
 
 This parameter must be something like a function.
 
-And that function takes parameters in the same way that path operation functions do.
+And that function takes parameters in the same way that *path operation functions* do.
 
 !!! tip
     You'll see what other "things", apart from functions, can be used as dependencies in the next chapter.
@@ -80,26 +80,25 @@ Whenever a new request arrives, **FastAPI** will take care of:
 
 * Calling your dependency ("dependable") function with the correct parameters.
 * Get the result from your function.
-* Assign that result to the parameter in your path operation function.
+* Assign that result to the parameter in your *path operation function*.
 
-!!! note
+!!! check
     Notice that you don't have to create a special class and pass it somewhere to **FastAPI** to "register" it or anything similar.
 
     You just pass it to `Depends` and **FastAPI** knows how to do the rest.
 
 ## To `async` or not to `async`
 
-As dependencies will also be called by **FastAPI** (the same as your path operation functions), the same rules apply while defining your functions.
+As dependencies will also be called by **FastAPI** (the same as your *path operation functions*), the same rules apply while defining your functions.
 
 You can use `async def` or normal `def`.
 
-And you can declare dependencies with `async def` inside of normal `def` path operation functions, or `def` dependencies inside of `async def` path operation functions, etc.
+And you can declare dependencies with `async def` inside of normal `def` *path operation functions*, or `def` dependencies inside of `async def` *path operation functions*, etc.
 
 It doesn't matter. **FastAPI** will know what to do.
 
 !!! note
-    If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
-
+    If you don't know, check the [Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank} section about `async` and `await` in the docs.
 
 ## Integrated with OpenAPI
 
@@ -118,7 +117,7 @@ Actually, all (or most) of the web frameworks work in this same way.
 
 You never call those functions directly. They are called by your framework (in this case, **FastAPI**).
 
-With the Dependency Injection system, you can also tell **FastAPI** that your path operation function also "depends" on something else that should be executed before your *path operation function*, and **FastAPI** will take care of executing it and "injecting" the results.
+With the Dependency Injection system, you can also tell **FastAPI** that your *path operation function* also "depends" on something else that should be executed before your *path operation function*, and **FastAPI** will take care of executing it and "injecting" the results.
 
 Other common terms for this same idea of "dependency injection" are:
 
@@ -130,9 +129,9 @@ Other common terms for this same idea of "dependency injection" are:
 
 ## **FastAPI** plug-ins
 
-Integrations and "plug-in"s can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your path operation functions.
+Integrations and "plug-in"s can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your *path operation functions*.
 
-And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, _literally_.
+And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, *literally*.
 
 You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
 
@@ -159,6 +158,6 @@ In the end, a hierarchical tree of dependencies is built, and the **Dependency I
 
 ## Integrated with **OpenAPI**
 
-All these dependencies, while declaring their requirements, add parameters, validations, etc. to your path operations. 
+All these dependencies, while declaring their requirements, also add parameters, validations, etc. to your *path operations*.
 
 **FastAPI** will take care of adding it all to the OpenAPI schema, so that it is shown in the interactive documentation systems.
index e55dd14e4f41aa8ec1a46feb0fb87682aa6d18e3..a0ea0273eb255df7df2a8b6ed823082fd70b343a 100644 (file)
@@ -1,6 +1,6 @@
-You can create dependencies that have sub-dependencies.
+You can create dependencies that have **sub-dependencies**.
 
-They can be as "deep" as you need them to be.
+They can be as **deep** as you need them to be.
 
 **FastAPI** will take care of solving them.
 
@@ -40,7 +40,7 @@ Then we can use the dependency with:
 ```
 
 !!! info
-    Notice that we are only declaring one dependency in the path operation function, the `query_or_cookie_extractor`.
+    Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`.
 
     But **FastAPI** will know that it has to solve `query_extractor` first, to pass the results of that to `query_or_cookie_extractor` while calling it.
 
@@ -61,7 +61,7 @@ async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False
 
 Apart from all the fancy words used here, the **Dependency Injection** system is quite simple.
 
-Just functions that look the same as the path operation functions.
+Just functions that look the same as the *path operation functions*.
 
 But still, it is very powerful, and allows you to declare arbitrarily deeply nested dependency "graphs" (trees).
 
index 241c3c2cca03b86208dcc91a0b692a27a29a026f..7534be86da81b4d1394886636fc582d33b2c094a 100644 (file)
@@ -50,7 +50,7 @@ Here are some of the additional data types you can use:
 
 ## Example
 
-Here's an example path operation with parameters using some of the above types.
+Here's an example *path operation* with parameters using some of the above types.
 
 ```Python hl_lines="1 2 11 12 13 14 15"
 {!./src/extra_data_types/tutorial001.py!}
index 7accf0234118f936daa9895b4e572ae1d59b03e1..731a73f3d18e78f9f6a6b6182482e6e50cc5551b 100644 (file)
@@ -9,7 +9,7 @@ This is especially the case for user models, because:
 !!! danger
     Never store user's plaintext passwords. Always store a "secure hash" that you can then verify.
 
-    If you don't know, you will learn what a "password hash" is in the <a href="/tutorial/security/simple-oauth2/#password-hashing" target="_blank">security chapters</a>.
+    If you don't know, you will learn what a "password hash" is in the [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.
 
 ## Multiple models
 
index e1f3a5ce8b06b13316aa4902a37ff2dce7fb3692..af6661bedb81499fd3e9cd64719628dbdae4af05 100644 (file)
@@ -160,7 +160,7 @@ And put it in a file `main.py`, then you would call `uvicorn` like:
 uvicorn main:my_awesome_api --reload
 ```
 
-### Step 3: create a path operation
+### Step 3: create a *path operation*
 
 #### Path
 
@@ -218,7 +218,7 @@ So, in OpenAPI, each of the HTTP methods is called an "operation".
 
 We are going to call them "**operations**" too.
 
-#### Define a path operation function
+#### Define a *path operation function*
 
 ```Python hl_lines="6"
 {!./src/first_steps/tutorial001.py!}
@@ -289,7 +289,7 @@ You could also define it as a normal function instead of `async def`:
 ```
 
 !!! note
-    If you don't know the difference, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
+    If you don't know the difference, check the [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
 
 ### Step 5: return the content
 
index 973e91b9891fe61a134b55f2e80d6e3931fcb77e..a6784e24f9d2bb53b7f88cf5228a2b6156d72c3e 100644 (file)
@@ -33,7 +33,7 @@ To return HTTP responses with errors to the client you use `HTTPException`.
 
 Because it's a Python exception, you don't `return` it, you `raise` it.
 
-This also means that if you are inside a utility function that you are calling inside of your path operation function, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the path operation function, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client.
+This also means that if you are inside a utility function that you are calling inside of your *path operation function*, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the *path operation function*, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client.
 
 The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security.
 
@@ -231,7 +231,7 @@ So, you can keep raising **FastAPI**'s `HTTPException` as normally in your code.
 
 But when you register an exception handler, you should register it for Starlette's `HTTPException`.
 
-This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises an `HTTPException`, your handler will be able to catch handle it.
+This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises an `HTTPException`, your handler will be able to catch and handle it.
 
 In this example, to be able to have both `HTTPException`s in the same code, Starlette's exceptions is renamed to `StarletteHTTPException`:
 
@@ -246,9 +246,9 @@ You could also just want to use the exception somehow, but then use the same def
 You can import and re-use the default exception handlers from `fastapi.exception_handlers`:
 
 ```Python hl_lines="2 3 4 5 15 21"
-{!./src/handling_errors/tutorial005.py!}
+{!./src/handling_errors/tutorial006.py!}
 ```
 
-In this example, you are just `print`ing the error with a very expressive notification.
+In this example, you are just `print`ing the error with a very expressive message.
 
 But you get the idea, you can use the exception and then just re-use the default exception handlers.
index 503d612ed77331b5a3c69d35bb6ebe065174cc39..46c349bd11ff0aec1203dea9eb65b24a0ed4c251 100644 (file)
@@ -21,7 +21,7 @@ The first value is the default value, you can pass all the extra validation or a
 !!! note "Technical Details"
     `Header` is a "sister" class of `Path`, `Query` and `Cookie`. It also inherits from the same common `Param` class.
 
-    But remember that when you import `Query`, `Path`, `Header`, and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+    But remember that when you import `Query`, `Path`, `Header`, and others from `fastapi`, those are actually functions that return special classes.
 
 !!! info
     To declare headers, you need to use `Header`, because otherwise the parameters would be interpreted as query parameters.
similarity index 68%
rename from docs/tutorial/intro.md
rename to docs/tutorial/index.md
index 705f4cf7f20ff78bfd215339dd44c0fe31d303b4..0aa572c88e9d4d7c93950fb347dc8a4bf5ec4957 100644 (file)
@@ -1,4 +1,4 @@
-This tutorial shows you how to use **FastAPI** with all its features, step by step.
+This tutorial shows you how to use **FastAPI** with most of its features, step by step.
 
 Each section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
 
@@ -36,7 +36,7 @@ pip install fastapi[all]
 
 !!! note
     You can also install it part by part.
-    
+
     This is what you would probably do once you want to deploy your application to production:
 
     ```
@@ -50,3 +50,13 @@ pip install fastapi[all]
     ```
 
     And the same for each of the optional dependencies that you want to use.
+
+## Advanced User Guide
+
+There is also an **Advanced User Guide** that you can read later after this **Tutorial - User guide**.
+
+The **Advanced User Guide**, builds on this, uses the same concepts, and teaches you some extra features.
+
+But you should first read the **Tutorial - User guide** (what you are reading right now).
+
+It's designed so that you can build a complete application with just the **Tutorial - User guide**, and then extend it in different ways, depending on your needs, using some of the additional ideas from the **Advanced User Guide**.
index 7b18adc22cd7eb69a921fd61083ca278d2475714..b37ff75f1b0ca9c34f17da4ca9beaf6552c1c5ff 100644 (file)
@@ -25,17 +25,15 @@ The middleware function receives:
 {!./src/middleware/tutorial001.py!}
 ```
 
-!!! tip
-    This technique is used in the tutorial about <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">SQL (Relational) Databases</a>.
-
 !!! tip
     Have in mind that custom proprietary headers can be added <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">using the 'X-' prefix</a>.
 
-    But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your <a href="https://fastapi.tiangolo.com/tutorial/cors/" target="_blank">CORS configurations</a>, using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
+    But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)
+](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
 
 ### Before and after the `response`
 
-You can add code to be run with the `request`,  before any *path operation* receives it. 
+You can add code to be run with the `request`,  before any *path operation* receives it.
 
 And also after the `response` is generated, before returning it.
 
index a60d8e07fd1507af176a5e05595cab85ce4b436f..ff200aae154aed5a597e9382fca41dbfde8eb1df 100644 (file)
@@ -1,11 +1,11 @@
-There are several parameters that you can pass to your path operation decorator to configure it.
+There are several parameters that you can pass to your *path operation decorator* to configure it.
 
 !!! warning
-    Notice that these parameters are passed directly to the path operation decorator, not to your path operation function.
+    Notice that these parameters are passed directly to the *path operation decorator*, not to your *path operation function*.
 
 ## Response Status Code
 
-You can define the (HTTP) `status_code` to be used in the response of your path operation.
+You can define the (HTTP) `status_code` to be used in the response of your *path operation*.
 
 You can pass directly the `int` code, like `404`.
 
@@ -19,7 +19,7 @@ That status code will be used in the response and will be added to the OpenAPI s
 
 ## Tags
 
-You can add tags to your path operation, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
+You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
 
 ```Python hl_lines="17 22 27"
 {!./src/path_operation_configuration/tutorial002.py!}
@@ -39,9 +39,9 @@ You can add a `summary` and `description`:
 
 ## Description from docstring
 
-As descriptions tend to be long and cover multiple lines, you can declare the path operation description in the function <abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation">docstring</abbr> and **FastAPI** will read it from there.
+As descriptions tend to be long and cover multiple lines, you can declare the *path operation* description in the function <abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation">docstring</abbr> and **FastAPI** will read it from there.
 
-You can write <a href="https://en.wikipedia.org/wiki/Markdown" class="target-blank" target="_blank">Markdown</a> in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
+You can write <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
 
 ```Python hl_lines="19 20 21 22 23 24 25 26 27"
 {!./src/path_operation_configuration/tutorial004.py!}
@@ -60,18 +60,18 @@ You can specify the response description with the parameter `response_descriptio
 ```
 
 !!! info
-    Notice that `response_description` refers specifically to the response, the `description` refers to the path operation in general.
+    Notice that `response_description` refers specifically to the response, the `description` refers to the *path operation* in general.
 
-!!! info
-    OpenAPI specifies that each path operation requires a response description.
+!!! check
+    OpenAPI specifies that each *path operation* requires a response description.
 
     So, if you don't provide one, **FastAPI** will automatically generate one of "Successful response".
 
 <img src="/img/tutorial/path-operation-configuration/image03.png">
 
-## Deprecate a path operation
+## Deprecate a *path operation*
 
-If you need to mark a path operation as <abbr title="obsolete, recommended not to use it">deprecated</abbr>, but without removing it, pass the parameter `deprecated`:
+If you need to mark a *path operation* as <abbr title="obsolete, recommended not to use it">deprecated</abbr>, but without removing it, pass the parameter `deprecated`:
 
 ```Python hl_lines="16"
 {!./src/path_operation_configuration/tutorial006.py!}
@@ -81,10 +81,10 @@ It will be clearly marked as deprecated in the interactive docs:
 
 <img src="/img/tutorial/path-operation-configuration/image04.png">
 
-Check how deprecated and non-deprecated path operations look like:
+Check how deprecated and non-deprecated *path operations* look like:
 
 <img src="/img/tutorial/path-operation-configuration/image05.png">
 
 ## Recap
 
-You can configure and add metadata for your path operations easily by passing parameters to the path operation decorators.
+You can configure and add metadata for your *path operations* easily by passing parameters to the *path operation decorators*.
index 80ace2624ce71d74cf32fa3e4ea63ae6478e459d..5fe638f5f3351959f724ba0d34e02a4569906c55 100644 (file)
@@ -66,6 +66,7 @@ Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than o
 ```Python hl_lines="8"
 {!./src/path_params_numeric_validations/tutorial004.py!}
 ```
+
 ## Number validations: greater than and less than or equal
 
 The same applies for:
@@ -93,7 +94,7 @@ And the same for <abbr title="less than"><code>lt</code></abbr>.
 
 ## Recap
 
-With `Query`, `Path` (and others you haven't seen yet) you can declare [metadata and string validations (the previous chapter)](/tutorial/query-params-str-validations).
+With `Query`, `Path` (and others you haven't seen yet) you can declare metadata and string validations in the same ways as with [Query Parameters and String Validations](query-params-str-validations.md){.internal-link target=_blank}.
 
 And you can also declare numeric validations:
 
index 36ccaddea3a9884e0adf92745c438e136dc52f74..b4c4054551a3b76cd60d25505b696f1027986033 100644 (file)
@@ -105,7 +105,7 @@ Like `/users/me`, let's say that it's to get data about the current user.
 
 And then you can also have a path `/users/{user_id}` to get data about a specific user by some user ID.
 
-Because path operations are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
+Because *path operations* are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
 
 ```Python hl_lines="6 11"
 {!./src/path_params/tutorial003.py!}
index 2340ee71e621c5dcfae797a1617e4e88b10d4876..a2af2771419ebb6bab4d41245f0a363fdbac9d9b 100644 (file)
@@ -50,7 +50,7 @@ And then, we can pass more parameters to `Query`. In this case, the `max_length`
 q: str = Query(None, max_length=50)
 ```
 
-This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema path operation.
+This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
 
 ## Add more validations
 
index 85a69205d4d06a7df5a598c3bd5447fbe3a00d48..5e72301105ad386637d9c128da319c6b8a580530 100644 (file)
@@ -188,7 +188,7 @@ In this case, there are 3 query parameters:
 * `limit`, an optional `int`.
 
 !!! tip
-    You could also use `Enum`s <a href="https://fastapi.tiangolo.com/tutorial/path-params/#predefined-values" target="_blank">the same way as with *path parameters*</a>.
+    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
 
index c1a2bf1d2efc0bd25b0edca94084ecb067d02d45..608e9e55d2143dbf73023c52a2564870e1b20d2a 100644 (file)
@@ -26,9 +26,9 @@ Create file parameters the same way you would for `Body` or `Form`:
 !!! info
     `File` is a class that inherits directly from `Form`.
 
-    But remember that when you import `Query`, `Path`, `File` and others from `fastapi`, <a href="https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#recap" target="_blank">those are actually functions that return classes of the same name</a>.
+    But remember that when you import `Query`, `Path`, `File` and others from `fastapi`, those are actually functions that return special classes.
 
-!!! info
+!!! tip
     To declare File bodies, you need to use `File`, because otherwise the parameters would be interpreted as query parameters or body (JSON) parameters.
 
 The files will be uploaded as "form data".
@@ -62,7 +62,7 @@ Using `UploadFile` has several advantages over `bytes`:
 
 * `filename`: A `str` with the original file name that was uploaded (e.g. `myimage.jpg`).
 * `content_type`: A `str` with the content type (MIME type / media type) (e.g. `image/jpeg`).
-* `file`: A <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" target="_blank">`SpooledTemporaryFile`</a> (a <a href="https://docs.python.org/3/glossary.html#term-file-like-object" target="_blank">file-like</a> object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
+* `file`: A <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (a <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
 
 `UploadFile` has the following `async` methods. They all call the corresponding file methods underneath (using the internal `SpooledTemporaryFile`).
 
@@ -107,7 +107,7 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
     If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
 
 !!! warning
-    You can declare multiple `File` and `Form` parameters in a path operation, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
+    You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
 
     This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
 
@@ -126,7 +126,7 @@ To use that, declare a `List` of `bytes` or `UploadFile`:
 You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
 
 !!! note
-    Notice that, as of 2019-04-14, Swagger UI doesn't support multiple file uploads in the same form field. For more information, check <a href="https://github.com/swagger-api/swagger-ui/issues/4276" target="_blank">#4276</a> and <a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>.
+    Notice that, as of 2019-04-14, Swagger UI doesn't support multiple file uploads in the same form field. For more information, check <a href="https://github.com/swagger-api/swagger-ui/issues/4276" class="external-link" target="_blank">#4276</a> and <a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>.
 
     Nevertheless, **FastAPI** is already compatible with it, using the standard OpenAPI.
     
index ce057eab3e7ea45fbd48af42ef87222386dd723d..51ba786386c0cab43ebf7f72d941f5b1477f72ed 100644 (file)
@@ -24,7 +24,7 @@ The files and form fields will be uploaded as form data and you will receive the
 And you can declare some of the files as `bytes` and some as `UploadFile`.
 
 !!! warning
-    You can declare multiple `File` and `Form` parameters in a path operation, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
+    You can declare multiple `File` and `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `multipart/form-data` instead of `application/json`.
 
     This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
 
index 95b356e755a6130cf9f3fb16bfbe2aeed6fef243..edb9af64174ef44d304b627a5aa4c5f6d55e3f15 100644 (file)
@@ -30,7 +30,7 @@ With `Form` you can declare the same metadata and validation as with `Body` (and
 !!! info
     `Form` is a class that inherits directly from `Body`.
 
-!!! info
+!!! tip
     To declare form bodies, you need to use `Form` explicitly, because without it the parameters would be interpreted as query parameters or body (JSON) parameters.
 
 ## About "Form Fields"
@@ -47,7 +47,7 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
     If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
 
 !!! warning
-    You can declare multiple `Form` parameters in a path operation, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `application/x-www-form-urlencoded` instead of `application/json`.
+    You can declare multiple `Form` parameters in a *path operation*, but you can't also declare `Body` fields that you expect to receive as JSON, as the request will have the body encoded using `application/x-www-form-urlencoded` instead of `application/json`.
 
     This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
 
index 178ca378397ae074262ff729e97bff76d94a1f8a..1f1288ca7c4d1451b04863b307af9f71dbf8db1f 100644 (file)
@@ -1,4 +1,4 @@
-You can declare the model used for the response with the parameter `response_model` in any of the path operations:
+You can declare the model used for the response with the parameter `response_model` in any of the *path operations*:
 
 * `@app.get()`
 * `@app.post()`
@@ -11,7 +11,7 @@ You can declare the model used for the response with the parameter `response_mod
 ```
 
 !!! note
-    Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your path operation function, like all the parameters and body.
+    Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
 
 It receives the same type you would declare for a Pydantic model attribute, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`.
 
@@ -19,7 +19,7 @@ FastAPI will use this `response_model` to:
 
 * Convert the output data to its type declaration.
 * Validate the data.
-* Add a JSON Schema for the response, in the OpenAPI path operation.
+* Add a JSON Schema for the response, in the OpenAPI *path operation*.
 * Will be used by the automatic documentation systems.
 
 But most importantly:
@@ -47,7 +47,7 @@ Now, whenever a browser is creating a user with a password, the API will return
 
 In this case, it might not be a problem, because the user himself is sending the password.
 
-But if we use the same model for another path operation, we could be sending our user's passwords to every client.
+But if we use the same model for another *path operation*, we could be sending our user's passwords to every client.
 
 !!! danger
     Never send the plain password of a user in a response.
@@ -60,7 +60,7 @@ We can instead create an input model with the plaintext password and an output m
 {!./src/response_model/tutorial003.py!}
 ```
 
-Here, even though our path operation function is returning the same input user that contains the password:
+Here, even though our *path operation function* is returning the same input user that contains the password:
 
 ```Python hl_lines="22"
 {!./src/response_model/tutorial003.py!}
@@ -192,6 +192,6 @@ If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will s
 
 ## Recap
 
-Use the path operation decorator's parameter `response_model` to define response models and especially to ensure private data is filtered out.
+Use the *path operation decorator's* parameter `response_model` to define response models and especially to ensure private data is filtered out.
 
 Use `response_model_exclude_unset` to return only the values explicitly set.
index bd86b5a89992ca3584d0185c84a4b3a9a5df72bb..821de9a4ff20c24e91d7a7cb4b55f702533f9866 100644 (file)
@@ -1,4 +1,4 @@
-The same way you can specify a response model, you can also declare the HTTP status code used for the response with the parameter `status_code` in any of the path operations:
+The same way you can specify a response model, you can also declare the HTTP status code used for the response with the parameter `status_code` in any of the *path operations*:
 
 * `@app.get()`
 * `@app.post()`
@@ -11,7 +11,7 @@ The same way you can specify a response model, you can also declare the HTTP sta
 ```
 
 !!! note
-    Notice that `status_code` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your path operation function, like all the parameters and body.
+    Notice that `status_code` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
 
 The `status_code` parameter receives a number with the HTTP status code.
 
@@ -76,4 +76,4 @@ They are just a convenience, they hold the same number, but that way you can use
 
 ## Changing the default
 
-Later, in a more advanced part of the tutorial/user guide, you will see how to <a href="https://fastapi.tiangolo.com/tutorial/response-change-status-code/" target="_blank">return a different status code than the default</a> you are declaring here.
+Later, in the **Advanced User Guide**, you will see how to return a different status code than the default you are declaring here.
index 26dbed0d7d9a931a6e9d61a31092007b7d5bb394..5d215bdd0540ad994053f822a3fc7fe60adfda2c 100644 (file)
@@ -48,7 +48,7 @@ You will see something like this:
 !!! check "Authorize button!"
     You already have a shinny new "Authorize" button.
 
-    And your path operation has a little lock in the top-right corner that you can click.
+    And your *path operation* has a little lock in the top-right corner that you can click.
 
 And if you click it, you have a little authorization form to type a `username` and `password` (and other optional fields):
 
@@ -112,7 +112,7 @@ In this example we are going to use **OAuth2**, with the **Password** flow, usin
 {!./src/security/tutorial001.py!}
 ```
 
-It doesn't create that endpoint / path operation, but declares that that URL is the one that the client should use to get the token. That information is used in OpenAPI, and then in the interactive API documentation systems.
+It doesn't create that endpoint / *path operation*, but declares that that URL is the one that the client should use to get the token. That information is used in OpenAPI, and then in the interactive API documentation systems.
 
 !!! info
     If you are a very strict "Pythonista" you might dislike the style of the parameter name `tokenUrl` instead of `token_url`.
index e38830b1c1a6a9512452dc60a2b6e1b0ed2fc0b7..e2d6b7924cacd495c09b47eb08f7f15a24f3b69e 100644 (file)
@@ -1,4 +1,4 @@
-In the previous chapter the security system (which is based on the dependency injection system) was giving the path operation function a `token` as a `str`:
+In the previous chapter the security system (which is based on the dependency injection system) was giving the *path operation function* a `token` as a `str`:
 
 ```Python hl_lines="10"
 {!./src/security/tutorial001.py!}
@@ -26,7 +26,7 @@ Remember that dependencies can have sub-dependencies?
 
 `get_current_user` will have a dependency with the same `oauth2_scheme` we created before.
 
-The same as we were doing before in the path operation directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`:
+The same as we were doing before in the *path operation* directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`:
 
 ```Python hl_lines="25"
 {!./src/security/tutorial002.py!}
@@ -42,7 +42,7 @@ The same as we were doing before in the path operation directly, our new depende
 
 ## Inject the current user
 
-So now we can use the same `Depends` with our `get_current_user` in the path operation:
+So now we can use the same `Depends` with our `get_current_user` in the *path operation*:
 
 ```Python hl_lines="31"
 {!./src/security/tutorial002.py!}
@@ -65,7 +65,7 @@ This will help us inside of the function with all the completion and type checks
 
 ## Other models
 
-You can now get the current user directly in the path operation functions and deal with the security mechanisms at the **Dependency Injection** level, using `Depends`.
+You can now get the current user directly in the *path operation functions* and deal with the security mechanisms at the **Dependency Injection** level, using `Depends`.
 
 And you can use any model or data for the security requirements (in this case, a Pydantic model `User`).
 
@@ -82,7 +82,7 @@ Just use any kind of model, any kind of class, any kind of database that you nee
 
 ## Code size
 
-This example might seem verbose. Have in mind that we are mixing security, data models utility functions and path operations in the same file.
+This example might seem verbose. Have in mind that we are mixing security, data models utility functions and *path operations* in the same file.
 
 But here's the key point.
 
@@ -90,11 +90,11 @@ The security and dependency injection stuff is written once.
 
 And you can make it as complex as you want. And still, have it written only once, in a single place. With all the flexibility.
 
-But you can have thousands of endpoints (path operations) using the same security system.
+But you can have thousands of endpoints (*path operations*) using the same security system.
 
 And all of them (or any portion of them that you want) can take the advantage of re-using these dependencies or any other dependencies you create.
 
-And all these thousands of path operations can be as small as 3 lines:
+And all these thousands of *path operations* can be as small as 3 lines:
 
 ```Python hl_lines="30 31 32"
 {!./src/security/tutorial002.py!}
@@ -102,10 +102,10 @@ And all these thousands of path operations can be as small as 3 lines:
 
 ## Recap
 
-You can now get the current user directly in your path operation function.
+You can now get the current user directly in your *path operation function*.
 
 We are already halfway there.
 
-We just need to add a path operation for the user/client to actually send the `username` and `password`.
+We just need to add a *path operation* for the user/client to actually send the `username` and `password`.
 
-That comes next.
\ No newline at end of file
+That comes next.
index 10c777bc8e401040305b52d46b6b9590f90ae331..163d8126fe88b50c678aa5551b2b8e47fccb8f78 100644 (file)
@@ -18,9 +18,9 @@ It is not encrypted, so, anyone could recover the information from the contents.
 
 But it's signed. So, when you receive a token that you emitted, you can verify that you actually emitted it.
 
-That way, you can create a token with an expiration of, let's say, 1 week, and then, after a week, when the user comes back with the token, you know he's still signed into your system.
+That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know she/he is still signed into your system.
 
-And after a week, the token will be expired. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
+And after a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
 
 If you want to play with JWT tokens and see how they work, check <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>.
 
@@ -131,7 +131,7 @@ If the token is invalid, return an HTTP error right away.
 {!./src/security/tutorial004.py!}
 ```
 
-## Update the `/token` path operation
+## Update the `/token` *path operation*
 
 Create a `timedelta` with the expiration time of the token.
 
@@ -211,7 +211,7 @@ You can use them to add a specific set of permissions to a JWT token.
 
 Then you can give this token to a user directly or a third party, to interact with your API with a set of restrictions.
 
-You can learn how to use them and how they are integrated into **FastAPI** in the next chapter.
+You can learn how to use them and how they are integrated into **FastAPI** later in the **Advanced User Guide**.
 
 ## Recap
 
@@ -229,10 +229,8 @@ It gives you all the flexibility to choose the ones that fit your project the be
 
 And you can use directly many well maintained and widely used packages like `passlib` and `pyjwt`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
 
-But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness or security.
+But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security.
 
 And you can use and implement secure, standard protocols, like OAuth2 in a relatively simple way.
 
-In the next (optional) section you can see how to extend this even further, using OAuth2 "scopes", for a more fine-grained permission system, following these same standards.
-
-OAuth2 with scopes (explained in the next section) is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, Twitter, etc.
+You can learn more in the **Advanced User Guide** about how to use OAuth2 "scopes", for a more fine-grained permission system, following these same standards. OAuth2 with scopes is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, Twitter, etc. to authorize third party applications to interact with their APIs on behalf of their users.
index cd0341b204ece239d37032c245de6b2f003e6c97..041f8517cae5e00819ddf13972b6905776aec756 100644 (file)
@@ -12,7 +12,7 @@ But don't worry, you can show it as you wish to your final users in the frontend
 
 And your database models can use any other names you want.
 
-But for the login path operation, we need to use these names to be compatible with the spec (and be able to, for example, use the integrated API documentation system).
+But for the login *path operation*, we need to use these names to be compatible with the spec (and be able to, for example, use the integrated API documentation system).
 
 The spec also states that the `username` and `password` must be sent as form data (so, no JSON here).
 
@@ -26,14 +26,14 @@ Each "scope" is just a string (without spaces).
 
 They are normally used to declare specific security permissions, for example:
 
-* `"users:read"` or `"users:write"` are common examples.
+* `users:read` or `users:write` are common examples.
 * `instagram_basic` is used by Facebook / Instagram.
 * `https://www.googleapis.com/auth/drive` is used by Google.
 
 !!! info
     In OAuth2 a "scope" is just a string that declares a specific permission required.
 
-    It doesn't matter if it has other characters like `:`, or if it is a URL.
+    It doesn't matter if it has other characters like `:` or if it is a URL.
     
     Those details are implementation specific.
 
@@ -114,7 +114,7 @@ But you cannot convert from the gibberish back to the password.
 
 If your database is stolen, the thief won't have your users' plaintext passwords, only the hashes.
 
-So, the thief won't be able to try to use that password in another system (as many users use the same password everywhere, this would be dangerous).
+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="79 80 81 82"
 {!./src/security/tutorial003.py!}
@@ -137,7 +137,7 @@ UserInDB(
 ```
 
 !!! info
-    For a more complete explanation of `**user_dict` check back in <a href="/tutorial/extra-models/#about-user_indict" target="_blank">the documentation for **Extra Models**</a>.
+    For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user_indict){.internal-link target=_blank}.
 
 ## Return the token
 
index ec00f041b55f4141fcda6d2eff2fa4fbd9066947..ab2633279fd55b59f053b4a296db482957a66668 100644 (file)
@@ -369,7 +369,7 @@ Create utility functions to:
 ```
 
 !!! tip
-    By creating functions that are only dedicated to interacting with the database (get a user or an item) independent of your path operation function, you can more easily reuse them in multiple parts and also add <abbr title="Automated tests, written in code, that check if another piece of code is working correctly.">unit tests</abbr> for them.
+    By creating functions that are only dedicated to interacting with the database (get a user or an item) independent of your *path operation function*, you can more easily reuse them in multiple parts and also add <abbr title="Automated tests, written in code, that check if another piece of code is working correctly.">unit tests</abbr> for them.
 
 ### Create data
 
@@ -444,7 +444,7 @@ A "migration" is the set of steps needed whenever you change the structure of yo
     pip install async-exit-stack async-generator
     ```
 
-    This installs <a href="https://github.com/sorcio/async_exit_stack" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
+    This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
 
     You can also use the alternative method with a "middleware" explained at the end.
 
@@ -454,7 +454,7 @@ We need to have an independent database session/connection (`SessionLocal`) per
 
 And then a new session will be created for the next request.
 
-For that, we will create a new dependency with `yield`, as explained before in the section about <a href="https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/" target="_blank">Dependencies with `yield`</a>.
+For that, we will create a new dependency with `yield`, as explained before in the section about [Dependencies with `yield`](dependencies/dependencies-with-yield.md){.internal-link target=_blank}.
 
 Our dependency will create a new SQLAlchemy `SessionLocal` that will be used in a single request, and then close it once the request is finished.
 
@@ -492,9 +492,9 @@ Now, finally, here's the standard **FastAPI** *path operations* code.
 
 We are creating the database session before each request in the dependency with `yield`, and then closing it afterwards.
 
-And then we can create the required dependency in the path operation function, to get that session directly.
+And then we can create the required dependency in the *path operation function*, to get that session directly.
 
-With that, we can just call `crud.get_user` directly from inside of the path operation function and use that session.
+With that, we can just call `crud.get_user` directly from inside of the *path operation function* and use that session.
 
 !!! tip
     Notice that the values you return are SQLAlchemy models, or lists of SQLAlchemy models.
@@ -508,7 +508,7 @@ With that, we can just call `crud.get_user` directly from inside of the path ope
 
 ### About `def` vs `async def`
 
-Here we are using SQLAlchemy code inside of the path operation function and in the dependency, and, in turn, it will go and communicate with an external database.
+Here we are using SQLAlchemy code inside of the *path operation function* and in the dependency, and, in turn, it will go and communicate with an external database.
 
 That could potentially require some "waiting".
 
@@ -534,7 +534,7 @@ def read_user(user_id: int, db: Session = Depends(get_db)):
 ```
 
 !!! note "Very Technical Details"
-    If you are curious and have a deep technical knowledge, you can check <a href="https://fastapi.tiangolo.com/async/#very-technical-details" target="_blank">the very technical details of how this `async def` vs `def` is handled</a>.
+    If you are curious and have a deep technical knowledge, you can check the very technical details of how this `async def` vs `def` is handled in the [Async](../async.md#very-technical-details){.internal-link target=_blank} docs.
 
 ## Migrations
 
@@ -612,7 +612,7 @@ It will look like this:
 
 <img src="/img/tutorial/sql-databases/image02.png">
 
-You can also use an online SQLite browser like <a href="https://inloop.github.io/sqlite-viewer/" target="_blank">SQLite Viewer</a> or <a href="https://extendsclass.com/sqlite-browser.html" class="external-link" target="_blank">ExtendsClass</a>.
+You can also use an online SQLite browser like <a href="https://inloop.github.io/sqlite-viewer/" class="external-link" target="_blank">SQLite Viewer</a> or <a href="https://extendsclass.com/sqlite-browser.html" class="external-link" target="_blank">ExtendsClass</a>.
 
 ## Alternative DB session with middleware
 
index 0b1cfb8d4e05cb1dc0c1bc3fc124eaf34c087111..77ffdee8237a7b235e8700ae0c00a7802dfb042a 100644 (file)
@@ -11,13 +11,19 @@ pip install aiofiles
 ## Use `StaticFiles`
 
 * Import `StaticFiles` from Starlette.
-* "Mount" it the same way you would <a href="https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/" target="_blank">mount a Sub-Application</a>.
+* "Mount" a `StaticFiles()` instance in a specific path.
 
 ```Python hl_lines="2 6"
 {!./src/static_files/tutorial001.py!}
 ```
 
-Then you could have a directory `./static/` with some files that will be served directly.
+### What is "Mounting"
+
+"Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
+
+This is different from using an `APIRouter` as a mounted application is completely independent. The OpenAPI and docs from your main application won't include anything from the mounted application, etc.
+
+You can read more about this in the **Advanced User Guide**.
 
 ## Details
 
index 2819b4f609d179704190751f9f4bc5f36c8797ba..5eaf6e778d11741ff07cd45d0bb01055907da74a 100644 (file)
@@ -92,25 +92,7 @@ For more information about how to pass data to the backend (using `requests` or
 !!! info
     Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models.
 
-    If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the <a href="https://fastapi.tiangolo.com/tutorial/encoder/" target="_blank">JSON compatible encoder: `jsonable_encoder`</a>.
-
-## Testing WebSockets
-
-You can use the same `TestClient` to test WebSockets.
-
-For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket:
-
-```Python hl_lines="27 28 29 30 31"
-{!./src/app_testing/tutorial002.py!}
-```
-
-## Testing Events, `startup` and `shutdown`
-
-When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement:
-
-```Python hl_lines="9 10 11 12 20 21 22 23 24"
-{!./src/app_testing/tutorial003.py!}
-```
+    If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the `jsonable_encoder` descibed in [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
 
 ## Run it
 
index 592634230858e7122be51df1c723d75d233a4af3..e38ed9b7f1f3e71c68c85489dc3ed7d17fdf304b 100644 (file)
@@ -22,7 +22,7 @@ nav:
     - Features: 'features.md'
     - Python types intro: 'python-types.md'
     - Tutorial - User Guide:
-        - Tutorial - User Guide - Intro: 'tutorial/intro.md'
+        - Tutorial - User Guide - Intro: 'tutorial/index.md'
         - First Steps: 'tutorial/first-steps.md'
         - Path Parameters: 'tutorial/path-params.md'
         - Query Parameters: 'tutorial/query-params.md'
@@ -43,53 +43,59 @@ nav:
         - Request Forms and Files: 'tutorial/request-forms-and-files.md'
         - Handling Errors: 'tutorial/handling-errors.md'
         - Path Operation Configuration: 'tutorial/path-operation-configuration.md'
-        - Path Operation Advanced Configuration: 'tutorial/path-operation-advanced-configuration.md'
-        - Additional Status Codes: 'tutorial/additional-status-codes.md'
-        - JSON compatible encoder: 'tutorial/encoder.md'
+        - JSON Compatible Encoder: 'tutorial/encoder.md'
         - Body - updates: 'tutorial/body-updates.md'
-        - Return a Response directly: 'tutorial/response-directly.md'
-        - Custom Response Class: 'tutorial/custom-response.md'
-        - Additional Responses in OpenAPI: 'tutorial/additional-responses.md'
-        - Response Cookies: 'tutorial/response-cookies.md'
-        - Response Headers: 'tutorial/response-headers.md'
-        - Response - Change Status Code: 'tutorial/response-change-status-code.md'
         - Dependencies:
-            - First Steps: 'tutorial/dependencies/first-steps.md'
+            - First Steps: 'tutorial/dependencies/index.md'
             - Classes as Dependencies: 'tutorial/dependencies/classes-as-dependencies.md'
             - Sub-dependencies: 'tutorial/dependencies/sub-dependencies.md'
             - Dependencies in path operation decorators: 'tutorial/dependencies/dependencies-in-path-operation-decorators.md'
             - Dependencies with yield: 'tutorial/dependencies/dependencies-with-yield.md'
-            - Advanced Dependencies: 'tutorial/dependencies/advanced-dependencies.md'
         - Security: 
-            - Security Intro: 'tutorial/security/intro.md'
+            - Security Intro: 'tutorial/security/index.md'
             - First Steps: 'tutorial/security/first-steps.md'
             - Get Current User: 'tutorial/security/get-current-user.md'
             - Simple OAuth2 with Password and Bearer: 'tutorial/security/simple-oauth2.md'
             - OAuth2 with Password (and hashing), Bearer with JWT tokens: 'tutorial/security/oauth2-jwt.md'
-            - OAuth2 scopes: 'tutorial/security/oauth2-scopes.md'
-            - HTTP Basic Auth: 'tutorial/security/http-basic-auth.md'
         - Middleware: 'tutorial/middleware.md'    
         - CORS (Cross-Origin Resource Sharing): 'tutorial/cors.md'    
-        - Using the Request Directly: 'tutorial/using-request-directly.md'    
         - SQL (Relational) Databases: 'tutorial/sql-databases.md'
-        - SQL (Relational) Databases with Peewee: 'tutorial/sql-databases-peewee.md'
-        - Async SQL (Relational) Databases: 'tutorial/async-sql-databases.md'
-        - NoSQL (Distributed / Big Data) Databases: 'tutorial/nosql-databases.md'
         - Bigger Applications - Multiple Files: 'tutorial/bigger-applications.md'
         - Background Tasks: 'tutorial/background-tasks.md'
-        - Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md'
         - Application Configuration: 'tutorial/application-configuration.md'
         - Static Files: 'tutorial/static-files.md'
-        - Templates: 'tutorial/templates.md'
-        - GraphQL: 'tutorial/graphql.md'
-        - WebSockets: 'tutorial/websockets.md'
-        - 'Events: startup - shutdown': 'tutorial/events.md'
-        - Custom Request and APIRoute class: 'tutorial/custom-request-and-route.md'
         - Testing: 'tutorial/testing.md'
-        - Testing Dependencies with Overrides: 'tutorial/testing-dependencies.md'
         - Debugging: 'tutorial/debugging.md'
-        - Extending OpenAPI: 'tutorial/extending-openapi.md'
-        - OpenAPI Callbacks: 'tutorial/openapi-callbacks.md'
+    - Advanced User Guide:
+        - Advanced User Guide - Intro: 'advanced/index.md'
+        - Path Operation Advanced Configuration: 'advanced/path-operation-advanced-configuration.md'
+        - Additional Status Codes: 'advanced/additional-status-codes.md'
+        - Return a Response Directly: 'advanced/response-directly.md'
+        - Custom Response Class: 'advanced/custom-response.md'
+        - Additional Responses in OpenAPI: 'advanced/additional-responses.md'
+        - Response Cookies: 'advanced/response-cookies.md'
+        - Response Headers: 'advanced/response-headers.md'
+        - Response - Change Status Code: 'advanced/response-change-status-code.md'
+        - Advanced Dependencies: 'advanced/advanced-dependencies.md'
+        - Advanced Security:
+            - Advanced Security - Intro: advanced/security/index.md
+            - OAuth2 scopes: 'advanced/security/oauth2-scopes.md'
+            - HTTP Basic Auth: 'advanced/security/http-basic-auth.md'
+        - Using the Request Directly: 'advanced/using-request-directly.md'
+        - SQL (Relational) Databases with Peewee: 'advanced/sql-databases-peewee.md'
+        - Async SQL (Relational) Databases: 'advanced/async-sql-databases.md'
+        - NoSQL (Distributed / Big Data) Databases: 'advanced/nosql-databases.md'
+        - Sub Applications - Behind a Proxy: 'advanced/sub-applications-proxy.md'
+        - Templates: 'advanced/templates.md'
+        - GraphQL: 'advanced/graphql.md'
+        - WebSockets: 'advanced/websockets.md'
+        - 'Events: startup - shutdown': 'advanced/events.md'
+        - Custom Request and APIRoute class: 'advanced/custom-request-and-route.md'
+        - Testing WebSockets: 'advanced/testing-websockets.md'
+        - 'Testing Events: startup - shutdown': 'advanced/testing-events.md'
+        - Testing Dependencies with Overrides: 'advanced/testing-dependencies.md'
+        - Extending OpenAPI: 'advanced/extending-openapi.md'
+        - OpenAPI Callbacks: 'advanced/openapi-callbacks.md'
     - Concurrency and async / await: 'async.md'
     - Deployment: 'deployment.md'
     - Project Generation - Template: 'project-generation.md'