diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index d64ca6b40..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: "[BUG]" -labels: bug -assignees: '' - ---- - -### Describe the bug - -Write here a clear and concise description of what the bug is. - -### To Reproduce - -Steps to reproduce the behavior with a minimum self-contained file. - -Replace each part with your own scenario: - -1. Create a file with: - -```Python -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -def read_root(): - return {"Hello": "World"} -``` - -3. Open the browser and call the endpoint `/`. -4. It returns a JSON with `{"Hello": "World"}`. -5. But I expected it to return `{"Hello": "Sara"}`. - -### Expected behavior - -Add a clear and concise description of what you expected to happen. - -### Screenshots - -If applicable, add screenshots to help explain your problem. - -### Environment - -- OS: [e.g. Linux / Windows / macOS] -- FastAPI Version [e.g. 0.3.0], get it with: - -```bash -python -c "import fastapi; print(fastapi.__version__)" -``` - -- Python version, get it with: - -```bash -python --version -``` - -### Additional context - -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 15b94028e..75c02cc1f 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,26 +1,104 @@ --- name: Feature request about: Suggest an idea for this project -title: "[FEATURE]" +title: "" labels: enhancement assignees: '' --- -### Is your feature request related to a problem +### First check -Is your feature request related to a problem? +* [ ] I added a very descriptive title to this issue. +* [ ] I used the GitHub search to find a similar issue and didn't find it. +* [ ] I searched the FastAPI documentation, with the integrated search. +* [ ] I already searched in Google "How to X in FastAPI" and didn't find any information. +* [ ] I already read and followed all the tutorial in the docs and didn't find an answer. +* [ ] I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/samuelcolvin/pydantic). +* [ ] I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui). +* [ ] I already checked if it is not related to FastAPI but to [ReDoc](https://github.com/Redocly/redoc). +* [ ] After submitting this, I commit to: + * Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there. + * Or, I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future. + * Implement a Pull Request for a confirmed bug. -Add a clear and concise description of what the problem is. Ex. I want to be able to [...] but I can't because [...] + + +### Example + +Here's a self-contained [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with my use case: + + + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} +``` + +### Description + + + +* Open the browser and call the endpoint `/`. +* It returns a JSON with `{"Hello": "World"}`. +* I would like it to have an extra parameter to teleport me to the moon and back. ### The solution you would like -Add a clear and concise description of what you want to happen. + + +I would like it to have a `teleport_to_moon` parameter that defaults to `False`, and can be set to `True` to teleport me: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/", teleport_to_moon=True) +def read_root(): + return {"Hello": "World"} +``` ### Describe alternatives you've considered -Add a clear and concise description of any alternative solutions or features you've considered. + + +To wait for Space X moon travel plans to drop down long after they release them. But I would rather teleport. + +### Environment + +* OS: [e.g. Linux / Windows / macOS]: +* FastAPI Version [e.g. 0.3.0]: + +To know the FastAPI version use: + +```bash +python -c "import fastapi; print(fastapi.__version__)" +``` + +* Python version: + +To know the Python version use: + +```bash +python --version +``` ### Additional context -Add any other context or screenshots about the feature request here. + diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index e7466133b..c49538916 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -1,24 +1,81 @@ --- -name: Question -about: Ask a question -title: "[QUESTION]" +name: Question or Problem +about: Ask a question or ask about a problem +title: "" labels: question -assignees: '' +assignees: "" --- ### First check +* [ ] I added a very descriptive title to this issue. * [ ] I used the GitHub search to find a similar issue and didn't find it. * [ ] I searched the FastAPI documentation, with the integrated search. * [ ] I already searched in Google "How to X in FastAPI" and didn't find any information. +* [ ] I already read and followed all the tutorial in the docs and didn't find an answer. +* [ ] I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/samuelcolvin/pydantic). +* [ ] I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui). +* [ ] I already checked if it is not related to FastAPI but to [ReDoc](https://github.com/Redocly/redoc). +* [ ] After submitting this, I commit to one of: + * Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there. + * I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future. + * Implement a Pull Request for a confirmed bug. + + + +### Example + +Here's a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with my use case: + + + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} +``` ### Description -How can I [...]? + -Is it possible to [...]? +* Open the browser and call the endpoint `/`. +* It returns a JSON with `{"Hello": "World"}`. +* But I expected it to return `{"Hello": "Sara"}`. + +### Environment + +* OS: [e.g. Linux / Windows / macOS]: +* FastAPI Version [e.g. 0.3.0]: + +To know the FastAPI version use: + +```bash +python -c "import fastapi; print(fastapi.__version__)" +``` + +* Python version: + +To know the Python version use: + +```bash +python --version +``` ### Additional context -Add any other context or screenshots about the question here. + diff --git a/.github/workflows/main.yml b/.github/workflows/issue-manager.yml similarity index 60% rename from .github/workflows/main.yml rename to .github/workflows/issue-manager.yml index 5e0a49684..712930e0b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/issue-manager.yml @@ -1,15 +1,24 @@ +name: Issue Manager + on: schedule: - - cron: "0 0 * * *" + - cron: "0 0 * * *" + issue_comment: + types: + - created + - edited + issues: + types: + - labeled jobs: issue-manager: runs-on: ubuntu-latest steps: - - uses: tiangolo/issue-manager@master - with: - token: ${{ secrets.GITHUB_TOKEN }} - config: > + - uses: tiangolo/issue-manager@0.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + config: > { "answered": { "users": ["tiangolo", "dmontagu"], diff --git a/docs/en/docs/advanced/behind-a-proxy.md b/docs/en/docs/advanced/behind-a-proxy.md new file mode 100644 index 000000000..660e374a4 --- /dev/null +++ b/docs/en/docs/advanced/behind-a-proxy.md @@ -0,0 +1,281 @@ +# Behind a Proxy + +In some situations, you might need to use a **proxy** server like Traefik or Nginx with a configuration that adds an extra path prefix that is not seen by your application. + +In these cases you can use `root_path` to configure your application. + +The `root_path` is a mechanism provided by the ASGI specification (that FastAPI is built on, through Starlette). + +The `root_path` is used to handle these specific cases. + +And it's also used internally when mounting sub-applications. + +## Proxy with a stripped path prefix + +Having a proxy with a stripped path prefix, in this case, means that you could declare a path at `/app` in your code, but then, you add a layer on top (the proxy) that would put your **FastAPI** application under a path like `/api/v1`. + +In this case, the original path `/app` would actually be served at `/api/v1/app`. + +Even though all your code is written assuming there's just `/app`. + +And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to Uvicorn, keep your application convinced that it is serving at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`. + +Up to here, everything would work as normally. + +But then, when you open the integrated docs UI (the frontend), it would expect to get the OpenAPI schema at `/openapi.json`, instead of `/api/v1/openapi.json`. + +So, the frontend (that runs in the browser) would try to reach `/openapi.json` and wouldn't be able to get the OpenAPI schema. + +Because we have a proxy with a path prefix of `/api/v1` for our app, the frontend needs to fetch the OpenAPI schema at `/api/v1/openapi.json`. + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +!!! tip + The IP `0.0.0.0` is commonly used to mean that the program listens on all the IPs available in that machine/server. + +The docs UI would also need that the JSON payload with the OpenAPI schema has the path defined as `/api/v1/app` (behind the proxy) instead of `/app`. For example, something like: + +```JSON hl_lines="5" +{ + "openapi": "3.0.2", + // More stuff here + "paths": { + "/api/v1/app": { + // More stuff here + } + } +} +``` + +In this example, the "Proxy" could be something like **Traefik**. And the server would be something like **Uvicorn**, running your FastAPI application. + +### Providing the `root_path` + +To achieve this, you can use the command line option `--root-path` like: + +
+
+But if we access the docs UI at the "official" URL using the proxy, at `/api/v1/docs`, it works correctly! 🎉
+
+Right as we wanted it. ✔️
+
+This is because FastAPI uses this `root_path` internally to tell the docs UI to use the URL for OpenAPI with the path prefix provided by `root_path`.
+
+You can check it at http://127.0.0.1:9999/api/v1/docs:
+
+
+
+## Mounting a sub-application
+
+If you need to mount a sub-application (as described in [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}) while also using a proxy with `root_path`, you can do it normally, as you would expect.
+
+FastAPI will internally use the `root_path` smartly, so it will just work. ✨
diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md
index 545a84436..f753cc300 100644
--- a/docs/en/docs/advanced/custom-response.md
+++ b/docs/en/docs/advanced/custom-response.md
@@ -203,6 +203,21 @@ File responses will include appropriate `Content-Length`, `Last-Modified` and `E
{!../../../docs_src/custom_response/tutorial009.py!}
```
+## Default response class
+
+When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
+
+The parameter that defines this is `default_response_class`.
+
+In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
+
+```Python hl_lines="2 4"
+{!../../../docs_src/custom_response/tutorial010.py!}
+```
+
+!!! tip
+ You can still override `response_class` in *path operations* as before.
+
## Additional documentation
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}.
diff --git a/docs/en/docs/advanced/extending-openapi.md b/docs/en/docs/advanced/extending-openapi.md
index f98be49a6..30cd857d5 100644
--- a/docs/en/docs/advanced/extending-openapi.md
+++ b/docs/en/docs/advanced/extending-openapi.md
@@ -52,15 +52,22 @@ First, write all your **FastAPI** application as normally:
Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
-```Python hl_lines="2 15 16 17 18 19 20"
+```Python hl_lines="2 15 16 17 18 19 20 21"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
+!!! tip
+ The `openapi_prefix` will contain any prefix needed for the generated OpenAPI *path operations*.
+
+ FastAPI will automatically use the `root_path` to pass it in the `openapi_prefix`.
+
+ But the important thing is that your function should receive that parameter `openapi_prefix` and pass it along.
+
### Modify the OpenAPI schema
Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
-```Python hl_lines="21 22 23"
+```Python hl_lines="22 23 24"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
@@ -72,7 +79,7 @@ That way, your application won't have to generate the schema every time a user o
It will be generated only once, and then the same cached schema will be used for the next requests.
-```Python hl_lines="13 14 24 25"
+```Python hl_lines="13 14 25 26"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
@@ -80,7 +87,7 @@ It will be generated only once, and then the same cached schema will be used for
Now you can replace the `.openapi()` method with your new function.
-```Python hl_lines="28"
+```Python hl_lines="29"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
diff --git a/docs/en/docs/advanced/sub-applications-proxy.md b/docs/en/docs/advanced/sub-applications-proxy.md
deleted file mode 100644
index 03a7f9446..000000000
--- a/docs/en/docs/advanced/sub-applications-proxy.md
+++ /dev/null
@@ -1,100 +0,0 @@
-# Sub Applications - Behind a Proxy, Mounts
-
-There are at least two situations where you could need to create your **FastAPI** application using some specific paths.
-
-But then you need to set them up to be served with a path prefix.
-
-It could happen if you have a:
-
-* **Proxy** server.
-* You are "**mounting**" a FastAPI application inside another FastAPI application (or inside another ASGI application, like Starlette).
-
-## Proxy
-
-Having a proxy in this case means that you could declare a path at `/app`, but then, you could need to add a layer on top (the Proxy) that would put your **FastAPI** application under a path like `/api/v1`.
-
-In this case, the original path `/app` will actually be served at `/api/v1/app`.
-
-Even though your application "thinks" it is serving at `/app`.
-
-And the Proxy could be re-writing the path "on the fly" to keep your application convinced that it is serving at `/app`.
-
-Up to here, everything would work as normally.
-
-But then, when you open the integrated docs, they would expect to get the OpenAPI schema at `/openapi.json`, instead of `/api/v1/openapi.json`.
-
-So, the frontend (that runs in the browser) would try to reach `/openapi.json` and wouldn't be able to get the OpenAPI schema.
-
-So, it's needed that the frontend looks for the OpenAPI schema at `/api/v1/openapi.json`.
-
-And it's also needed that the returned JSON OpenAPI schema has the defined path at `/api/v1/app` (behind the proxy) instead of `/app`.
-
----
-
-For these cases, you can declare an `openapi_prefix` parameter in your `FastAPI` application.
-
-See the section below, about "mounting", for an example.
-
-## Mounting a **FastAPI** application
-
-"Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
-
-You could want to do this if you have several "independent" applications that you want to separate, having their own independent OpenAPI schema and user interfaces.
-
-### Top-level application
-
-First, create the main, top-level, **FastAPI** application, and its *path operations*:
-
-```Python hl_lines="3 6 7 8"
-{!../../../docs_src/sub_applications/tutorial001.py!}
-```
-
-### Sub-application
-
-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".
-
-When creating the sub-application, use the parameter `openapi_prefix`. In this case, with a prefix of `/subapi`:
-
-```Python hl_lines="11 14 15 16"
-{!../../../docs_src/sub_applications/tutorial001.py!}
-```
-
-### Mount the sub-application
-
-In your top-level application, `app`, mount the sub-application, `subapi`.
-
-Here you need to make sure you use the same path that you used for the `openapi_prefix`, in this case, `/subapi`:
-
-```Python hl_lines="11 19"
-{!../../../docs_src/sub_applications/tutorial001.py!}
-```
-
-## Check the automatic API docs
-
-Now, run `uvicorn`, if your file is at `main.py`, it would be:
-
-
-
-And then, open the docs for the sub-application, at http://127.0.0.1:8000/subapi/docs.
-
-You will see the automatic API docs for the sub-application, including only its own sub-paths, with their correct prefix:
-
-
-
-If you try interacting with any of the two user interfaces, they will work, because the browser will be able to talk to the correct path (or sub-path).
diff --git a/docs/en/docs/advanced/sub-applications.md b/docs/en/docs/advanced/sub-applications.md
new file mode 100644
index 000000000..68d5790db
--- /dev/null
+++ b/docs/en/docs/advanced/sub-applications.md
@@ -0,0 +1,73 @@
+# Sub Applications - Mounts
+
+If you need to have two independent FastAPI applications, with their own independent OpenAPI and their own docs UIs, you can have a main app and "mount" one (or more) sub-application(s).
+
+## Mounting a **FastAPI** application
+
+"Mounting" means adding a completely "independent" application in a specific path, that then takes care of handling all everything under that path, with the _path operations_ declared in that sub-application.
+
+### Top-level application
+
+First, create the main, top-level, **FastAPI** application, and its *path operations*:
+
+```Python hl_lines="3 6 7 8"
+{!../../../docs_src/sub_applications/tutorial001.py!}
+```
+
+### Sub-application
+
+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":
+
+```Python hl_lines="11 14 15 16"
+{!../../../docs_src/sub_applications/tutorial001.py!}
+```
+
+### Mount the sub-application
+
+In your top-level application, `app`, mount the sub-application, `subapi`.
+
+In this case, it will be mounted at the path `/subapi`:
+
+```Python hl_lines="11 19"
+{!../../../docs_src/sub_applications/tutorial001.py!}
+```
+
+### Check the automatic API docs
+
+Now, run `uvicorn` with the main app, if your file is `main.py`, it would be:
+
+
+
+And then, open the docs for the sub-application, at http://127.0.0.1:8000/subapi/docs.
+
+You will see the automatic API docs for the sub-application, including only its own _path operations_, all under the correct sub-path prefix `/subapi`:
+
+
+
+If you try interacting with any of the two user interfaces, they will work correctly, because the browser will be able to talk to each specific app or sub-app.
+
+### Technical Details: `root_path`
+
+When you mount a sub-application as described above, FastAPI will take care of communicating the mount path for the sub-application using a mechanism from the ASGI specification called a `root_path`.
+
+That way, the sub-application will know to use that path prefix for the docs UI.
+
+And the sub-application could also have its own mounted sub-applications and everything would work correctly, because FastAPI handles all these `root_path`s automatically.
+
+You will learn more about the `root_path` and how to use it explicitly in the section about [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank}.
diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md
index d473cef07..6cacc2e6f 100644
--- a/docs/en/docs/advanced/websockets.md
+++ b/docs/en/docs/advanced/websockets.md
@@ -51,38 +51,7 @@ In your WebSocket route you can `await` for messages and send messages.
You can receive and send binary, text, and JSON data.
-## Using `Depends` and others
-
-In WebSocket endpoints you can import from `fastapi` and use:
-
-* `Depends`
-* `Security`
-* `Cookie`
-* `Header`
-* `Path`
-* `Query`
-
-They work the same way as for other FastAPI endpoints/*path operations*:
-
-```Python hl_lines="53 54 55 56 57 58 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76"
-{!../../../docs_src/websockets/tutorial002.py!}
-```
-
-!!! info
- In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
-
- You can use a closing code from the valid codes defined in the specification.
-
- In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the PR #527 in Starlette.
-
-## More info
-
-To learn more about the options, check Starlette's documentation for:
-
-* The `WebSocket` class.
-* Class-based WebSocket handling.
-
-## Test it
+## Try it
If your file is named `main.py`, run your application with:
@@ -115,3 +84,62 @@ You can send (and receive) many messages:
And all of them will use the same WebSocket connection.
+
+## Using `Depends` and others
+
+In WebSocket endpoints you can import from `fastapi` and use:
+
+* `Depends`
+* `Security`
+* `Cookie`
+* `Header`
+* `Path`
+* `Query`
+
+They work the same way as for other FastAPI endpoints/*path operations*:
+
+```Python hl_lines="56 57 58 59 60 61 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79"
+{!../../../docs_src/websockets/tutorial002.py!}
+```
+
+!!! info
+ In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
+
+ You can use a closing code from the valid codes defined in the specification.
+
+ In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the PR #527 in Starlette.
+
+### Try the WebSockets with dependencies
+
+If your file is named `main.py`, run your application with:
+
+
+
+## More info
+
+To learn more about the options, check Starlette's documentation for:
+
+* The `WebSocket` class.
+* Class-based WebSocket handling.
diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css
index 94bdbed43..b7de5e34e 100644
--- a/docs/en/docs/css/custom.css
+++ b/docs/en/docs/css/custom.css
@@ -11,3 +11,8 @@ a.internal-link::after {
*/
content: "\00A0↪";
}
+
+/* Give space to lower icons so Gitter chat doesn't get on top of them */
+.md-footer-meta {
+ padding-bottom: 2em;
+}
diff --git a/docs/en/docs/external-links.md b/docs/en/docs/external-links.md
index 34ba30e0a..a3c79a8d2 100644
--- a/docs/en/docs/external-links.md
+++ b/docs/en/docs/external-links.md
@@ -25,8 +25,6 @@ Here's an incomplete list of some of them.
* FastAPI authentication revisited: Enabling API key authentication by Nils de Bruin.
-* FastAPI, a simple use case on logging by @euri10.
-
* Deploying a scikit-learn model with ONNX and FastAPI by Nico Axtmann.
* Top 5 Asynchronous Web Frameworks for Python by Ankush Thakur on GeekFlare.
@@ -104,12 +102,6 @@ Here's an incomplete list of some of them.
* [FastAPI] Python製のASGI Web フレームワーク FastAPIに入門する by @bee2.
-### Chinese
-
-* 使用FastAPI框架快速构建高性能的api服务 by 逍遥散人.
-
-* FastAPI框架中文文档 by 何大仙.
-
### Vietnamese
* FASTAPI: TRIỂN KHAI BẰNG DOCKER by Nguyễn Nhân.
diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md
index c1a7d918a..aed3ed6f6 100644
--- a/docs/en/docs/help-fastapi.md
+++ b/docs/en/docs/help-fastapi.md
@@ -12,28 +12,18 @@ And there are several ways to get help too.
## Star **FastAPI** in GitHub
-You can "star" FastAPI in GitHub (clicking the star button at the top right): https://github.com/tiangolo/fastapi.
+You can "star" FastAPI in GitHub (clicking the star button at the top right): https://github.com/tiangolo/fastapi. ⭐️
By adding a star, other users will be able to find it more easily and see that it has been already useful for others.
## Watch the GitHub repository for releases
-You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): https://github.com/tiangolo/fastapi.
+You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): https://github.com/tiangolo/fastapi. 👀
There you can select "Releases only".
Doing it, you will receive notifications (in your email) whenever there's a new release (a new version) of **FastAPI** with bug fixes and new features.
-## Join the chat
-
-
-
+Without types, that's almost impossible to achieve.
+
Notice that the variable `item` is one of the elements in the list `items`.
And still, the editor knows it is a `str`, and provides support for that.
-#### Tuples and Sets
+#### `Tuple` and `Set`
You would do the same to declare `tuple`s and `set`s:
@@ -197,13 +202,13 @@ This means:
* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
* The variable `items_s` is a `set`, and each of its items is of type `bytes`.
-#### Dicts
+#### `Dict`
-To define a `dict`, you pass 2 subtypes, separated by commas.
+To define a `dict`, you pass 2 type parameters, separated by commas.
-The first subtype is for the keys of the `dict`.
+The first type parameter is for the keys of the `dict`.
-The second subtype is for the values of the `dict`:
+The second type parameter is for the values of the `dict`:
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
@@ -215,6 +220,29 @@ 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).
+#### `Optional`
+
+You can also use `Optional` to declare that a variable has a type, like `str`, but that it is "optional", which means that it could also be `None`:
+
+```Python hl_lines="1 4"
+{!../../../docs_src/python_types/tutorial009.py!}
+```
+
+Using `Optional[str]` instead of just `str` will let the editor help you detecting errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
+
+#### Generic types
+
+These types that take type parameters in square brackets, like:
+
+* `List`
+* `Tuple`
+* `Set`
+* `Dict`
+* `Optional`
+* ...and others.
+
+are called **Generic types** or **Generics**.
+
### Classes as types
You can also declare a class as the type of a variable.
@@ -222,13 +250,13 @@ You can also declare a class as the type of a variable.
Let's say you have a class `Person`, with a name:
```Python hl_lines="1 2 3"
-{!../../../docs_src/python_types/tutorial009.py!}
+{!../../../docs_src/python_types/tutorial010.py!}
```
Then you can declare a variable to be of type `Person`:
```Python hl_lines="6"
-{!../../../docs_src/python_types/tutorial009.py!}
+{!../../../docs_src/python_types/tutorial010.py!}
```
And then, again, you get all the editor support:
@@ -250,7 +278,7 @@ And you get all the editor support with that resulting object.
Taken from the official Pydantic docs:
```Python
-{!../../../docs_src/python_types/tutorial010.py!}
+{!../../../docs_src/python_types/tutorial011.py!}
```
!!! info
diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md
index 09f6b2a83..b0e3797b6 100644
--- a/docs/en/docs/release-notes.md
+++ b/docs/en/docs/release-notes.md
@@ -2,6 +2,60 @@
## Latest changes
+## 0.57.0
+
+* Remove broken link from "External Links". PR [#1565](https://github.com/tiangolo/fastapi/pull/1565) by [@victorphoenix3](https://github.com/victorphoenix3).
+* Update/fix docs for [WebSockets with dependencies](https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others). Original PR [#1540](https://github.com/tiangolo/fastapi/pull/1540) by [@ChihSeanHsu](https://github.com/ChihSeanHsu).
+* Add support for Python's `http.HTTPStatus` in `status_code` parameters. PR [#1534](https://github.com/tiangolo/fastapi/pull/1534) by [@retnikt](https://github.com/retnikt).
+* When using Pydantic models with `__root__`, use the internal value in `jsonable_encoder`. PR [#1524](https://github.com/tiangolo/fastapi/pull/1524) by [@patrickkwang](https://github.com/patrickkwang).
+* Update docs for path parameters. PR [#1521](https://github.com/tiangolo/fastapi/pull/1521) by [@yankeexe](https://github.com/yankeexe).
+* Update docs for first steps, links and rewording. PR [#1518](https://github.com/tiangolo/fastapi/pull/1518) by [@yankeexe](https://github.com/yankeexe).
+* Enable `showCommonExtensions` in Swagger UI to show additional validations like `maxLength`, etc. PR [#1466](https://github.com/tiangolo/fastapi/pull/1466) by [@TiewKH](https://github.com/TiewKH).
+* Make `OAuth2PasswordRequestFormStrict` importable directly from `fastapi.security`. PR [#1462](https://github.com/tiangolo/fastapi/pull/1462) by [@RichardHoekstra](https://github.com/RichardHoekstra).
+* Add docs about [Default response class](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). PR [#1455](https://github.com/tiangolo/fastapi/pull/1455) by [@TezRomacH](https://github.com/TezRomacH).
+* Add note in docs about additional parameters `response_model_exclude_defaults` and `response_model_exclude_none` in [Response Model](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). PR [#1427](https://github.com/tiangolo/fastapi/pull/1427) by [@wshayes](https://github.com/wshayes).
+* Add note about [PyCharm Pydantic plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin) to docs. PR [#1420](https://github.com/tiangolo/fastapi/pull/1420) by [@koxudaxi](https://github.com/koxudaxi).
+* Update and clarify testing function name. PR [#1395](https://github.com/tiangolo/fastapi/pull/1395) by [@chenl](https://github.com/chenl).
+* Fix duplicated headers created by indirect dependencies that use the request directly. PR [#1386](https://github.com/tiangolo/fastapi/pull/1386) by [@obataku](https://github.com/obataku) from tests by [@scottsmith2gmail](https://github.com/scottsmith2gmail).
+* Upgrade Starlette version to `0.13.4`. PR [#1361](https://github.com/tiangolo/fastapi/pull/1361) by [@rushton](https://github.com/rushton).
+* Improve error handling and feedback for requests with invalid JSON. PR [#1354](https://github.com/tiangolo/fastapi/pull/1354) by [@aviramha](https://github.com/aviramha).
+* Add support for declaring metadata for tags in OpenAPI. New docs at [Tutorial - Metadata and Docs URLs - Metadata for tags](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-tags). PR [#1348](https://github.com/tiangolo/fastapi/pull/1348) by [@thomas-maschler](https://github.com/thomas-maschler).
+* Add basic setup for Russian translations. PR [#1566](https://github.com/tiangolo/fastapi/pull/1566).
+* Remove obsolete Chinese articles after adding official community translations. PR [#1510](https://github.com/tiangolo/fastapi/pull/1510) by [@waynerv](https://github.com/waynerv).
+* Add `__repr__` for *path operation function* parameter helpers (like `Query`, `Depends`, etc) to simplify debugging. PR [#1560](https://github.com/tiangolo/fastapi/pull/1560) by [@rkbeatss](https://github.com/rkbeatss) and [@victorphoenix3](https://github.com/victorphoenix3).
+
+## 0.56.1
+
+* Add link to advanced docs from tutorial. PR [#1512](https://github.com/tiangolo/fastapi/pull/1512) by [@kx-chen](https://github.com/kx-chen).
+* Remove internal unnecessary f-strings. PR [#1526](https://github.com/tiangolo/fastapi/pull/1526) by [@kotamatsuoka](https://github.com/kotamatsuoka).
+* Add translation to Chinese for [Query Parameters and String Validations - 查询参数和字符串校验](https://fastapi.tiangolo.com/zh/tutorial/query-params-str-validations/). PR [#1500](https://github.com/tiangolo/fastapi/pull/1500) by [@waynerv](https://github.com/waynerv).
+* Add translation to Chinese for [Request Body - 请求体](https://fastapi.tiangolo.com/zh/tutorial/body/). PR [#1492](https://github.com/tiangolo/fastapi/pull/1492) by [@waynerv](https://github.com/waynerv).
+* Add translation to Chinese for [Help FastAPI - Get Help - 帮助 FastAPI - 获取帮助](https://fastapi.tiangolo.com/zh/help-fastapi/). PR [#1465](https://github.com/tiangolo/fastapi/pull/1465) by [@waynerv](https://github.com/waynerv).
+* Add translation to Chinese for [Query Parameters - 查询参数](https://fastapi.tiangolo.com/zh/tutorial/query-params/). PR [#1454](https://github.com/tiangolo/fastapi/pull/1454) by [@waynerv](https://github.com/waynerv).
+* Add translation to Chinese for [Contributing - 开发 - 贡献](https://fastapi.tiangolo.com/zh/contributing/). PR [#1460](https://github.com/tiangolo/fastapi/pull/1460) by [@waynerv](https://github.com/waynerv).
+* Add translation to Chinese for [Path Parameters - 路径参数](https://fastapi.tiangolo.com/zh/tutorial/path-params/). PR [#1453](https://github.com/tiangolo/fastapi/pull/1453) by [@waynerv](https://github.com/waynerv).
+* Add official Microsoft project generator for [serving spaCy with FastAPI and Azure Cognitive Skills](https://github.com/microsoft/cookiecutter-spacy-fastapi) to [Project Generators](https://fastapi.tiangolo.com/project-generation/). PR [#1390](https://github.com/tiangolo/fastapi/pull/1390) by [@kabirkhan](https://github.com/kabirkhan).
+* Update docs in [Python Types Intro](https://fastapi.tiangolo.com/python-types/) to include info about `Optional`. Original PR [#1377](https://github.com/tiangolo/fastapi/pull/1377) by [@yaegassy](https://github.com/yaegassy).
+* Fix support for callable class dependencies with `yield`. PR [#1365](https://github.com/tiangolo/fastapi/pull/1365) by [@mrosales](https://github.com/mrosales).
+* Fix/remove incorrect error logging when a client sends invalid payloads. PR [#1351](https://github.com/tiangolo/fastapi/pull/1351) by [@dbanty](https://github.com/dbanty).
+* Add translation to Chinese for [First Steps - 第一步](https://fastapi.tiangolo.com/zh/tutorial/first-steps/). PR [#1323](https://github.com/tiangolo/fastapi/pull/1323) by [@waynerv](https://github.com/waynerv).
+* Fix generating OpenAPI for apps using callbacks with routers including Pydantic models. PR [#1322](https://github.com/tiangolo/fastapi/pull/1322) by [@nsidnev](https://github.com/nsidnev).
+* Optimize internal regex performance in `get_path_param_names()`. PR [#1243](https://github.com/tiangolo/fastapi/pull/1243) by [@heckad](https://github.com/heckad).
+* Remove `*,` from functions in docs where it's not needed. PR [#1239](https://github.com/tiangolo/fastapi/pull/1239) by [@pankaj-giri](https://github.com/pankaj-giri).
+* Start translations for Italian. PR [#1557](https://github.com/tiangolo/fastapi/pull/1557) by [@csr](https://github.com/csr).
+
+## 0.56.0
+
+* Add support for ASGI `root_path`:
+ * Use `root_path` internally for mounted applications, so that OpenAPI and the docs UI works automatically without extra configurations and parameters.
+ * Add new `root_path` parameter for `FastAPI` applications to provide it in cases where it can be set with the command line (e.g. for Uvicorn and Hypercorn, with the parameter `--root-path`).
+ * Deprecate `openapi_prefix` parameter in favor of the new `root_path` parameter.
+ * Add new/updated docs for [Sub Applications - Mounts](https://fastapi.tiangolo.com/advanced/sub-applications/), without `openapi_prefix` (as it is now handled automatically).
+ * Add new/updated docs for [Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/), including how to setup a local testing proxy with Traefik and using `root_path`.
+ * Update docs for [Extending OpenAPI](https://fastapi.tiangolo.com/advanced/extending-openapi/) with the new `openapi_prefix` parameter passed (internally generated from `root_path`).
+ * Original PR [#1199](https://github.com/tiangolo/fastapi/pull/1199) by [@iksteen](https://github.com/iksteen).
+* Update new issue templates and docs: [Help FastAPI - Get Help](https://fastapi.tiangolo.com/help-fastapi/). PR [#1531](https://github.com/tiangolo/fastapi/pull/1531).
+* Update GitHub action issue-manager. PR [#1520](https://github.com/tiangolo/fastapi/pull/1520).
* Add new links:
* **English articles**:
* [Real-time Notifications with Python and Postgres](https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/) by [Guillermo Cruz](https://wuilly.com/).
diff --git a/docs/en/docs/tutorial/body.md b/docs/en/docs/tutorial/body.md
index 25b1fb6ba..b2cde0762 100644
--- a/docs/en/docs/tutorial/body.md
+++ b/docs/en/docs/tutorial/body.md
@@ -108,6 +108,17 @@ But you would get the same editor support with
+!!! tip
+ If you use PyCharm as your editor, you can use the Pydantic PyCharm Plugin.
+
+ It improves editor support for Pydantic models, with:
+
+ * auto-completion
+ * type checks
+ * refactoring
+ * searching
+ * inspections
+
## Use the model
Inside of the function, you can access all the attributes of the model object directly:
diff --git a/docs/en/docs/tutorial/first-steps.md b/docs/en/docs/tutorial/first-steps.md
index 11a9d16e0..6ca5f39eb 100644
--- a/docs/en/docs/tutorial/first-steps.md
+++ b/docs/en/docs/tutorial/first-steps.md
@@ -71,13 +71,13 @@ You will see the alternative automatic documentation (provided by OpenAPI is a specification that dictates how to define a schema of your API.
-This OpenAPI schema would include your API paths, the possible parameters they take, etc.
+This schema definition includes your API paths, the possible parameters they take, etc.
#### Data "schema"
@@ -91,7 +91,7 @@ OpenAPI defines an API schema for your API. And that schema includes definitions
#### Check the `openapi.json`
-If you are curious about how the raw OpenAPI schema looks like, it is just an automatically generated JSON with the descriptions of all your API.
+If you are curious about how the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API.
You can see it directly at: http://127.0.0.1:8000/openapi.json.
@@ -120,7 +120,7 @@ It will show a JSON starting with something like:
#### What is OpenAPI for
-This OpenAPI schema is what powers the 2 interactive documentation systems included.
+The OpenAPI schema is what powers the two interactive documentation systems included.
And there are dozens of alternatives, all based on OpenAPI. You could easily add any of those alternatives to your application built with **FastAPI**.
@@ -139,7 +139,7 @@ You could also use it to generate code automatically, for clients that communica
!!! note "Technical Details"
`FastAPI` is a class that inherits directly from `Starlette`.
- You can use all the Starlette functionality with `FastAPI` too.
+ You can use all the Starlette functionality with `FastAPI` too.
### Step 2: create a `FastAPI` "instance"
@@ -202,7 +202,7 @@ https://example.com/items/foo
!!! info
A "path" is also commonly called an "endpoint" or a "route".
-Building an API, the "path" is the main way to separate "concerns" and "resources".
+While building an API, the "path" is the main way to separate "concerns" and "resources".
#### Operation
@@ -281,7 +281,7 @@ And the more exotic ones:
The information here is presented as a guideline, not a requirement.
- For example, when using GraphQL you normally perform all the actions using only `post`.
+ For example, when using GraphQL you normally perform all the actions using only `POST` operations.
### Step 4: define the **path operation function**
@@ -297,7 +297,7 @@ This is our "**path operation function**":
This is a Python function.
-It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using `GET`.
+It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using a `GET` operation.
In this case, it is an `async` function.
diff --git a/docs/en/docs/tutorial/metadata.md b/docs/en/docs/tutorial/metadata.md
index 666fa7648..25c00db70 100644
--- a/docs/en/docs/tutorial/metadata.md
+++ b/docs/en/docs/tutorial/metadata.md
@@ -21,6 +21,58 @@ With this configuration, the automatic API docs would look like:
+## Metadata for tags
+
+You can also add additional metadata for the different tags used to group your path operations with the parameter `openapi_tags`.
+
+It takes a list containing one dictionary for each tag.
+
+Each dictionary can contain:
+
+* `name` (**required**): a `str` with the same tag name you use in the `tags` parameter in your *path operations* and `APIRouter`s.
+* `description`: a `str` with a short description for the tag. It can have Markdown and will be shown in the docs UI.
+* `externalDocs`: a `dict` describing external documentation with:
+ * `description`: a `str` with a short description for the external docs.
+ * `url` (**required**): a `str` with the URL for the external documentation.
+
+### Create metadata for tags
+
+Let's try that in an example with tags for `users` and `items`.
+
+Create metadata for your tags and pass it to the `openapi_tags` parameter:
+
+```Python hl_lines="3 4 5 6 7 8 9 10 11 12 13 14 15 16 18"
+{!../../../docs_src/metadata/tutorial004.py!}
+```
+
+Notice that you can use Markdown inside of the descriptions, for example "login" will be shown in bold (**login**) and "fancy" will be shown in italics (_fancy_).
+
+!!! tip
+ You don't have to add metadata for all the tags that you use.
+
+### Use your tags
+
+Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assign them to different tags:
+
+```Python hl_lines="21 26"
+{!../../../docs_src/metadata/tutorial004.py!}
+```
+
+!!! info
+ Read more about tags in [Path Operation Configuration](../path-operation-configuration/#tags){.internal-link target=_blank}.
+
+### Check the docs
+
+Now, if you check the docs, they will show all the additional metadata:
+
+
+
+### Order of tags
+
+The order of each tag metadata dictionary also defines the order shown in the docs UI.
+
+For example, even though `users` would go after `items` in alphabetical order, it is shown before them, because we added their metadata as the first dictionary in the list.
+
## OpenAPI URL
By default, the OpenAPI schema is served at `/openapi.json`.
diff --git a/docs/en/docs/tutorial/path-params.md b/docs/en/docs/tutorial/path-params.md
index 1c32108bb..77c5c02e2 100644
--- a/docs/en/docs/tutorial/path-params.md
+++ b/docs/en/docs/tutorial/path-params.md
@@ -85,7 +85,7 @@ And when you open your browser at OpenAPI standard, there are many compatible tools.
-Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc):
+Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc), which you can access at http://127.0.0.1:8000/redoc:
@@ -125,7 +125,7 @@ Import `Enum` and create a sub-class that inherits from `str` and from `Enum`.
By inheriting from `str` the API docs will be able to know that the values must be of type `string` and will be able to render correctly.
-And create class attributes with fixed values, those fixed values will be the available valid values:
+Then create class attributes with fixed values, which will be the available valid values:
```Python hl_lines="1 6 7 8 9"
{!../../../docs_src/path_params/tutorial005.py!}
@@ -147,7 +147,7 @@ Then create a *path parameter* with a type annotation using the enum class you c
### Check the docs
-Because the available values for the *path parameter* are specified, the interactive docs can show them nicely:
+Because the available values for the *path parameter* are predefined, the interactive docs can show them nicely:
@@ -167,7 +167,7 @@ You can compare it with the *enumeration member* in your created enum `ModelName
You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
-```Python hl_lines="19"
+```Python hl_lines="20"
{!../../../docs_src/path_params/tutorial005.py!}
```
@@ -178,12 +178,21 @@ You can get the actual value (a `str` in this case) using `model_name.value`, or
You can return *enum members* from your *path operation*, even nested in a JSON body (e.g. a `dict`).
-They will be converted to their corresponding values before returning them to the client:
+They will be converted to their corresponding values (strings in this case) before returning them to the client:
-```Python hl_lines="18 20 21"
+```Python hl_lines="18 21 23"
{!../../../docs_src/path_params/tutorial005.py!}
```
+In your client you will get a JSON response like:
+
+```JSON
+{
+ "model_name": "alexnet",
+ "message": "Deep Learning FTW!"
+}
+```
+
## Path parameters containing paths
Let's say you have a *path operation* with a path `/files/{file_path}`.
diff --git a/docs/en/docs/tutorial/response-model.md b/docs/en/docs/tutorial/response-model.md
index 9dd0b6dee..dd76eca6e 100644
--- a/docs/en/docs/tutorial/response-model.md
+++ b/docs/en/docs/tutorial/response-model.md
@@ -124,6 +124,14 @@ So, if you send a request to that *path operation* for the item with ID `foo`, t
!!! info
FastAPI uses Pydantic model's `.dict()` with its `exclude_unset` parameter to achieve this.
+!!! info
+ You can also use:
+
+ * `response_model_exclude_defaults=True`
+ * `response_model_exclude_none=True`
+
+ as described in the Pydantic docs for `exclude_defaults` and `exclude_none`.
+
#### Data with values for fields with defaults
But if your data has values for the model's fields with default values, like the item with ID `bar`:
diff --git a/docs/en/docs/tutorial/response-status-code.md b/docs/en/docs/tutorial/response-status-code.md
index 29b8521fc..7915624fa 100644
--- a/docs/en/docs/tutorial/response-status-code.md
+++ b/docs/en/docs/tutorial/response-status-code.md
@@ -17,6 +17,9 @@ The same way you can specify a response model, you can also declare the HTTP sta
The `status_code` parameter receives a number with the HTTP status code.
+!!! info
+ `status_code` can alternatively also receive an `IntEnum`, such as Python's `http.HTTPStatus`.
+
It will:
* Return that status code in the response.
@@ -83,4 +86,4 @@ They are just a convenience, they hold the same number, but that way you can use
## Changing the default
-Later, in the **Advanced User Guide**, you will see how to return a different status code than the default you are declaring here.
+Later, in the [Advanced User Guide](../advanced/response-change-status-code.md){.internal-link target=_blank}, you will see how to return a different status code than the default you are declaring here.
diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md
index 70c3d1846..8a497ccd5 100644
--- a/docs/en/docs/tutorial/schema-extra-example.md
+++ b/docs/en/docs/tutorial/schema-extra-example.md
@@ -33,7 +33,7 @@ The same way you can pass extra info to `Field`, you can do the same with `Path`
For example, you can pass an `example` for a body request to `Body`:
-```Python hl_lines="20 21 22 23 24 25"
+```Python hl_lines="19 20 21 22 23 24"
{!../../../docs_src/schema_extra_example/tutorial003.py!}
```
diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml
index abbe25450..26826c573 100644
--- a/docs/en/mkdocs.yml
+++ b/docs/en/mkdocs.yml
@@ -23,7 +23,9 @@ nav:
- en: /
- es: /es/
- ja: /ja/
+ - it: /it/
- pt: /pt/
+ - ru: /ru/
- zh: /zh/
- features.md
- python-types.md
@@ -93,7 +95,8 @@ nav:
- advanced/sql-databases-peewee.md
- advanced/async-sql-databases.md
- advanced/nosql-databases.md
- - advanced/sub-applications-proxy.md
+ - advanced/sub-applications.md
+ - advanced/behind-a-proxy.md
- advanced/templates.md
- advanced/graphql.md
- advanced/websockets.md
diff --git a/docs/es/mkdocs.yml b/docs/es/mkdocs.yml
index e87262b69..1c7bfc68e 100644
--- a/docs/es/mkdocs.yml
+++ b/docs/es/mkdocs.yml
@@ -23,7 +23,9 @@ nav:
- en: /
- es: /es/
- ja: /ja/
+ - it: /it/
- pt: /pt/
+ - ru: /ru/
- zh: /zh/
- features.md
- python-types.md
diff --git a/docs/it/docs/index.md b/docs/it/docs/index.md
new file mode 100644
index 000000000..20dd403ab
--- /dev/null
+++ b/docs/it/docs/index.md
@@ -0,0 +1,447 @@
+
+{!../../../docs/missing-translation.md!}
+
+
+
++ FastAPI framework, high performance, easy to learn, fast to code, ready for production +
+ + +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/tiangolo/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. + +The key features are: + +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). + +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion 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. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Opinions + +"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" + +async def...uvicorn main:app --reload...ujson - for faster JSON "parsing".
+* email_validator - for email validation.
+
+Used by Starlette:
+
+* requests - Required if you want to use the `TestClient`.
+* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`.
+* jinja2 - Required if you want to use the default template configuration.
+* python-multipart - Required if you want to support form "parsing", with `request.form()`.
+* itsdangerous - Required for `SessionMiddleware` support.
+* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
+* graphene - Required for `GraphQLApp` support.
+* ujson - Required if you want to use `UJSONResponse`.
+
+Used by FastAPI / Starlette:
+
+* uvicorn - for the server that loads and serves your application.
+* orjson - Required if you want to use `ORJSONResponse`.
+
+You can install all of these with `pip install fastapi[all]`.
+
+## License
+
+This project is licensed under the terms of the MIT license.
diff --git a/docs/it/mkdocs.yml b/docs/it/mkdocs.yml
new file mode 100644
index 000000000..0341f88a9
--- /dev/null
+++ b/docs/it/mkdocs.yml
@@ -0,0 +1,67 @@
+site_name: FastAPI
+site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
+site_url: https://fastapi.tiangolo.com/it/
+theme:
+ name: material
+ palette:
+ primary: teal
+ accent: amber
+ icon:
+ repo: fontawesome/brands/github-alt
+ logo: https://fastapi.tiangolo.com/img/icon-white.svg
+ favicon: https://fastapi.tiangolo.com/img/favicon.png
+ language: it
+repo_name: tiangolo/fastapi
+repo_url: https://github.com/tiangolo/fastapi
+edit_uri: ''
+google_analytics:
+- UA-133183413-1
+- auto
+nav:
+- FastAPI: index.md
+- Languages:
+ - en: /
+ - es: /es/
+ - it: /it/
+ - pt: /pt/
+ - ru: /ru/
+ - zh: /zh/
+markdown_extensions:
+- toc:
+ permalink: true
+- markdown.extensions.codehilite:
+ guess_lang: false
+- markdown_include.include:
+ base_path: docs
+- admonition
+- codehilite
+- extra
+- pymdownx.superfences:
+ custom_fences:
+ - name: mermaid
+ class: mermaid
+ format: !!python/name:pymdownx.superfences.fence_div_format ''
+- pymdownx.tabbed
+extra:
+ social:
+ - icon: fontawesome/brands/github-alt
+ link: https://github.com/tiangolo/typer
+ - icon: fontawesome/brands/twitter
+ link: https://twitter.com/tiangolo
+ - icon: fontawesome/brands/linkedin
+ link: https://www.linkedin.com/in/tiangolo
+ - icon: fontawesome/brands/dev
+ link: https://dev.to/tiangolo
+ - icon: fontawesome/brands/medium
+ link: https://medium.com/@tiangolo
+ - icon: fontawesome/solid/globe
+ link: https://tiangolo.com
+extra_css:
+- https://fastapi.tiangolo.com/css/termynal.css
+- https://fastapi.tiangolo.com/css/custom.css
+extra_javascript:
+- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
+- https://fastapi.tiangolo.com/js/termynal.js
+- https://fastapi.tiangolo.com/js/custom.js
+- https://fastapi.tiangolo.com/js/chat.js
+- https://sidecar.gitter.im/dist/sidecar.v1.js
diff --git a/docs/pt/mkdocs.yml b/docs/pt/mkdocs.yml
index d54ac1c9d..c72777b33 100644
--- a/docs/pt/mkdocs.yml
+++ b/docs/pt/mkdocs.yml
@@ -23,7 +23,9 @@ nav:
- en: /
- es: /es/
- ja: /ja/
+ - it: /it/
- pt: /pt/
+ - ru: /ru/
- zh: /zh/
- features.md
- Tutorial - Guia de Usuário:
diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md
new file mode 100644
index 000000000..20dd403ab
--- /dev/null
+++ b/docs/ru/docs/index.md
@@ -0,0 +1,447 @@
+
+{!../../../docs/missing-translation.md!}
+
+
+
++ FastAPI framework, high performance, easy to learn, fast to code, ready for production +
+ + +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/tiangolo/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. + +The key features are: + +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). + +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion 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. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Opinions + +"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" + +async def...uvicorn main:app --reload...ujson - for faster JSON "parsing".
+* email_validator - for email validation.
+
+Used by Starlette:
+
+* requests - Required if you want to use the `TestClient`.
+* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`.
+* jinja2 - Required if you want to use the default template configuration.
+* python-multipart - Required if you want to support form "parsing", with `request.form()`.
+* itsdangerous - Required for `SessionMiddleware` support.
+* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
+* graphene - Required for `GraphQLApp` support.
+* ujson - Required if you want to use `UJSONResponse`.
+
+Used by FastAPI / Starlette:
+
+* uvicorn - for the server that loads and serves your application.
+* orjson - Required if you want to use `ORJSONResponse`.
+
+You can install all of these with `pip install fastapi[all]`.
+
+## License
+
+This project is licensed under the terms of the MIT license.
diff --git a/docs/ru/mkdocs.yml b/docs/ru/mkdocs.yml
new file mode 100644
index 000000000..d50359397
--- /dev/null
+++ b/docs/ru/mkdocs.yml
@@ -0,0 +1,67 @@
+site_name: FastAPI
+site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
+site_url: https://fastapi.tiangolo.com/ru/
+theme:
+ name: material
+ palette:
+ primary: teal
+ accent: amber
+ icon:
+ repo: fontawesome/brands/github-alt
+ logo: https://fastapi.tiangolo.com/img/icon-white.svg
+ favicon: https://fastapi.tiangolo.com/img/favicon.png
+ language: ru
+repo_name: tiangolo/fastapi
+repo_url: https://github.com/tiangolo/fastapi
+edit_uri: ''
+google_analytics:
+- UA-133183413-1
+- auto
+nav:
+- FastAPI: index.md
+- Languages:
+ - en: /
+ - es: /es/
+ - it: /it/
+ - pt: /pt/
+ - ru: /ru/
+ - zh: /zh/
+markdown_extensions:
+- toc:
+ permalink: true
+- markdown.extensions.codehilite:
+ guess_lang: false
+- markdown_include.include:
+ base_path: docs
+- admonition
+- codehilite
+- extra
+- pymdownx.superfences:
+ custom_fences:
+ - name: mermaid
+ class: mermaid
+ format: !!python/name:pymdownx.superfences.fence_div_format ''
+- pymdownx.tabbed
+extra:
+ social:
+ - icon: fontawesome/brands/github-alt
+ link: https://github.com/tiangolo/typer
+ - icon: fontawesome/brands/twitter
+ link: https://twitter.com/tiangolo
+ - icon: fontawesome/brands/linkedin
+ link: https://www.linkedin.com/in/tiangolo
+ - icon: fontawesome/brands/dev
+ link: https://dev.to/tiangolo
+ - icon: fontawesome/brands/medium
+ link: https://medium.com/@tiangolo
+ - icon: fontawesome/solid/globe
+ link: https://tiangolo.com
+extra_css:
+- https://fastapi.tiangolo.com/css/termynal.css
+- https://fastapi.tiangolo.com/css/custom.css
+extra_javascript:
+- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
+- https://fastapi.tiangolo.com/js/termynal.js
+- https://fastapi.tiangolo.com/js/custom.js
+- https://fastapi.tiangolo.com/js/chat.js
+- https://sidecar.gitter.im/dist/sidecar.v1.js
diff --git a/docs/zh/docs/contributing.md b/docs/zh/docs/contributing.md
new file mode 100644
index 000000000..e9645392e
--- /dev/null
+++ b/docs/zh/docs/contributing.md
@@ -0,0 +1,510 @@
+# 开发 - 贡献
+
+首先,你最好先了解 [帮助 FastAPI 及获取帮助](help-fastapi.md){.internal-link target=_blank}的基本方式。
+
+## 开发
+
+如果你已经克隆了源码仓库,并且需要深入研究代码,下面是设置开发环境的指南。
+
+### 通过 `venv` 管理虚拟环境
+
+你可以使用 Python 的 `venv` 模块在一个目录中创建虚拟环境:
+
+
+
+而且还将在每一个需要它们的*路径操作*的 API 文档中使用:
+
+
+
+## 编辑器支持
+
+在你的编辑器中,你会在函数内部的任意地方得到类型提示和代码补全(如果你接收的是一个 `dict` 而不是 Pydantic 模型,则不会发生这种情况):
+
+
+
+你还会获得对不正确的类型操作的错误检查:
+
+
+
+这并非偶然,整个框架都是围绕该设计而构建。
+
+并且在进行任何实现之前,已经在设计阶段经过了全面测试,以确保它可以在所有的编辑器中生效。
+
+Pydantic 本身甚至也进行了一些更改以支持此功能。
+
+上面的截图取自 Visual Studio Code。
+
+但是在 PyCharm 和绝大多数其他 Python 编辑器中你也会获得同样的编辑器支持:
+
+
+
+## 使用模型
+
+在函数内部,你可以直接访问模型对象的所有属性:
+
+```Python hl_lines="19"
+{!../../../docs_src/body/tutorial002.py!}
+```
+
+## 请求体 + 路径参数
+
+你可以同时声明路径参数和请求体。
+
+**FastAPI** 将识别出与路径参数匹配的函数参数应**从路径中获取**,而声明为 Pydantic 模型的函数参数应**从请求体中获取**。
+
+```Python hl_lines="15 16"
+{!../../../docs_src/body/tutorial003.py!}
+```
+
+## 请求体 + 路径参数 + 查询参数
+
+你还可以同时声明**请求体**、**路径参数**和**查询参数**。
+
+**FastAPI** 会识别它们中的每一个,并从正确的位置获取数据。
+
+```Python hl_lines="16"
+{!../../../docs_src/body/tutorial004.py!}
+```
+
+函数参数将依次按如下规则进行识别:
+
+* 如果在**路径**中也声明了该参数,它将被用作路径参数。
+* 如果参数属于**单一类型**(比如 `int`、`float`、`str`、`bool` 等)它将被解释为**查询**参数。
+* 如果参数的类型被声明为一个 **Pydantic 模型**,它将被解释为**请求体**。
+
+## 不使用 Pydantic
+
+如果你不想使用 Pydantic 模型,你还可以使用 **Body** 参数。请参阅文档 [请求体 - 多个参数:请求体中的单一值](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}。
diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md
new file mode 100644
index 000000000..ab63a8650
--- /dev/null
+++ b/docs/zh/docs/tutorial/first-steps.md
@@ -0,0 +1,335 @@
+# 第一步
+
+最简单的 FastAPI 文件可能像下面这样:
+
+```Python
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+将其复制到 `main.py` 文件中。
+
+运行实时服务器:
+
+get 操作
+
+!!! info "`@decorator` Info"
+ `@something` 语法在 Python 中被称为「装饰器」。
+
+ 像一顶漂亮的装饰帽一样,将它放在一个函数的上方(我猜测这个术语的命名就是这么来的)。
+
+ 装饰器接收位于其下方的函数并且用它完成一些工作。
+
+ 在我们的例子中,这个装饰器告诉 **FastAPI** 位于其下方的函数对应着**路径** `/` 加上 `get` **操作**。
+
+ 它是一个「**路径操作装饰器**」。
+
+你也可以使用其他的操作:
+
+* `@app.post()`
+* `@app.put()`
+* `@app.delete()`
+
+以及更少见的:
+
+* `@app.options()`
+* `@app.head()`
+* `@app.patch()`
+* `@app.trace()`
+
+!!! tip
+ 您可以随意使用任何一个操作(HTTP方法)。
+
+ **FastAPI** 没有强制要求操作有任何特定的含义。
+
+ 此处提供的信息仅作为指导,而不是要求。
+
+ 比如,当使用 GraphQL 时通常你所有的动作都通过 `post` 一种方法执行。
+
+### 步骤 4:定义**路径操作函数**
+
+这是我们的「**路径操作函数**」:
+
+* **路径**:是 `/`。
+* **操作**:是 `get`。
+* **函数**:是位于「装饰器」下方的函数(位于 `@app.get("/")` 下方)。
+
+```Python hl_lines="7"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+这是一个 Python 函数。
+
+每当 **FastAPI** 接收一个使用 `GET` 方法访问 URL「`/`」的请求时这个函数会被调用。
+
+在这个例子中,它是一个 `async` 函数。
+
+---
+
+你也可以将其定义为常规函数而不使用 `async def`:
+
+```Python hl_lines="7"
+{!../../../docs_src/first_steps/tutorial003.py!}
+```
+
+!!! note
+ 如果你不知道两者的区别,请查阅 [Async: *"In a hurry?"*](https://fastapi.tiangolo.com/async/#in-a-hurry){.internal-link target=_blank}。
+
+### 步骤 5:返回内容
+
+```Python hl_lines="8"
+{!../../../docs_src/first_steps/tutorial001.py!}
+```
+
+你可以返回一个 `dict`、`list`,像 `str`、`int` 一样的单个值,等等。
+
+你还可以返回 Pydantic 模型(稍后你将了解更多)。
+
+还有许多其他将会自动转换为 JSON 的对象和模型(包括 ORM 对象等)。尝试下使用你最喜欢的一种,它很有可能已经被支持。
+
+## 总结
+
+* 导入 `FastAPI`。
+* 创建一个 `app` 实例。
+* 编写一个**路径操作装饰器**(如 `@app.get("/")`)。
+* 编写一个**路径操作函数**(如上面的 `def root(): ...`)。
+* 运行开发服务器(如 `uvicorn main:app --reload`)。
diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md
new file mode 100644
index 000000000..db35e9564
--- /dev/null
+++ b/docs/zh/docs/tutorial/path-params.md
@@ -0,0 +1,234 @@
+# 路径参数
+
+你可以使用与 Python 格式化字符串相同的语法来声明路径"参数"或"变量":
+
+```Python hl_lines="6 7"
+{!../../../docs_src/path_params/tutorial001.py!}
+```
+
+路径参数 `item_id` 的值将作为参数 `item_id` 传递给你的函数。
+
+所以,如果你运行示例并访问 http://127.0.0.1:8000/items/foo,将会看到如下响应:
+
+```JSON
+{"item_id":"foo"}
+```
+
+## 有类型的路径参数
+
+你可以使用标准的 Python 类型标注为函数中的路径参数声明类型。
+
+```Python hl_lines="7"
+{!../../../docs_src/path_params/tutorial002.py!}
+```
+
+在这个例子中,`item_id` 被声明为 `int` 类型。
+
+!!! check
+ 这将为你的函数提供编辑器支持,包括错误检查、代码补全等等。
+
+## 数据转换
+
+如果你运行示例并打开浏览器访问 http://127.0.0.1:8000/items/3,将得到如下响应:
+
+```JSON
+{"item_id":3}
+```
+
+!!! check
+ 注意函数接收(并返回)的值为 3,是一个 Python `int` 值,而不是字符串 `"3"`。
+
+ 所以,**FastAPI** 通过上面的类型声明提供了对请求的自动"解析"。
+
+## 数据校验
+
+但如果你通过浏览器访问 http://127.0.0.1:8000/items/foo,你会看到一个清晰可读的 HTTP 错误:
+
+```JSON
+{
+ "detail": [
+ {
+ "loc": [
+ "path",
+ "item_id"
+ ],
+ "msg": "value is not a valid integer",
+ "type": "type_error.integer"
+ }
+ ]
+}
+```
+
+因为路径参数 `item_id` 传入的值为 `"foo"`,它不是一个 `int`。
+
+如果你提供的是 `float` 而非整数也会出现同样的错误,比如: http://127.0.0.1:8000/items/4.2
+
+!!! check
+ 所以,通过同样的 Python 类型声明,**FastAPI** 提供了数据校验功能。
+
+ 注意上面的错误同样清楚地指出了校验未通过的具体原因。
+
+ 在开发和调试与你的 API 进行交互的代码时,这非常有用。
+
+## 文档
+
+当你打开浏览器访问 http://127.0.0.1:8000/docs,你将看到自动生成的交互式 API 文档:
+
+
+
+!!! check
+ 再一次,还是通过相同的 Python 类型声明,**FastAPI** 为你提供了自动生成的交互式文档(集成 Swagger UI)。
+
+ 注意这里的路径参数被声明为一个整数。
+
+## 基于标准的好处:可选文档
+
+由于生成的 API 模式来自于 OpenAPI 标准,所以有很多工具与其兼容。
+
+正因如此,**FastAPI** 内置了一个可选的 API 文档(使用 Redoc):
+
+
+
+同样的,还有很多其他兼容的工具,包括适用于多种语言的代码生成工具。
+
+## Pydantic
+
+所有的数据校验都由 Pydantic 在幕后完成,所以你可以从它所有的优点中受益。并且你知道它在这方面非常胜任。
+
+你可以使用同样的类型声明来声明 `str`、`float`、`bool` 以及许多其他的复合数据类型。
+
+本教程的下一章节将探讨其中的一些内容。
+
+## 顺序很重要
+
+在创建*路径操作*时,你会发现有些情况下路径是固定的。
+
+比如 `/users/me`,我们假设它用来获取关于当前用户的数据.
+
+然后,你还可以使用路径 `/users/{user_id}` 来通过用户 ID 获取关于特定用户的数据。
+
+由于*路径操作*是按顺序依次运行的,你需要确保路径 `/users/me` 声明在路径 `/users/{user_id}`之前:
+```Python hl_lines="6 11"
+{!../../../docs_src/path_params/tutorial003.py!}
+```
+
+否则,`/users/{user_id}` 的路径还将与 `/users/me` 相匹配,"认为"自己正在接收一个值为 `"me"` 的 `user_id` 参数。
+
+## 预设值
+
+如果你有一个接收路径参数的路径操作,但你希望预先设定可能的有效参数值,则可以使用标准的 Python `Enum` 类型。
+
+### 创建一个 `Enum` 类
+
+导入 `Enum` 并创建一个继承自 `str` 和 `Enum` 的子类。
+
+通过从 `str` 继承,API 文档将能够知道这些值必须为 `string` 类型并且能够正确地展示出来。
+
+然后创建具有固定值的类属性,这些固定值将是可用的有效值:
+
+```Python hl_lines="1 6 7 8 9"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+!!! info
+ 枚举(或 enums)从 3.4 版本起在 Python 中可用。
+
+!!! tip
+ 如果你想知道,"AlexNet"、"ResNet" 和 "LeNet" 只是机器学习中的模型名称。
+
+### 声明*路径参数*
+
+然后使用你定义的枚举类(`ModelName`)创建一个带有类型标注的*路径参数*:
+
+```Python hl_lines="16"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+### 查看文档
+
+因为已经指定了*路径参数*的可用值,所以交互式文档可以恰当地展示它们:
+
+
+
+### 使用 Python *枚举类型*
+
+*路径参数*的值将是一个*枚举成员*。
+
+#### 比较*枚举成员*
+
+你可以将它与你创建的枚举类 `ModelName` 中的*枚举成员*进行比较:
+
+```Python hl_lines="17"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+#### 获取*枚举值*
+
+你可以使用 `model_name.value` 或通常来说 `your_enum_member.value` 来获取实际的值(在这个例子中为 `str`):
+
+```Python hl_lines="19"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+!!! tip
+ 你也可以通过 `ModelName.lenet.value` 来获取值 `"lenet"`。
+
+#### 返回*枚举成员*
+
+你可以从*路径操作*中返回*枚举成员*,即使嵌套在 JSON 结构中(例如一个 `dict` 中)。
+
+在返回给客户端之前,它们将被转换为对应的值:
+
+```Python hl_lines="18 20 21"
+{!../../../docs_src/path_params/tutorial005.py!}
+```
+
+## 包含路径的路径参数
+
+假设你有一个*路径操作*,它的路径为 `/files/{file_path}`。
+
+但是你需要 `file_path` 自身也包含*路径*,比如 `home/johndoe/myfile.txt`。
+
+因此,该文件的URL将类似于这样:`/files/home/johndoe/myfile.txt`。
+
+### OpenAPI 支持
+
+OpenAPI 不支持任何方式去声明*路径参数*以在其内部包含*路径*,因为这可能会导致难以测试和定义的情况出现。
+
+不过,你仍然可以通过 Starlette 的一个内部工具在 **FastAPI** 中实现它。
+
+而且文档依旧可以使用,但是不会添加任何该参数应包含路径的说明。
+
+### 路径转换器
+
+你可以使用直接来自 Starlette 的选项来声明一个包含*路径*的*路径参数*:
+
+```
+/files/{file_path:path}
+```
+
+在这种情况下,参数的名称为 `file_path`,结尾部分的 `:path` 说明该参数应匹配任意的*路径*。
+
+因此,你可以这样使用它:
+
+```Python hl_lines="6"
+{!../../../docs_src/path_params/tutorial004.py!}
+```
+
+!!! tip
+ 你可能会需要参数包含 `/home/johndoe/myfile.txt`,以斜杠(`/`)开头。
+
+ 在这种情况下,URL 将会是 `/files//home/johndoe/myfile.txt`,在`files` 和 `home` 之间有一个双斜杠(`//`)。
+
+## 总结
+
+使用 **FastAPI**,通过简短、直观和标准的 Python 类型声明,你将获得:
+
+* 编辑器支持:错误检查,代码补全等
+* 数据 "解析"
+* 数据校验
+* API 标注和自动生成的文档
+
+而且你只需要声明一次即可。
+
+这可能是 **FastAPI** 与其他框架相比主要的明显优势(除了原始性能以外)。
diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md
new file mode 100644
index 000000000..2a1d41a89
--- /dev/null
+++ b/docs/zh/docs/tutorial/query-params-str-validations.md
@@ -0,0 +1,281 @@
+# 查询参数和字符串校验
+
+**FastAPI** 允许你为参数声明额外的信息和校验。
+
+让我们以下面的应用程序为例:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial001.py!}
+```
+
+查询参数 `q` 的类型为 `str`,默认值为 `None`,因此它是可选的。
+
+## 额外的校验
+
+我们打算添加约束条件:即使 `q` 是可选的,但只要提供了该参数,则该参数值**不能超过50个字符的长度**。
+
+### 导入 `Query`
+
+为此,首先从 `fastapi` 导入 `Query`:
+
+```Python hl_lines="1"
+{!../../../docs_src/query_params_str_validations/tutorial002.py!}
+```
+
+## 使用 `Query` 作为默认值
+
+现在,将 `Query` 用作查询参数的默认值,并将它的 `max_length` 参数设置为 50:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial002.py!}
+```
+
+由于我们必须用 `Query(None)` 替换默认值 `None`,`Query` 的第一个参数同样也是用于定义默认值。
+
+所以:
+
+```Python
+q: str = Query(None)
+```
+
+...使得参数可选,等同于:
+
+```Python
+q: str = None
+```
+
+但是 `Query` 显式地将其声明为查询参数。
+
+然后,我们可以将更多的参数传递给 `Query`。在本例中,适用于字符串的 `max_length` 参数:
+
+```Python
+q: str = Query(None, max_length=50)
+```
+
+将会校验数据,在数据无效时展示清晰的错误信息,并在 OpenAPI 模式的*路径操作*中记录该参数。
+
+## 添加更多校验
+
+你还可以添加 `min_length` 参数:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial003.py!}
+```
+
+## 添加正则表达式
+
+你可以定义一个参数值必须匹配的正则表达式:
+
+```Python hl_lines="8"
+{!../../../docs_src/query_params_str_validations/tutorial004.py!}
+```
+
+这个指定的正则表达式通过以下规则检查接收到的参数值:
+
+* `^`:以该符号之后的字符开头,符号之前没有字符。
+* `fixedquery`: 值精确地等于 `fixedquery`。
+* `$`: 到此结束,在 `fixedquery` 之后没有更多字符。
+
+如果你对所有的这些**「正则表达式」**概念感到迷茫,请不要担心。对于许多人来说这都是一个困难的主题。你仍然可以在无需正则表达式的情况下做很多事情。
+
+但是,一旦你需要用到并去学习它们时,请了解你已经可以在 **FastAPI** 中直接使用它们。
+
+## 默认值
+
+你可以向 `Query` 的第一个参数传入 `None` 用作查询参数的默认值,以同样的方式你也可以传递其他默认值。
+
+假设你想要声明查询参数 `q`,使其 `min_length` 为 `3`,并且默认值为 `fixedquery`:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial005.py!}
+```
+
+!!! note
+ 具有默认值还会使该参数成为可选参数。
+
+## 声明为必需参数
+
+当我们不需要声明额外的校验或元数据时,只需不声明默认值就可以使 `q` 参数成为必需参数,例如:
+
+```Python
+q: str
+```
+
+代替:
+
+```Python
+q: str = None
+```
+
+但是现在我们正在用 `Query` 声明它,例如:
+
+```Python
+q: str = Query(None, min_length=3)
+```
+
+因此,当你在使用 `Query` 且需要声明一个值是必需的时,可以将 `...` 用作第一个参数值:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial006.py!}
+```
+
+!!! info
+ 如果你之前没见过 `...` 这种用法:它是一个特殊的单独值,它是 Python 的一部分并且被称为「省略号」。
+
+这将使 **FastAPI** 知道此查询参数是必需的。
+
+## 查询参数列表 / 多个值
+
+当你使用 `Query` 显式地定义查询参数时,你还可以声明它去接收一组值,或换句话来说,接收多个值。
+
+例如,要声明一个可在 URL 中出现多次的查询参数 `q`,你可以这样写:
+
+```Python hl_lines="9"
+{!../../../docs_src/query_params_str_validations/tutorial011.py!}
+```
+
+然后,输入如下网址:
+
+```
+http://localhost:8000/items/?q=foo&q=bar
+```
+
+你会在*路径操作函数*的*函数参数* `q` 中以一个 Python `list` 的形式接收到*查询参数* `q` 的多个值(`foo` 和 `bar`)。
+
+因此,该 URL 的响应将会是:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+!!! tip
+ 要声明类型为 `list` 的查询参数,如上例所示,你需要显式地使用 `Query`,否则该参数将被解释为请求体。
+
+交互式 API 文档将会相应地进行更新,以允许使用多个值:
+
+
+
+### 具有默认值的查询参数列表 / 多个值
+
+你还可以定义在没有任何给定值时的默认 `list` 值:
+
+```Python hl_lines="9"
+{!../../../docs_src/query_params_str_validations/tutorial012.py!}
+```
+
+如果你访问:
+
+```
+http://localhost:8000/items/
+```
+
+`q` 的默认值将为:`["foo", "bar"]`,你的响应会是:
+
+```JSON
+{
+ "q": [
+ "foo",
+ "bar"
+ ]
+}
+```
+
+#### 使用 `list`
+
+你也可以直接使用 `list` 代替 `List [str]`:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial013.py!}
+```
+
+!!! note
+ 请记住,在这种情况下 FastAPI 将不会检查列表的内容。
+
+ 例如,`List[int]` 将检查(并记录到文档)列表的内容必须是整数。但是单独的 `list` 不会。
+
+## 声明更多元数据
+
+你可以添加更多有关该参数的信息。
+
+这些信息将包含在生成的 OpenAPI 模式中,并由文档用户界面和外部工具所使用。
+
+!!! note
+ 请记住,不同的工具对 OpenAPI 的支持程度可能不同。
+
+ 其中一些可能不会展示所有已声明的额外信息,尽管在大多数情况下,缺少的这部分功能已经计划进行开发。
+
+你可以添加 `title`:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial007.py!}
+```
+
+以及 `description`:
+
+```Python hl_lines="11"
+{!../../../docs_src/query_params_str_validations/tutorial008.py!}
+```
+
+## 别名参数
+
+假设你想要查询参数为 `item-query`。
+
+像下面这样:
+
+```
+http://127.0.0.1:8000/items/?item-query=foobaritems
+```
+
+但是 `item-query` 不是一个有效的 Python 变量名称。
+
+最接近的有效名称是 `item_query`。
+
+但是你仍然要求它在 URL 中必须是 `item-query`...
+
+这时你可以用 `alias` 参数声明一个别名,该别名将用于在 URL 中查找查询参数值:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params_str_validations/tutorial009.py!}
+```
+
+## 弃用参数
+
+现在假设你不再喜欢此参数。
+
+你不得不将其保留一段时间,因为有些客户端正在使用它,但你希望文档清楚地将其展示为已弃用。
+
+那么将参数 `deprecated=True` 传入 `Query`:
+
+```Python hl_lines="16"
+{!../../../docs_src/query_params_str_validations/tutorial010.py!}
+```
+
+文档将会像下面这样展示它:
+
+
+
+## 总结
+
+你可以为查询参数声明额外的校验和元数据。
+
+通用的校验和元数据:
+
+* `alias`
+* `title`
+* `description`
+* `deprecated`
+
+特定于字符串的校验:
+
+* `min_length`
+* `max_length`
+* `regex`
+
+在这些示例中,你了解了如何声明对 `str` 值的校验。
+
+请参阅下一章节,以了解如何声明对其他类型例如数值的校验。
diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md
new file mode 100644
index 000000000..c91392cde
--- /dev/null
+++ b/docs/zh/docs/tutorial/query-params.md
@@ -0,0 +1,226 @@
+# 查询参数
+
+声明不属于路径参数的其他函数参数时,它们将被自动解释为"查询字符串"参数
+
+```Python hl_lines="9"
+{!../../../docs_src/query_params/tutorial001.py!}
+```
+
+查询字符串是键值对的集合,这些键值对位于 URL 的 `?` 之后,并以 `&` 符号分隔。
+
+例如,在以下 url 中:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+...查询参数为:
+
+* `skip`:对应的值为 `0`
+* `limit`:对应的值为 `10`
+
+由于它们是 URL 的一部分,因此它们的"原始值"是字符串。
+
+但是,当你为它们声明了 Python 类型(在上面的示例中为 `int`)时,它们将转换为该类型并针对该类型进行校验。
+
+应用于路径参数的所有相同过程也适用于查询参数:
+
+* (很明显的)编辑器支持
+* 数据"解析"
+* 数据校验
+* 自动生成文档
+
+## 默认值
+
+由于查询参数不是路径的固定部分,因此它们可以是可选的,并且可以有默认值。
+
+在上面的示例中,它们具有 `skip=0` 和 `limit=10` 的默认值。
+
+因此,访问 URL:
+
+```
+http://127.0.0.1:8000/items/
+```
+
+将与访问以下地址相同:
+
+```
+http://127.0.0.1:8000/items/?skip=0&limit=10
+```
+
+但是,如果你访问的是:
+
+```
+http://127.0.0.1:8000/items/?skip=20
+```
+
+函数中的参数值将会是:
+
+* `skip=20`:在 URL 中设定的值
+* `limit=10`:使用默认值
+
+## 可选参数
+
+通过同样的方式,你可以将它们的默认值设置为 `None` 来声明可选查询参数:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params/tutorial002.py!}
+```
+
+在这个例子中,函数参数 `q` 将是可选的,并且默认值为 `None`。
+
+!!! check
+ 还要注意的是,**FastAPI** 足够聪明,能够分辨出参数 `item_id` 是路径参数而 `q` 不是,因此 `q` 是一个查询参数。
+
+## 查询参数类型转换
+
+你还可以声明 `bool` 类型,它们将被自动转换:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params/tutorial003.py!}
+```
+
+这个例子中,如果你访问:
+
+```
+http://127.0.0.1:8000/items/foo?short=1
+```
+
+或
+
+```
+http://127.0.0.1:8000/items/foo?short=True
+```
+
+或
+
+```
+http://127.0.0.1:8000/items/foo?short=true
+```
+
+或
+
+```
+http://127.0.0.1:8000/items/foo?short=on
+```
+
+或
+
+```
+http://127.0.0.1:8000/items/foo?short=yes
+```
+
+或任何其他的变体形式(大写,首字母大写等等),你的函数接收的 `short` 参数都会是布尔值 `True`。对于值为 `False` 的情况也是一样的。
+
+
+## 多个路径和查询参数
+
+你可以同时声明多个路径参数和查询参数,**FastAPI** 能够识别它们。
+
+而且你不需要以任何特定的顺序来声明。
+
+它们将通过名称被检测到:
+
+```Python hl_lines="6 8"
+{!../../../docs_src/query_params/tutorial004.py!}
+```
+
+## 必需查询参数
+
+当你为非路径参数声明了默认值时(目前而言,我们所知道的仅有查询参数),则该参数不是必需的。
+
+如果你不想添加一个特定的值,而只是想使该参数成为可选的,则将默认值设置为 `None`。
+
+但当你想让一个查询参数成为必需的,不声明任何默认值就可以:
+
+```Python hl_lines="6 7"
+{!../../../docs_src/query_params/tutorial005.py!}
+```
+
+这里的查询参数 `needy` 是类型为 `str` 的必需查询参数。
+
+如果你在浏览器中打开一个像下面的 URL:
+
+```
+http://127.0.0.1:8000/items/foo-item
+```
+
+...因为没有添加必需的参数 `needy`,你将看到类似以下的错误:
+
+```JSON
+{
+ "detail": [
+ {
+ "loc": [
+ "query",
+ "needy"
+ ],
+ "msg": "field required",
+ "type": "value_error.missing"
+ }
+ ]
+}
+```
+
+由于 `needy` 是必需参数,因此你需要在 URL 中设置它的值:
+
+```
+http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
+```
+
+...这样就正常了:
+
+```JSON
+{
+ "item_id": "foo-item",
+ "needy": "sooooneedy"
+}
+```
+
+当然,你也可以定义一些参数为必需的,一些具有默认值,而某些则完全是可选的:
+
+```Python hl_lines="7"
+{!../../../docs_src/query_params/tutorial006.py!}
+```
+
+在这个例子中,有3个查询参数:
+
+* `needy`,一个必需的 `str` 类型参数。
+* `skip`,一个默认值为 `0` 的 `int` 类型参数。
+* `limit`,一个可选的 `int` 类型参数。
+
+!!! tip
+ 你还可以像在 [路径参数](path-params.md#predefined-values){.internal-link target=_blank} 中那样使用 `Enum`。
+
+## Optional 类型声明
+
+!!! warning
+ 这可能是一个比较高级的使用场景。
+
+ 您也可以跳过它。
+
+如果你正在使用 `mypy`,它可能会对如下的类型声明进行警告:
+
+```Python
+limit: int = None
+```
+
+提示类似以下错误:
+
+```
+Incompatible types in assignment (expression has type "None", variable has type "int")
+```
+
+在这种情况下,你可以使用 `Optional` 来告诉 `mypy` 该值可以为 `None`,例如:
+
+```Python
+from typing import Optional
+
+limit: Optional[int] = None
+```
+
+在一个*路径操作*中,看起来会是:
+
+```Python hl_lines="9"
+{!../../../docs_src/query_params/tutorial007.py!}
+```
diff --git a/docs/zh/mkdocs.yml b/docs/zh/mkdocs.yml
index 26b7433c4..bd372fd71 100644
--- a/docs/zh/mkdocs.yml
+++ b/docs/zh/mkdocs.yml
@@ -23,13 +23,22 @@ nav:
- en: /
- es: /es/
- ja: /ja/
+ - it: /it/
- pt: /pt/
+ - ru: /ru/
- zh: /zh/
- features.md
- python-types.md
- 教程 - 用户指南:
- tutorial/index.md
+ - tutorial/first-steps.md
+ - tutorial/path-params.md
+ - tutorial/query-params.md
+ - tutorial/body.md
+ - tutorial/query-params-str-validations.md
- deployment.md
+- contributing.md
+- help-fastapi.md
markdown_extensions:
- toc:
permalink: true
diff --git a/docs_src/app_testing/test_main_b.py b/docs_src/app_testing/test_main_b.py
index 3e31a4180..83cc7d255 100644
--- a/docs_src/app_testing/test_main_b.py
+++ b/docs_src/app_testing/test_main_b.py
@@ -51,7 +51,7 @@ def test_create_item_bad_token():
assert response.json() == {"detail": "Invalid X-Token header"}
-def test_create_existing_token():
+def test_create_existing_item():
response = client.post(
"/items/",
headers={"X-Token": "coneofsilence"},
diff --git a/docs_src/behind_a_proxy/tutorial001.py b/docs_src/behind_a_proxy/tutorial001.py
new file mode 100644
index 000000000..ede59ada1
--- /dev/null
+++ b/docs_src/behind_a_proxy/tutorial001.py
@@ -0,0 +1,8 @@
+from fastapi import FastAPI, Request
+
+app = FastAPI()
+
+
+@app.get("/app")
+def read_main(request: Request):
+ return {"message": "Hello World", "root_path": request.scope.get("root_path")}
diff --git a/docs_src/behind_a_proxy/tutorial002.py b/docs_src/behind_a_proxy/tutorial002.py
new file mode 100644
index 000000000..c1600cde9
--- /dev/null
+++ b/docs_src/behind_a_proxy/tutorial002.py
@@ -0,0 +1,8 @@
+from fastapi import FastAPI, Request
+
+app = FastAPI(root_path="/api/v1")
+
+
+@app.get("/app")
+def read_main(request: Request):
+ return {"message": "Hello World", "root_path": request.scope.get("root_path")}
diff --git a/docs_src/body_fields/tutorial001.py b/docs_src/body_fields/tutorial001.py
index 7b2c9454d..dcd5b9764 100644
--- a/docs_src/body_fields/tutorial001.py
+++ b/docs_src/body_fields/tutorial001.py
@@ -12,6 +12,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item = Body(..., embed=True)):
+async def update_item(item_id: int, item: Item = Body(..., embed=True)):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_multiple_params/tutorial002.py b/docs_src/body_multiple_params/tutorial002.py
index 5c9e8344d..54f6d9138 100644
--- a/docs_src/body_multiple_params/tutorial002.py
+++ b/docs_src/body_multiple_params/tutorial002.py
@@ -17,6 +17,6 @@ class User(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item, user: User):
+async def update_item(item_id: int, item: Item, user: User):
results = {"item_id": item_id, "item": item, "user": user}
return results
diff --git a/docs_src/body_multiple_params/tutorial003.py b/docs_src/body_multiple_params/tutorial003.py
index 301f1a862..691fe848b 100644
--- a/docs_src/body_multiple_params/tutorial003.py
+++ b/docs_src/body_multiple_params/tutorial003.py
@@ -18,7 +18,7 @@ class User(BaseModel):
@app.put("/items/{item_id}")
async def update_item(
- *, item_id: int, item: Item, user: User, importance: int = Body(...)
+ item_id: int, item: Item, user: User, importance: int = Body(...)
):
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
return results
diff --git a/docs_src/body_multiple_params/tutorial005.py b/docs_src/body_multiple_params/tutorial005.py
index 61f1b2917..606d3bbbb 100644
--- a/docs_src/body_multiple_params/tutorial005.py
+++ b/docs_src/body_multiple_params/tutorial005.py
@@ -12,6 +12,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item = Body(..., embed=True)):
+async def update_item(item_id: int, item: Item = Body(..., embed=True)):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_nested_models/tutorial001.py b/docs_src/body_nested_models/tutorial001.py
index 9e0fa4494..56db2a093 100644
--- a/docs_src/body_nested_models/tutorial001.py
+++ b/docs_src/body_nested_models/tutorial001.py
@@ -13,6 +13,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_nested_models/tutorial002.py b/docs_src/body_nested_models/tutorial002.py
index 8f769279b..db33e483f 100644
--- a/docs_src/body_nested_models/tutorial002.py
+++ b/docs_src/body_nested_models/tutorial002.py
@@ -15,6 +15,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_nested_models/tutorial003.py b/docs_src/body_nested_models/tutorial003.py
index bb539b127..f65195b62 100644
--- a/docs_src/body_nested_models/tutorial003.py
+++ b/docs_src/body_nested_models/tutorial003.py
@@ -15,6 +15,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_nested_models/tutorial004.py b/docs_src/body_nested_models/tutorial004.py
index 257928ef3..6c2ca25eb 100644
--- a/docs_src/body_nested_models/tutorial004.py
+++ b/docs_src/body_nested_models/tutorial004.py
@@ -21,6 +21,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_nested_models/tutorial005.py b/docs_src/body_nested_models/tutorial005.py
index afea77179..d6d9d6479 100644
--- a/docs_src/body_nested_models/tutorial005.py
+++ b/docs_src/body_nested_models/tutorial005.py
@@ -21,6 +21,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_nested_models/tutorial006.py b/docs_src/body_nested_models/tutorial006.py
index 3d0db6e58..d64668518 100644
--- a/docs_src/body_nested_models/tutorial006.py
+++ b/docs_src/body_nested_models/tutorial006.py
@@ -21,6 +21,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/body_nested_models/tutorial007.py b/docs_src/body_nested_models/tutorial007.py
index f13c07ad5..f4b699dbf 100644
--- a/docs_src/body_nested_models/tutorial007.py
+++ b/docs_src/body_nested_models/tutorial007.py
@@ -28,5 +28,5 @@ class Offer(BaseModel):
@app.post("/offers/")
-async def create_offer(*, offer: Offer):
+async def create_offer(offer: Offer):
return offer
diff --git a/docs_src/body_nested_models/tutorial008.py b/docs_src/body_nested_models/tutorial008.py
index b6f5c0660..3431cc636 100644
--- a/docs_src/body_nested_models/tutorial008.py
+++ b/docs_src/body_nested_models/tutorial008.py
@@ -12,5 +12,5 @@ class Image(BaseModel):
@app.post("/images/multiple/")
-async def create_multiple_images(*, images: List[Image]):
+async def create_multiple_images(images: List[Image]):
return images
diff --git a/docs_src/cookie_params/tutorial001.py b/docs_src/cookie_params/tutorial001.py
index 5a6fd30fe..bee934b06 100644
--- a/docs_src/cookie_params/tutorial001.py
+++ b/docs_src/cookie_params/tutorial001.py
@@ -4,5 +4,5 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(*, ads_id: str = Cookie(None)):
+async def read_items(ads_id: str = Cookie(None)):
return {"ads_id": ads_id}
diff --git a/docs_src/custom_response/tutorial010.py b/docs_src/custom_response/tutorial010.py
new file mode 100644
index 000000000..57cb06260
--- /dev/null
+++ b/docs_src/custom_response/tutorial010.py
@@ -0,0 +1,9 @@
+from fastapi import FastAPI
+from fastapi.responses import ORJSONResponse
+
+app = FastAPI(default_response_class=ORJSONResponse)
+
+
+@app.get("/items/")
+async def read_items():
+ return [{"item_id": "Foo"}]
diff --git a/docs_src/extending_openapi/tutorial001.py b/docs_src/extending_openapi/tutorial001.py
index 561e95898..d9d7e9844 100644
--- a/docs_src/extending_openapi/tutorial001.py
+++ b/docs_src/extending_openapi/tutorial001.py
@@ -9,7 +9,7 @@ async def read_items():
return [{"name": "Foo"}]
-def custom_openapi():
+def custom_openapi(openapi_prefix: str):
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
@@ -17,6 +17,7 @@ def custom_openapi():
version="2.5.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
+ openapi_prefix=openapi_prefix,
)
openapi_schema["info"]["x-logo"] = {
"url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png"
diff --git a/docs_src/extra_models/tutorial001.py b/docs_src/extra_models/tutorial001.py
index 08d3659b0..7ff4bba7e 100644
--- a/docs_src/extra_models/tutorial001.py
+++ b/docs_src/extra_models/tutorial001.py
@@ -36,6 +36,6 @@ def fake_save_user(user_in: UserIn):
@app.post("/user/", response_model=UserOut)
-async def create_user(*, user_in: UserIn):
+async def create_user(user_in: UserIn):
user_saved = fake_save_user(user_in)
return user_saved
diff --git a/docs_src/extra_models/tutorial002.py b/docs_src/extra_models/tutorial002.py
index ab680eca0..030699114 100644
--- a/docs_src/extra_models/tutorial002.py
+++ b/docs_src/extra_models/tutorial002.py
@@ -34,6 +34,6 @@ def fake_save_user(user_in: UserIn):
@app.post("/user/", response_model=UserOut)
-async def create_user(*, user_in: UserIn):
+async def create_user(user_in: UserIn):
user_saved = fake_save_user(user_in)
return user_saved
diff --git a/docs_src/header_params/tutorial001.py b/docs_src/header_params/tutorial001.py
index 69f3dc712..e871de68d 100644
--- a/docs_src/header_params/tutorial001.py
+++ b/docs_src/header_params/tutorial001.py
@@ -4,5 +4,5 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(*, user_agent: str = Header(None)):
+async def read_items(user_agent: str = Header(None)):
return {"User-Agent": user_agent}
diff --git a/docs_src/header_params/tutorial002.py b/docs_src/header_params/tutorial002.py
index 4edc4b6fd..ba6cef1de 100644
--- a/docs_src/header_params/tutorial002.py
+++ b/docs_src/header_params/tutorial002.py
@@ -4,5 +4,5 @@ app = FastAPI()
@app.get("/items/")
-async def read_items(*, strange_header: str = Header(None, convert_underscores=False)):
+async def read_items(strange_header: str = Header(None, convert_underscores=False)):
return {"strange_header": strange_header}
diff --git a/docs_src/metadata/tutorial004.py b/docs_src/metadata/tutorial004.py
new file mode 100644
index 000000000..465bd659d
--- /dev/null
+++ b/docs_src/metadata/tutorial004.py
@@ -0,0 +1,28 @@
+from fastapi import FastAPI
+
+tags_metadata = [
+ {
+ "name": "users",
+ "description": "Operations with users. The **login** logic is also here.",
+ },
+ {
+ "name": "items",
+ "description": "Manage items. So _fancy_ they have their own docs.",
+ "externalDocs": {
+ "description": "Items external docs",
+ "url": "https://fastapi.tiangolo.com/",
+ },
+ },
+]
+
+app = FastAPI(openapi_tags=tags_metadata)
+
+
+@app.get("/users/", tags=["users"])
+async def get_users():
+ return [{"name": "Harry"}, {"name": "Ron"}]
+
+
+@app.get("/items/", tags=["items"])
+async def get_items():
+ return [{"name": "wand"}, {"name": "flying broom"}]
diff --git a/docs_src/path_operation_advanced_configuration/tutorial004.py b/docs_src/path_operation_advanced_configuration/tutorial004.py
index 36bf02b11..24be0cb94 100644
--- a/docs_src/path_operation_advanced_configuration/tutorial004.py
+++ b/docs_src/path_operation_advanced_configuration/tutorial004.py
@@ -15,7 +15,7 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, summary="Create an item")
-async def create_item(*, item: Item):
+async def create_item(item: Item):
"""
Create an item with all the information:
diff --git a/docs_src/path_operation_configuration/tutorial001.py b/docs_src/path_operation_configuration/tutorial001.py
index a60b47fef..77437cd08 100644
--- a/docs_src/path_operation_configuration/tutorial001.py
+++ b/docs_src/path_operation_configuration/tutorial001.py
@@ -15,5 +15,5 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
-async def create_item(*, item: Item):
+async def create_item(item: Item):
return item
diff --git a/docs_src/path_operation_configuration/tutorial002.py b/docs_src/path_operation_configuration/tutorial002.py
index b5d0f12ca..ed29ea014 100644
--- a/docs_src/path_operation_configuration/tutorial002.py
+++ b/docs_src/path_operation_configuration/tutorial002.py
@@ -15,7 +15,7 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, tags=["items"])
-async def create_item(*, item: Item):
+async def create_item(item: Item):
return item
diff --git a/docs_src/path_operation_configuration/tutorial003.py b/docs_src/path_operation_configuration/tutorial003.py
index 106607fd2..4c4b048c7 100644
--- a/docs_src/path_operation_configuration/tutorial003.py
+++ b/docs_src/path_operation_configuration/tutorial003.py
@@ -20,5 +20,5 @@ class Item(BaseModel):
summary="Create an item",
description="Create an item with all the information, name, description, price, tax and a set of unique tags",
)
-async def create_item(*, item: Item):
+async def create_item(item: Item):
return item
diff --git a/docs_src/path_operation_configuration/tutorial004.py b/docs_src/path_operation_configuration/tutorial004.py
index f47d422e0..f9822aae4 100644
--- a/docs_src/path_operation_configuration/tutorial004.py
+++ b/docs_src/path_operation_configuration/tutorial004.py
@@ -15,7 +15,7 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, summary="Create an item")
-async def create_item(*, item: Item):
+async def create_item(item: Item):
"""
Create an item with all the information:
diff --git a/docs_src/path_operation_configuration/tutorial005.py b/docs_src/path_operation_configuration/tutorial005.py
index 72d02ece3..7ae2acafc 100644
--- a/docs_src/path_operation_configuration/tutorial005.py
+++ b/docs_src/path_operation_configuration/tutorial005.py
@@ -20,7 +20,7 @@ class Item(BaseModel):
summary="Create an item",
response_description="The created item",
)
-async def create_item(*, item: Item):
+async def create_item(item: Item):
"""
Create an item with all the information:
diff --git a/docs_src/path_params/tutorial005.py b/docs_src/path_params/tutorial005.py
index e58b22c61..d14b926e5 100644
--- a/docs_src/path_params/tutorial005.py
+++ b/docs_src/path_params/tutorial005.py
@@ -16,6 +16,8 @@ app = FastAPI()
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
+
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
+
return {"model_name": model_name, "message": "Have some residuals"}
diff --git a/docs_src/python_types/tutorial009.py b/docs_src/python_types/tutorial009.py
index 468cffc2d..6328a1495 100644
--- a/docs_src/python_types/tutorial009.py
+++ b/docs_src/python_types/tutorial009.py
@@ -1,7 +1,8 @@
-class Person:
- def __init__(self, name: str):
- self.name = name
+from typing import Optional
-def get_person_name(one_person: Person):
- return one_person.name
+def say_hi(name: Optional[str] = None):
+ if name is not None:
+ print(f"Hey {name}!")
+ else:
+ print("Hello World")
diff --git a/docs_src/python_types/tutorial010.py b/docs_src/python_types/tutorial010.py
index faeb02a58..468cffc2d 100644
--- a/docs_src/python_types/tutorial010.py
+++ b/docs_src/python_types/tutorial010.py
@@ -1,23 +1,7 @@
-from datetime import datetime
-from typing import List
-
-from pydantic import BaseModel
+class Person:
+ def __init__(self, name: str):
+ self.name = name
-class User(BaseModel):
- id: int
- name = "John Doe"
- signup_ts: datetime = None
- friends: List[int] = []
-
-
-external_data = {
- "id": "123",
- "signup_ts": "2017-06-01 12:22",
- "friends": [1, "2", b"3"],
-}
-user = User(**external_data)
-print(user)
-# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
-print(user.id)
-# > 123
+def get_person_name(one_person: Person):
+ return one_person.name
diff --git a/docs_src/python_types/tutorial011.py b/docs_src/python_types/tutorial011.py
new file mode 100644
index 000000000..047b633b5
--- /dev/null
+++ b/docs_src/python_types/tutorial011.py
@@ -0,0 +1,23 @@
+from datetime import datetime
+from typing import List, Optional
+
+from pydantic import BaseModel
+
+
+class User(BaseModel):
+ id: int
+ name = "John Doe"
+ signup_ts: Optional[datetime] = None
+ friends: List[int] = []
+
+
+external_data = {
+ "id": "123",
+ "signup_ts": "2017-06-01 12:22",
+ "friends": [1, "2", b"3"],
+}
+user = User(**external_data)
+print(user)
+# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
+print(user.id)
+# > 123
diff --git a/docs_src/request_forms/tutorial001.py b/docs_src/request_forms/tutorial001.py
index 0290b644d..c07e22945 100644
--- a/docs_src/request_forms/tutorial001.py
+++ b/docs_src/request_forms/tutorial001.py
@@ -4,5 +4,5 @@ app = FastAPI()
@app.post("/login/")
-async def login(*, username: str = Form(...), password: str = Form(...)):
+async def login(username: str = Form(...), password: str = Form(...)):
return {"username": username}
diff --git a/docs_src/response_model/tutorial002.py b/docs_src/response_model/tutorial002.py
index b36b2a347..67084b45e 100644
--- a/docs_src/response_model/tutorial002.py
+++ b/docs_src/response_model/tutorial002.py
@@ -13,5 +13,5 @@ class UserIn(BaseModel):
# Don't do this in production!
@app.post("/user/", response_model=UserIn)
-async def create_user(*, user: UserIn):
+async def create_user(user: UserIn):
return user
diff --git a/docs_src/response_model/tutorial003.py b/docs_src/response_model/tutorial003.py
index a73372901..8450723c2 100644
--- a/docs_src/response_model/tutorial003.py
+++ b/docs_src/response_model/tutorial003.py
@@ -18,5 +18,5 @@ class UserOut(BaseModel):
@app.post("/user/", response_model=UserOut)
-async def create_user(*, user: UserIn):
+async def create_user(user: UserIn):
return user
diff --git a/docs_src/schema_extra_example/tutorial001.py b/docs_src/schema_extra_example/tutorial001.py
index cd4d45f51..59a583750 100644
--- a/docs_src/schema_extra_example/tutorial001.py
+++ b/docs_src/schema_extra_example/tutorial001.py
@@ -22,6 +22,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/schema_extra_example/tutorial002.py b/docs_src/schema_extra_example/tutorial002.py
index edf9897d0..0a567bd79 100644
--- a/docs_src/schema_extra_example/tutorial002.py
+++ b/docs_src/schema_extra_example/tutorial002.py
@@ -12,6 +12,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
-async def update_item(*, item_id: int, item: Item):
+async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/schema_extra_example/tutorial003.py b/docs_src/schema_extra_example/tutorial003.py
index 1165fd7a0..87fbefbb6 100644
--- a/docs_src/schema_extra_example/tutorial003.py
+++ b/docs_src/schema_extra_example/tutorial003.py
@@ -13,7 +13,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(
- *,
item_id: int,
item: Item = Body(
...,
@@ -23,7 +22,7 @@ async def update_item(
"price": 35.4,
"tax": 3.2,
},
- )
+ ),
):
results = {"item_id": item_id, "item": item}
return results
diff --git a/docs_src/security/tutorial004.py b/docs_src/security/tutorial004.py
index 3c8b6693d..56f0eb0ea 100644
--- a/docs_src/security/tutorial004.py
+++ b/docs_src/security/tutorial004.py
@@ -75,7 +75,7 @@ def authenticate_user(fake_db, username: str, password: str):
return user
-def create_access_token(*, data: dict, expires_delta: timedelta = None):
+def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
diff --git a/docs_src/security/tutorial005.py b/docs_src/security/tutorial005.py
index f43659454..489404d6f 100644
--- a/docs_src/security/tutorial005.py
+++ b/docs_src/security/tutorial005.py
@@ -91,7 +91,7 @@ def authenticate_user(fake_db, username: str, password: str):
return user
-def create_access_token(*, data: dict, expires_delta: timedelta = None):
+def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
diff --git a/docs_src/sub_applications/tutorial001.py b/docs_src/sub_applications/tutorial001.py
index 3b1f77a82..57e627e80 100644
--- a/docs_src/sub_applications/tutorial001.py
+++ b/docs_src/sub_applications/tutorial001.py
@@ -8,7 +8,7 @@ def read_main():
return {"message": "Hello World from main app"}
-subapi = FastAPI(openapi_prefix="/subapi")
+subapi = FastAPI()
@subapi.get("/sub")
diff --git a/docs_src/websockets/tutorial002.py b/docs_src/websockets/tutorial002.py
index 43005e54c..5be199cd6 100644
--- a/docs_src/websockets/tutorial002.py
+++ b/docs_src/websockets/tutorial002.py
@@ -1,4 +1,4 @@
-from fastapi import Cookie, Depends, FastAPI, Header, WebSocket, status
+from fastapi import Cookie, Depends, FastAPI, Query, WebSocket, status
from fastapi.responses import HTMLResponse
app = FastAPI()
@@ -13,8 +13,9 @@ html = """