mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-25 07:08:11 -05:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
072c2bc7f9 | ||
|
|
da7826b0eb | ||
|
|
2f478eeca6 | ||
|
|
543ef7753a | ||
|
|
88a887329e | ||
|
|
8cfe254400 | ||
|
|
bfd46e562b | ||
|
|
a0e4d38bea | ||
|
|
b0414b9929 | ||
|
|
3b4413f9f5 | ||
|
|
374cdf29a9 | ||
|
|
8d844bc5cf | ||
|
|
1092261ae1 | ||
|
|
5984233223 | ||
|
|
98bb9f13da | ||
|
|
d375dc6ebe | ||
|
|
ee335bca82 | ||
|
|
601d8eb809 | ||
|
|
b99f350a18 | ||
|
|
c1b0e796c6 | ||
|
|
d9e65147c7 | ||
|
|
6001513c4f | ||
|
|
3fa033d8d5 | ||
|
|
59f7e66ac3 | ||
|
|
08e8dfccbe | ||
|
|
fc70a2f36f | ||
|
|
f5c5dbb739 | ||
|
|
ca939fabf7 | ||
|
|
cc3d795bea | ||
|
|
7fc1bac54b | ||
|
|
27367df90c | ||
|
|
f93861e321 | ||
|
|
30e56ec835 | ||
|
|
48ccef9ad2 | ||
|
|
b79e002635 | ||
|
|
1fa28b7cb6 | ||
|
|
22f7eae3f2 | ||
|
|
ae93773465 | ||
|
|
0f387553d1 | ||
|
|
d53a253c8d | ||
|
|
f8f0a6e462 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github: [tiangolo]
|
||||
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
62
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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.
|
||||
92
.github/ISSUE_TEMPLATE/feature_request.md
vendored
92
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -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 [...]
|
||||
<!--
|
||||
|
||||
I'm asking all this because answering questions and solving problems in GitHub issues consumes a lot of time. I end up not being able to add new features, fix bugs, review Pull Requests, etc. as fast as I wish because I have to spend too much time handling issues.
|
||||
|
||||
All that, on top of all the incredible help provided by a bunch of community members that give a lot of their time to come here and help others.
|
||||
|
||||
That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅).
|
||||
|
||||
-->
|
||||
|
||||
### Example
|
||||
|
||||
Here's a self-contained [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with my use case:
|
||||
|
||||
<!-- Replace the code below with your own self-contained, minimal, reproducible, example -->
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
<!-- Replace the content below with your own feature request -->
|
||||
|
||||
* 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.
|
||||
<!-- Replace this with your own content -->
|
||||
|
||||
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.
|
||||
<!-- Replace this with your own ideas -->
|
||||
|
||||
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.
|
||||
<!-- Add any other context or screenshots about the question here. -->
|
||||
|
||||
71
.github/ISSUE_TEMPLATE/question.md
vendored
71
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -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.
|
||||
|
||||
<!--
|
||||
|
||||
I'm asking all this because answering questions and solving problems in GitHub issues consumes a lot of time. I end up not being able to add new features, fix bugs, review Pull Requests, etc. as fast as I wish because I have to spend too much time handling issues.
|
||||
|
||||
All that, on top of all the incredible help provided by a bunch of community members that give a lot of their time to come here and help others.
|
||||
|
||||
That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅).
|
||||
|
||||
-->
|
||||
|
||||
### Example
|
||||
|
||||
Here's a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with my use case:
|
||||
|
||||
<!-- Replace the code below with your own self-contained, minimal, reproducible, example, if I (or someone) can copy it, run it, and see it right away, there's a much higher chance I (or someone) will be able to help you -->
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
```
|
||||
|
||||
### Description
|
||||
|
||||
How can I [...]?
|
||||
<!-- Replace the content below with your own problem, question, or error -->
|
||||
|
||||
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 feature request here.
|
||||
<!-- Add any other context or screenshots about the question here. -->
|
||||
|
||||
@@ -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"],
|
||||
30
README.md
30
README.md
@@ -33,7 +33,7 @@ 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% *.
|
||||
* **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. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
@@ -45,38 +45,44 @@ The key features are:
|
||||
|
||||
## 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.*"
|
||||
"_[...] 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._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*I’m over the moon excited about **FastAPI**. It’s so fun!*"
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*"
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]*"
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"*We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]*"
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
281
docs/en/docs/advanced/behind-a-proxy.md
Normal file
281
docs/en/docs/advanced/behind-a-proxy.md
Normal file
@@ -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:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --root-path /api/v1
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
If you use Hypercorn, it also has the option `--root-path`.
|
||||
|
||||
!!! note "Technical Details"
|
||||
The ASGI specification defines a `root_path` for this use case.
|
||||
|
||||
And the `--root-path` command line option provides that `root_path`.
|
||||
|
||||
### Checking the current `root_path`
|
||||
|
||||
You can get the current `root_path` used by your application for each request, it is part of the `scope` dictionary (that's part of the ASGI spec).
|
||||
|
||||
Here we are including it in the message just for demonstration purposes.
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/behind_a_proxy/tutorial001.py!}
|
||||
```
|
||||
|
||||
Then, if you start Uvicorn with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --root-path /api/v1
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
The response would be something like:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"message": "Hello World",
|
||||
"root_path": "/api/v1"
|
||||
}
|
||||
```
|
||||
|
||||
### Setting the `root_path` in the FastAPI app
|
||||
|
||||
Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/behind_a_proxy/tutorial002.py!}
|
||||
```
|
||||
|
||||
Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn.
|
||||
|
||||
### About `root_path`
|
||||
|
||||
Have in mind that the server (Uvicorn) won't use that `root_path` for anything else than passing it to the app.
|
||||
|
||||
But if you go with your browser to <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> you will see the normal response:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"message": "Hello World",
|
||||
"root_path": "/api/v1"
|
||||
}
|
||||
```
|
||||
|
||||
So, it won't expect to be accessed at `http://127.0.0.1:8000/api/v1/app`.
|
||||
|
||||
Uvicorn will expect the proxy to access Uvicorn at `http://127.0.0.1:8000/app`, and then it would be the proxy's responsibility to add the extra `/api/v1` prefix on top.
|
||||
|
||||
## About proxies with a stripped path prefix
|
||||
|
||||
Have in mind that a proxy with stripped path prefix is only one of the ways to configure it.
|
||||
|
||||
Probably in many cases the default will be that the proxy doesn't have a stripped path prefix.
|
||||
|
||||
In a case like that (without a stripped path prefix), the proxy would listen on something like `https://myawesomeapp.com`, and then if the browser goes to `https://myawesomeapp.com/api/v1/app` and your server (e.g. Uvicorn) listens on `http://127.0.0.1:8000` the proxy (without a stripped path prefix) would access Uvicorn at the same path: `http://127.0.0.1:8000/api/v1/app`.
|
||||
|
||||
## Testing locally with Traefik
|
||||
|
||||
You can easily run the experiment locally with a stripped path prefix using <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
|
||||
|
||||
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Download Traefik</a>, it's a single binary, you can extract the compressed file and run it directly from the terminal.
|
||||
|
||||
Then create a file `traefik.toml` with:
|
||||
|
||||
```TOML hl_lines="3"
|
||||
[entryPoints]
|
||||
[entryPoints.http]
|
||||
address = ":9999"
|
||||
|
||||
[providers]
|
||||
[providers.file]
|
||||
filename = "routes.toml"
|
||||
```
|
||||
|
||||
This tells Traefik to listen on port 9999 and to use another file `routes.toml`.
|
||||
|
||||
!!! tip
|
||||
We are using port 9999 instead of the standard HTTP port 80 so that you don't have to run it with admin (`sudo`) privileges.
|
||||
|
||||
Now create that other file `routes.toml`:
|
||||
|
||||
```TOML hl_lines="5 12 20"
|
||||
[http]
|
||||
[http.middlewares]
|
||||
|
||||
[http.middlewares.api-stripprefix.stripPrefix]
|
||||
prefixes = ["/api/v1"]
|
||||
|
||||
[http.routers]
|
||||
|
||||
[http.routers.app-http]
|
||||
entryPoints = ["http"]
|
||||
service = "app"
|
||||
rule = "PathPrefix(`/api/v1`)"
|
||||
middlewares = ["api-stripprefix"]
|
||||
|
||||
[http.services]
|
||||
|
||||
[http.services.app]
|
||||
[http.services.app.loadBalancer]
|
||||
[[http.services.app.loadBalancer.servers]]
|
||||
url = "http://127.0.0.1:8000"
|
||||
```
|
||||
|
||||
This file configures Traefik to use the path prefix `/api/v1`.
|
||||
|
||||
And then it will redirect its requests to your Uvicorn running on `http://127.0.0.1:8000`.
|
||||
|
||||
Now start Traefik:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ ./traefik --configFile=traefik.toml
|
||||
|
||||
INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
And now start your app with Uvicorn, using the `--root-path` option:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --root-path /api/v1
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Check the responses
|
||||
|
||||
Now, if you go to the URL with the port for Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, you will see the normal response:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"message": "Hello World",
|
||||
"root_path": "/api/v1"
|
||||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
Notice that even though you are accessing it at `http://127.0.0.1:8000/app` it shows the `root_path` of `/api/v1`, taken from the option `--root-path`.
|
||||
|
||||
And now open the URL with the port for Traefik, including the path prefix: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/vi/app</a>.
|
||||
|
||||
We get the same response:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"message": "Hello World",
|
||||
"root_path": "/api/v1"
|
||||
}
|
||||
```
|
||||
|
||||
but this time at the URL with the prefix path provided by the proxy: `/api/v1`.
|
||||
|
||||
Of course, the idea here is that everyone would access the app through the proxy, so the version with the path prefix `/app/v1` is the "correct" one.
|
||||
|
||||
And the version without the path prefix (`http://127.0.0.1:8000/app`), provided by Uvicorn directly, would be exclusively for the _proxy_ (Traefik) to access it.
|
||||
|
||||
That demonstrates how the Proxy (Traefik) uses the path prefix and how the server (Uvicorn) uses the `root_path` from the option `--root-path`.
|
||||
|
||||
### Check the docs UI
|
||||
|
||||
But here's the fun part. ✨
|
||||
|
||||
The "official" way to access the app would be through the proxy with the path prefix that we defined. So, as we would expect, if you try the docs UI served by Uvicorn directly, without the path prefix in the URL, it won't work, because it expects to be accessed through the proxy.
|
||||
|
||||
You can check it at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>:
|
||||
|
||||
<img src="/img/tutorial/behind-a-proxy/image01.png">
|
||||
|
||||
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 <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>:
|
||||
|
||||
<img src="/img/tutorial/behind-a-proxy/image02.png">
|
||||
|
||||
## 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. ✨
|
||||
@@ -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!}
|
||||
```
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
And open the docs at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic API docs for the main app, including only its own paths:
|
||||
|
||||
<img src="/img/tutorial/sub-applications/image01.png">
|
||||
|
||||
And then, open the docs for the sub-application, at <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
|
||||
|
||||
You will see the automatic API docs for the sub-application, including only its own sub-paths, with their correct prefix:
|
||||
|
||||
<img src="/img/tutorial/sub-applications/image02.png">
|
||||
|
||||
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).
|
||||
73
docs/en/docs/advanced/sub-applications.md
Normal file
73
docs/en/docs/advanced/sub-applications.md
Normal file
@@ -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:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
And open the docs at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic API docs for the main app, including only its own _path operations_:
|
||||
|
||||
<img src="/img/tutorial/sub-applications/image01.png">
|
||||
|
||||
And then, open the docs for the sub-application, at <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
|
||||
|
||||
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`:
|
||||
|
||||
<img src="/img/tutorial/sub-applications/image02.png">
|
||||
|
||||
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}.
|
||||
@@ -265,7 +265,7 @@ To see how to achieve this parallelism in production see the section about [Depl
|
||||
|
||||
## `async` and `await`
|
||||
|
||||
Modern versions of python have a very intuitive way to define asynchronous code. This makes it look just like normal "sequential" code and do the "awaiting" for you at the right moments.
|
||||
Modern versions of Python have a very intuitive way to define asynchronous code. This makes it look just like normal "sequential" code and do the "awaiting" for you at the right moments.
|
||||
|
||||
When there is an operation that will require waiting before giving the results and has support for these new Python features, you can code it like:
|
||||
|
||||
@@ -336,7 +336,7 @@ But before that, handling asynchronous code was quite more complex and difficult
|
||||
|
||||
In previous versions of Python, you could have used threads or <a href="http://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. But the code is way more complex to understand, debug, and think about.
|
||||
|
||||
In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which lead to <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
|
||||
In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which leads to <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
|
||||
|
||||
## Coroutines
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,23 @@ Here's an incomplete list of some of them.
|
||||
|
||||
* <a href="https://iwpnd.pw/articles/2020-03/apache-kafka-fastapi-geostream" class="external-link" target="_blank">Apache Kafka producer and consumer with FastAPI and aiokafka</a> by <a href="https://iwpnd.pw" class="external-link" target="_blank">Benjamin Ramser</a>.
|
||||
|
||||
* <a href="https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/" class="external-link" target="_blank">Real-time Notifications with Python and Postgres</a> by <a href="https://wuilly.com/" class="external-link" target="_blank">Guillermo Cruz</a>.
|
||||
|
||||
* <a href="https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc" class="external-link" target="_blank">Microservice in Python using FastAPI</a> by <a href="https://twitter.com/PaurakhSharma" class="external-link" target="_blank">Paurakh Sharma Humagain</a>.
|
||||
|
||||
* <a href="https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o" class="external-link" target="_blank">Build simple API service with Python FastAPI — Part 1</a> by <a href="https://dev.to/cuongld2" class="external-link" target="_blank">cuongld2</a>.
|
||||
|
||||
* <a href="https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/" class="external-link" target="_blank">FastAPI + Zeit.co = 🚀
|
||||
</a> by <a href="https://twitter.com/PaulWebSec" class="external-link" target="_blank">Paul Sec</a>.
|
||||
|
||||
* <a href="https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe" class="external-link" target="_blank">Build a web API from scratch with FastAPI - the workshop</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
|
||||
|
||||
* <a href="https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi" class="external-link" target="_blank">Build a Secure Twilio Webhook with Python and FastAPI</a> by <a href="https://www.twilio.com" class="external-link" target="_blank">Twilio</a>.
|
||||
|
||||
* <a href="https://www.stavros.io/posts/fastapi-with-django/" class="external-link" target="_blank">Using FastAPI with Django</a> by <a href="https://twitter.com/Stavros" class="external-link" target="_blank">Stavros Korokithakis</a>.
|
||||
|
||||
* <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" class="external-link" target="_blank">Introducing Dispatch</a> by <a href="https://netflixtechblog.com/" class="external-link" target="_blank">Netflix</a>.
|
||||
|
||||
### Japanese
|
||||
|
||||
* <a href="https://qiita.com/mtitg/items/47770e9a562dd150631d" class="external-link" target="_blank">FastAPI|DB接続してCRUDするPython製APIサーバーを構築</a> by <a href="https://qiita.com/mtitg" class="external-link" target="_blank">@mtitg</a>.
|
||||
@@ -110,11 +127,16 @@ Here's an incomplete list of some of them.
|
||||
## Podcasts
|
||||
|
||||
* <a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" class="external-link" target="_blank">FastAPI on PythonBytes</a> by <a href="https://pythonbytes.fm/" class="external-link" target="_blank">Python Bytes FM</a>.
|
||||
* <a href="https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/" class="external-link" target="_blank">Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)</a> by <a href="https://www.pythonpodcast.com/" class="external-link" target="_blank">Podcast.`__init__`</a>.
|
||||
|
||||
## Talks
|
||||
|
||||
* <a href="https://www.youtube.com/watch?v=3DLwPcrE5mA" class="external-link" target="_blank">PyCon UK 2019: FastAPI from the ground up</a> by <a href="https://twitter.com/chriswithers13" class="external-link" target="_blank">Chris Withers</a>.
|
||||
|
||||
* <a href="https://www.youtube.com/watch?v=z9K5pwb0rt8" class="external-link" target="_blank">PyConBY 2020: Serve ML models easily with FastAPI</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
|
||||
|
||||
* <a href="https://www.youtube.com/watch?v=PnpTY1f4k2U" class="external-link" target="_blank">[VIRTUAL] Py.Amsterdam's flying Software Circus: Intro to FastAPI</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
|
||||
|
||||
## Projects
|
||||
|
||||
Latest GitHub projects with the topic `fastapi`:
|
||||
|
||||
@@ -71,7 +71,7 @@ my_second_user: User = User(**second_user_data)
|
||||
|
||||
### Editor support
|
||||
|
||||
All the framework was designed to be easy and intuitive to use, all the decisions where tested on multiple editors even before starting development, to ensure the best development experience.
|
||||
All the framework was designed to be easy and intuitive to use, all the decisions were tested on multiple editors even before starting development, to ensure the best development experience.
|
||||
|
||||
In the last Python developer survey it was clear <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">that the most used feature is "autocompletion"</a>.
|
||||
|
||||
|
||||
@@ -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): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>.
|
||||
You can "star" FastAPI in GitHub (clicking the star button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. ⭐️
|
||||
|
||||
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): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>.
|
||||
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
|
||||
|
||||
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
|
||||
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
</a>
|
||||
|
||||
Join the chat on Gitter: <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">https://gitter.im/tiangolo/fastapi</a>.
|
||||
|
||||
There you can ask quick questions, help others, share ideas, etc.
|
||||
|
||||
## Connect with the author
|
||||
|
||||
You can connect with <a href="https://tiangolo.com" class="external-link" target="_blank">me (Sebastián Ramírez / `tiangolo`)</a>, the author.
|
||||
@@ -45,39 +35,32 @@ You can:
|
||||
* Follow me to see when I create a new Open Source project.
|
||||
* <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Follow me on **Twitter**</a>.
|
||||
* Tell me how you use FastAPI (I love to hear that).
|
||||
* Ask questions.
|
||||
* Hear when I make announcements or release new tools.
|
||||
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Connect with me on **Linkedin**</a>.
|
||||
* Talk to me.
|
||||
* Endorse me or recommend me :)
|
||||
* <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">Read what I write (or follow me) on **Medium**</a>.
|
||||
* Read other ideas, articles and tools I have created.
|
||||
* Follow me to see when I publish something new.
|
||||
* Hear when I make announcements or release new tools (although I use Twitter more often 🤷♂).
|
||||
* Read what I write (or follow me) on <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> or <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>.
|
||||
* Read other ideas, articles, and about tools I have created.
|
||||
* Follow me to read when I publish something new.
|
||||
|
||||
## Tweet about **FastAPI**
|
||||
|
||||
<a href="https://twitter.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/tiangolo/fastapi cc @tiangolo" class="external-link" target="_blank">Tweet about **FastAPI**</a> and let me and others know why you like it.
|
||||
|
||||
## Let me know how are you using **FastAPI**
|
||||
<a href="https://twitter.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/tiangolo/fastapi cc @tiangolo" class="external-link" target="_blank">Tweet about **FastAPI**</a> and let me and others know why you like it. 🎉
|
||||
|
||||
I love to hear about how **FastAPI** is being used, what have you liked in it, in which project/company are you using it, etc.
|
||||
|
||||
You can let me know:
|
||||
|
||||
* <a href="https://twitter.com/compose/tweet?text=Hey @tiangolo, I'm using FastAPI at..." class="external-link" target="_blank">On **Twitter**</a>.
|
||||
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">On **Linkedin**</a>.
|
||||
* <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">On **Medium**</a>.
|
||||
|
||||
## Vote for FastAPI
|
||||
|
||||
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Vote for **FastAPI** in Slant</a>.
|
||||
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Vote for **FastAPI** in AlternativeTo</a>.
|
||||
* <a href="https://github.com/marmelab/awesome-rest/pull/93" class="external-link" target="_blank">Vote for **FastAPI** on awesome-rest</a>.
|
||||
|
||||
## Help others with issues in GitHub
|
||||
|
||||
You can see <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">existing issues</a> and try and help others.
|
||||
You can see <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">existing issues</a> and try and help others, most of the times they are questions that you might already know the answer for. 🤓
|
||||
|
||||
## Watch the GitHub repository
|
||||
|
||||
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>.
|
||||
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
|
||||
|
||||
If you select "Watching" instead of "Releases only", you will receive notifications when someone creates a new issue.
|
||||
|
||||
@@ -87,9 +70,10 @@ Then you can try and help them solving those issues.
|
||||
|
||||
You can <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">create a new issue</a> in the GitHub repository, for example to:
|
||||
|
||||
* Report a bug/issue.
|
||||
* Ask a question or ask about a problem.
|
||||
* Suggest a new feature.
|
||||
* Ask a question.
|
||||
|
||||
**Note**: if you create an issue then I'm going to ask you to also help others. 😉
|
||||
|
||||
## Create a Pull Request
|
||||
|
||||
@@ -100,6 +84,39 @@ You can <a href="https://github.com/tiangolo/fastapi" class="external-link" targ
|
||||
* To fix an existing issue/bug.
|
||||
* To add a new feature.
|
||||
|
||||
## Join the chat
|
||||
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
</a>
|
||||
|
||||
Join the chat on Gitter: <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">https://gitter.im/tiangolo/fastapi</a>.
|
||||
|
||||
There you can have quick conversations with others, help others, share ideas, etc.
|
||||
|
||||
But have in mind that as it allows more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers.
|
||||
|
||||
In GitHub issues the template will guide to to write the right question so that you can more easily get a good answer, or even solve the problem yourself even before asking. And in GitHub I can make sure I always answer everything, even if it takes some time. I can't personally do that with the Gitter chat. 😅
|
||||
|
||||
Conversations in Gitter are also not as easily searchable as in GitHub, so questions and answers might get lost in the conversation.
|
||||
|
||||
On the other side, there's more than 1000 people in the chat, so there's a high chance you'll find someone to talk to there, almost all the time. 😄
|
||||
|
||||
## Sponsor the author
|
||||
|
||||
You can also financially support the author (me) through <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>.
|
||||
|
||||
There you could buy me a coffee ☕️ to say thanks 😄.
|
||||
|
||||
## Sponsor the tools that power FastAPI
|
||||
|
||||
As you have seen in the documentation, FastAPI stands on the shoulders of giants, Starlette and Pydantic.
|
||||
|
||||
You can also sponsor:
|
||||
|
||||
* <a href="https://github.com/sponsors/samuelcolvin" class="external-link" target="_blank">Samuel Colvin (Pydantic)</a>
|
||||
* <a href="https://github.com/sponsors/encode" class="external-link" target="_blank">Encode (Starlette, Uvicorn)</a>
|
||||
|
||||
---
|
||||
|
||||
Thanks!
|
||||
Thanks! 🚀
|
||||
|
||||
BIN
docs/en/docs/img/tutorial/behind-a-proxy/image01.png
Normal file
BIN
docs/en/docs/img/tutorial/behind-a-proxy/image01.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
BIN
docs/en/docs/img/tutorial/behind-a-proxy/image02.png
Normal file
BIN
docs/en/docs/img/tutorial/behind-a-proxy/image02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -33,7 +33,7 @@ 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% *.
|
||||
* **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. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
@@ -45,38 +45,44 @@ The key features are:
|
||||
|
||||
## 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.*"
|
||||
"_[...] 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._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*I’m over the moon excited about **FastAPI**. It’s so fun!*"
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*"
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]*"
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"*We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]*"
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
@@ -2,6 +2,56 @@
|
||||
|
||||
## Latest changes
|
||||
|
||||
## 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/).
|
||||
* [Microservice in Python using FastAPI](https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc) by [Paurakh Sharma Humagain](https://twitter.com/PaurakhSharma).
|
||||
* [Build simple API service with Python FastAPI — Part 1](https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o) by [cuongld2](https://dev.to/cuongld2).
|
||||
* [FastAPI + Zeit.co = 🚀](https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/) by [Paul Sec](https://twitter.com/PaulWebSec).
|
||||
* [Build a web API from scratch with FastAPI - the workshop](https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe) by [Sebastián Ramírez (tiangolo)](https://twitter.com/tiangolo).
|
||||
* [Build a Secure Twilio Webhook with Python and FastAPI](https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi) by [Twilio](https://www.twilio.com).
|
||||
* [Using FastAPI with Django](https://www.stavros.io/posts/fastapi-with-django/) by [Stavros Korokithakis](https://twitter.com/Stavros).
|
||||
* [Introducing Dispatch](https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072) by [Netflix](https://netflixtechblog.com/).
|
||||
* **Podcasts**:
|
||||
* [Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)](https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/) by [Podcast.`__init__`](https://www.pythonpodcast.com/).
|
||||
* **Talks**:
|
||||
* [PyConBY 2020: Serve ML models easily with FastAPI](https://www.youtube.com/watch?v=z9K5pwb0rt8) by [Sebastián Ramírez (tiangolo)](https://twitter.com/tiangolo).
|
||||
* [[VIRTUAL] Py.Amsterdam's flying Software Circus: Intro to FastAPI](https://www.youtube.com/watch?v=PnpTY1f4k2U) by [Sebastián Ramírez (tiangolo)](https://twitter.com/tiangolo).
|
||||
* PR [#1467](https://github.com/tiangolo/fastapi/pull/1467).
|
||||
* Add translation to Chinese for [Python Types Intro - Python 类型提示简介](https://fastapi.tiangolo.com/zh/python-types/). PR [#1197](https://github.com/tiangolo/fastapi/pull/1197) by [@waynerv](https://github.com/waynerv).
|
||||
|
||||
## 0.55.1
|
||||
|
||||
* Fix handling of enums with their own schema in path parameters. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1463](https://github.com/tiangolo/fastapi/pull/1463).
|
||||
|
||||
## 0.55.0
|
||||
|
||||
* Allow enums to allow them to have their own schemas in OpenAPI. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1461](https://github.com/tiangolo/fastapi/pull/1461).
|
||||
* Add links for funding through [GitHub sponsors](https://github.com/sponsors/tiangolo). PR [#1425](https://github.com/tiangolo/fastapi/pull/1425).
|
||||
* Update issue template for for questions. PR [#1344](https://github.com/tiangolo/fastapi/pull/1344) by [@retnikt](https://github.com/retnikt).
|
||||
* Update warning about storing passwords in docs. PR [#1336](https://github.com/tiangolo/fastapi/pull/1336) by [@skorokithakis](https://github.com/skorokithakis).
|
||||
* Fix typo. PR [#1326](https://github.com/tiangolo/fastapi/pull/1326) by [@chenl](https://github.com/chenl).
|
||||
* Add translation to Portuguese for [Alternatives, Inspiration and Comparisons - Alternativas, Inspiração e Comparações](https://fastapi.tiangolo.com/pt/alternatives/). PR [#1325](https://github.com/tiangolo/fastapi/pull/1325) by [@Serrones](https://github.com/Serrones).
|
||||
* Fix 2 typos in docs. PR [#1324](https://github.com/tiangolo/fastapi/pull/1324) by [@waynerv](https://github.com/waynerv).
|
||||
* Update CORS docs, fix correct default of `max_age=600`. PR [#1301](https://github.com/tiangolo/fastapi/pull/1301) by [@derekbekoe](https://github.com/derekbekoe).
|
||||
* Add translation of [main page to Portuguese](https://fastapi.tiangolo.com/pt/). PR [#1300](https://github.com/tiangolo/fastapi/pull/1300) by [@Serrones](https://github.com/Serrones).
|
||||
* Re-word and clarify docs for extra info in fields. PR [#1299](https://github.com/tiangolo/fastapi/pull/1299) by [@chris-allnutt](https://github.com/chris-allnutt).
|
||||
* Make sure the `*` in short features in the docs is consistent (after `.`) in all languages. PR [#1424](https://github.com/tiangolo/fastapi/pull/1424).
|
||||
* Update order of execution for `get_db` in SQLAlchemy tutorial. PR [#1293](https://github.com/tiangolo/fastapi/pull/1293) by [@bcb](https://github.com/bcb).
|
||||
* Fix typos in Async docs. PR [#1423](https://github.com/tiangolo/fastapi/pull/1423).
|
||||
|
||||
## 0.54.2
|
||||
|
||||
* Add translation to Spanish for [Concurrency and async / await - Concurrencia y async / await](https://fastapi.tiangolo.com/es/async/). PR [#1290](https://github.com/tiangolo/fastapi/pull/1290) by [@alvaropernas](https://github.com/alvaropernas).
|
||||
|
||||
@@ -39,7 +39,7 @@ You can then use `Field` with model attributes:
|
||||
|
||||
You can declare extra information in `Field`, `Query`, `Body`, etc. And it will be included in the generated JSON Schema.
|
||||
|
||||
You will learn more about it later to declare examples examples.
|
||||
You will learn more about adding extra information later in the docs, when learning to declare examples.
|
||||
|
||||
## Recap
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ The following arguments are supported:
|
||||
* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for CORS requests.
|
||||
* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`.
|
||||
* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
|
||||
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `60`.
|
||||
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.
|
||||
|
||||
The middleware responds to two particular types of HTTP request...
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ So, in OpenAPI, each of the HTTP methods is called an "operation".
|
||||
|
||||
We are going to call them "**operations**" too.
|
||||
|
||||
#### Define a *path operation function*
|
||||
#### Define a *path operation decorator*
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
|
||||
@@ -115,7 +115,7 @@ So, you will receive a clean error, with an HTTP status code of `418` and a JSON
|
||||
|
||||
**FastAPI** has some default exception handlers.
|
||||
|
||||
These handlers are in charge or returning the default JSON responses when you `raise` an `HTTPException` and when the request has invalid data.
|
||||
These handlers are in charge of returning the default JSON responses when you `raise` an `HTTPException` and when the request has invalid data.
|
||||
|
||||
You can override these exception handlers with your own.
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ In this case, it might not be a problem, because the user himself is sending the
|
||||
But if we use the same model for another *path operation*, we could be sending our user's passwords to every client.
|
||||
|
||||
!!! danger
|
||||
Never send the plain password of a user in a response.
|
||||
Never store the plain password of a user or send it in a response.
|
||||
|
||||
## Add an output model
|
||||
|
||||
|
||||
@@ -92,7 +92,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
|
||||
|
||||
@@ -265,7 +265,7 @@ Para ver cómo lograr este paralelismo en producción, consulta la sección sobr
|
||||
|
||||
## `async` y `await`
|
||||
|
||||
Las versiones modernas de python tienen una forma muy intuitiva de definir código asíncrono. Esto hace que se vea como un código "secuencial" normal y que haga la "espera" por ti en los momentos correctos.
|
||||
Las versiones modernas de Python tienen una forma muy intuitiva de definir código asíncrono. Esto hace que se vea como un código "secuencial" normal y que haga la "espera" por ti en los momentos correctos.
|
||||
|
||||
Cuando hay una operación que requerirá esperar antes de dar los resultados y tiene soporte para estas nuevas características de Python, puedes programarlo como:
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ Sus características principales son:
|
||||
|
||||
* **Rapidez**: Alto rendimiento, a la par con **NodeJS** y **Go** (gracias a Starlette y Pydantic). [Uno de los frameworks de Python más rápidos](#rendimiento).
|
||||
|
||||
* **Rápido de programar**: Incrementa la velocidad de desarrollo entre 200% y 300% *.
|
||||
* **Menos errores**: Reduce los errores humanos (de programador) aproximadamente un 40% *.
|
||||
* **Rápido de programar**: Incrementa la velocidad de desarrollo entre 200% y 300%. *
|
||||
* **Menos errores**: Reduce los errores humanos (de programador) aproximadamente un 40%. *
|
||||
* **Intuitivo**: Gran soporte en los editores con <abbr title="conocido en inglés como auto-complete, autocompletion, IntelliSense, completion">auto completado</abbr> en todas partes. Gasta menos tiempo <abbr title="buscando y corrigiendo errores">debugging</abbr>.
|
||||
* **Fácil**: Está diseñado para ser fácil de usar y aprender. Gastando menos tiempo leyendo documentación.
|
||||
* **Corto**: Minimiza la duplicación de código. Múltiples funcionalidades con cada declaración de parámetros. Menos errores.
|
||||
@@ -44,38 +44,44 @@ Sus características principales son:
|
||||
|
||||
## Opiniones
|
||||
|
||||
"*[...] 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.*"
|
||||
"_[...] 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._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*I’m over the moon excited about **FastAPI**. It’s so fun!*"
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*"
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]*"
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"*We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]*"
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, el FastAPI de las CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
413
docs/pt/docs/alternatives.md
Normal file
413
docs/pt/docs/alternatives.md
Normal file
@@ -0,0 +1,413 @@
|
||||
# Alternativas, Inspiração e Comparações
|
||||
|
||||
O que inspirou **FastAPI**, como ele se compara a outras alternativas e o que FastAPI aprendeu delas.
|
||||
|
||||
## Introdução
|
||||
|
||||
**FastAPI** não poderia existir se não fosse pelos trabalhos anteriores de outras pessoas.
|
||||
|
||||
Houveram tantas ferramentas criadas que ajudaram a inspirar sua criação.
|
||||
|
||||
Tenho evitado criar um novo framework por anos. Primeiramente tentei resolver todos os recursos cobertos pelo **FastAPI** utilizando muitos frameworks diferentes, plug-ins e ferramentas.
|
||||
|
||||
Mas em algum ponto, não houve outra opção senão criar algo que fornecesse todos esses recursos, pegando as melhores idéias de ferramentas anteriores, e combinando eles da melhor forma possível, utilizando recursos da linguagem que não estavam disponíveis antes (_Type Hints_ no Python 3.6+).
|
||||
|
||||
## Ferramentas anteriores
|
||||
|
||||
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
|
||||
|
||||
É o framework mais popular e largamente confiável. É utilizado para construir sistemas como o _Instagram_.
|
||||
|
||||
É bem acoplado com banco de dados relacional (como MySQL ou PostgreSQL), então, tendo um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra etc) como a principal ferramenta de armazenamento não é muito fácil.
|
||||
|
||||
Foi criado para gerar HTML no _backend_, não para criar APIs utilizando um _frontend_ moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos <abbr title="Internet das Coisas">IoT</abbr>) comunicando com ele.
|
||||
|
||||
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
|
||||
|
||||
Django REST framework foi criado para ser uma caixa de ferramentas flexível para construção de APIs web utilizando Django por baixo, para melhorar suas capacidades de API.
|
||||
|
||||
Ele é utilizado por muitas companhias incluindo Mozilla, Red Hat e Eventbrite.
|
||||
|
||||
Ele foi um dos primeiros exemplos de **documentação automática de API**, e essa foi especificamente uma das primeiras idéias que inspirou "a busca por" **FastAPI**.
|
||||
|
||||
!!! note "Nota"
|
||||
Django REST Framework foi criado por Tom Christie. O mesmo criador de Starlette e Uvicorn, nos quais **FastAPI** é baseado.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Ter uma documentação automática da API em interface web.
|
||||
|
||||
### <a href="http://flask.pocoo.org/" class="external-link" target="_blank">Flask</a>
|
||||
|
||||
Flask é um "microframework", não inclui integração com banco de dados nem muitas das coisas que vêm por padrão no Django.
|
||||
|
||||
Sua simplicidade e flexibilidade permitem fazer coisas como utilizar bancos de dados NoSQL como principal sistema de armazenamento de dados.
|
||||
|
||||
Por ser tão simples, é relativamente intuitivo de aprender, embora a documentação esteja de forma mais técnica em alguns pontos.
|
||||
|
||||
Ele é comumente utilizado por outras aplicações que não necessariamente precisam de banco de dados, gerenciamento de usuários, ou algum dos muitos recursos que já vem instalados no Django. Embora muitos desses recursos possam ser adicionados com plug-ins.
|
||||
|
||||
Esse desacoplamento de partes, e sendo um "microframework" que pode ser extendido para cobrir exatamente o que é necessário era um recurso chave que eu queria manter.
|
||||
|
||||
Dada a simplicidade do Flask, parecia uma ótima opção para construção de APIs. A próxima coisa a procurar era um "Django REST Framework" para Flask.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Ser um microframework. Fazer ele fácil para misturar e combinar com ferramentas e partes necessárias.
|
||||
|
||||
Ser simples e com sistema de roteamento fácil de usar.
|
||||
|
||||
### <a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests</a>
|
||||
|
||||
**FastAPI** não é uma alternativa para **Requests**. O escopo deles é muito diferente.
|
||||
|
||||
Na verdade é comum utilizar Requests *dentro* de uma aplicação FastAPI.
|
||||
|
||||
Ainda assim, FastAPI pegou alguma inspiração do Requests.
|
||||
|
||||
**Requests** é uma biblioteca para interagir com APIs (como um cliente), enquanto **FastAPI** é uma biblioteca para *construir* APIs (como um servidor).
|
||||
|
||||
Eles estão, mais ou menos, em pontas opostas, um complementando o outro.
|
||||
|
||||
Requests tem um projeto muito simples e intuitivo, fácil de usar, com padrões sensíveis. Mas ao mesmo tempo, é muito poderoso e customizável.
|
||||
|
||||
É por isso que, como dito no site oficial:
|
||||
|
||||
> Requests é um dos pacotes Python mais baixados de todos os tempos
|
||||
|
||||
O jeito de usar é muito simples. Por exemplo, para fazer uma requisição `GET`, você deveria escrever:
|
||||
|
||||
```Python
|
||||
response = requests.get("http://example.com/some/url")
|
||||
```
|
||||
|
||||
A contra-parte da aplicação FastAPI, *rota de operação*, poderia parecer como:
|
||||
|
||||
```Python hl_lines="1"
|
||||
@app.get("/some/url")
|
||||
def read_url():
|
||||
return {"message": "Hello World"}
|
||||
```
|
||||
|
||||
Veja as similaridades em `requests.get(...)` e `@app.get(...)`.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
* Ter uma API simples e intuitiva.
|
||||
* Utilizar nomes de métodos HTTP (operações) diretamente, de um jeito direto e intuitivo.
|
||||
* Ter padrões sensíveis, mas customizações poderosas.
|
||||
|
||||
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
|
||||
|
||||
O principal recurso que eu queria do Django REST Framework era a documentação automática da API.
|
||||
|
||||
Então eu descobri que existia um padrão para documentar APIs, utilizando JSON (ou YAML, uma extensão do JSON) chamado Swagger.
|
||||
|
||||
E tinha uma interface web para APIs Swagger já criada. Então, sendo capaz de gerar documentação Swagger para uma API poderia permitir utilizar essa interface web automaticamente.
|
||||
|
||||
Em algum ponto, Swagger foi dado para a Fundação Linux, e foi renomeado OpenAPI.
|
||||
|
||||
Isso acontece porquê quando alguém fala sobre a versão 2.0 é comum dizer "Swagger", e para a versão 3+, "OpenAPI".
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Adotar e usar um padrão aberto para especificações API, ao invés de algum esquema customizado.
|
||||
|
||||
E integrar ferramentas de interface para usuários baseado nos padrões:
|
||||
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
|
||||
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
|
||||
|
||||
Esses dois foram escolhidos por serem bem populares e estáveis, mas fazendo uma pesquisa rápida, você pode encontrar dúzias de interfaces alternativas adicionais para OpenAPI (assim você poderá utilizar com **FastAPI**).
|
||||
|
||||
### Flask REST frameworks
|
||||
|
||||
Existem vários Flask REST frameworks, mas depois de investir tempo e trabalho investigando eles, eu descobri que muitos estão descontinuados ou abandonados, com alguns tendo questões que fizeram eles inadequados.
|
||||
|
||||
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a>
|
||||
|
||||
Um dos principais recursos necessários em sistemas API é "<abbr title="também chamado _ marshalling, conversão">serialização</abbr>" de dados, que é pegar dados do código (Python) e converter eles em alguma coisa que possa ser enviado através da rede. Por exemplo, converter um objeto contendo dados de um banco de dados em um objeto JSON. Converter objetos `datetime` em strings etc.
|
||||
|
||||
Outro grande recurso necessário nas APIs é validação de dados, certificando que os dados são válidos, dados certos parâmetros. Por exemplo, algum campo é `int`, e não alguma string aleatória. Isso é especialmente útil para dados que estão chegando.
|
||||
|
||||
Sem um sistema de validação de dados, você teria que realizar todas as verificações manualmente, no código.
|
||||
|
||||
Esses recursos são o que Marshmallow foi construído para fornecer. Ele é uma ótima biblioteca, e eu já utilizei muito antes.
|
||||
|
||||
Mas ele foi criado antes da existência do _type hints_ do Python. Então, para definir todo o <abbr title="definição de como os dados devem ser formados">_schema_</abbr> você precisa utilizar específicas ferramentas e classes fornecidas pelo Marshmallow.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Usar código para definir "schemas" que forneçam, automaticamente, tipos de dados e validação.
|
||||
|
||||
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
|
||||
|
||||
Outro grande recurso necessário pelas APIs é a <abbr title="ler e converter para dados Python">análise</abbr> de dados vindos de requisições.
|
||||
|
||||
Webargs é uma ferramente feita para fornecer o que está no topo de vários frameworks, inclusive Flask.
|
||||
|
||||
Ele utiliza Marshmallow por baixo para validação de dados. E ele foi criado pelos mesmos desenvolvedores.
|
||||
|
||||
Ele é uma grande ferramenta e eu também a utilizei muito, antes de ter o **FastAPI**.
|
||||
|
||||
!!! info
|
||||
Webargs foi criado pelos mesmos desenvolvedores do Marshmallow.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Ter validação automática de dados vindos de requisições.
|
||||
|
||||
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
|
||||
|
||||
Marshmallow e Webargs fornecem validação, análise e serialização como plug-ins.
|
||||
|
||||
Mas a documentação ainda está faltando. Então APISpec foi criado.
|
||||
|
||||
APISpec tem plug-ins para muitos frameworks (e tem um plug-in para Starlette também).
|
||||
|
||||
O jeito como ele funciona é que você escreve a definição do _schema_ usando formato YAML dentro da _docstring_ de cada função controlando uma rota.
|
||||
|
||||
E ele gera _schemas_ OpenAPI.
|
||||
|
||||
É assim como funciona no Flask, Starlette, Responder etc.
|
||||
|
||||
Mas então, nós temos novamente o problema de ter uma micro-sintaxe, dentro de uma string Python (um grande YAML).
|
||||
|
||||
O editor não poderá ajudar muito com isso. E se nós modificarmos os parâmetros dos _schemas_ do Marshmallow e esquecer de modificar também aquela _docstring_ YAML, o _schema_ gerado pode ficar obsoleto.
|
||||
|
||||
!!! info
|
||||
APISpec foi criado pelos mesmos desenvolvedores do Marshmallow.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Dar suporte a padrões abertos para APIs, OpenAPI.
|
||||
|
||||
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
|
||||
|
||||
É um plug-in Flask, que amarra junto Webargs, Marshmallow e APISpec.
|
||||
|
||||
Ele utiliza a informação do Webargs e Marshmallow para gerar automaticamente _schemas_ OpenAPI, usando APISpec.
|
||||
|
||||
É uma grande ferramenta, mas muito subestimada. Ela deveria ser um pouco mais popular do que muitos outros plug-ins Flask. É de ser esperado que sua documentação seja bem concisa e abstrata.
|
||||
|
||||
Isso resolveu o problema de ter que escrever YAML (outra sintaxe) dentro das _docstrings_ Python.
|
||||
|
||||
Essa combinação de Flask, Flask-apispec com Marshmallow e Webargs foi meu _backend stack_ favorito até construir **FastAPI**.
|
||||
|
||||
Usando essa combinação levou a criação de vários geradores Flask _full-stack_. Há muitas _stacks_ que eu (e vários times externos) estou utilizando até agora:
|
||||
|
||||
* <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
|
||||
* <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
|
||||
* <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
|
||||
|
||||
E esses mesmos geradores _full-stack_ foram a base dos [Geradores de Projetos **FastAPI**](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
!!! info
|
||||
Flask-apispec foi criado pelos mesmos desenvolvedores do Marshmallow.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Gerar _schema_ OpenAPI automaticamente, a partir do mesmo código que define serialização e validação.
|
||||
|
||||
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (and <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>)
|
||||
|
||||
NestJS, que não é nem Python, é um framework NodeJS JavaScript (TypeScript) inspirado pelo Angular.
|
||||
|
||||
Ele alcança de uma forma similar ao que pode ser feito com o Flask-apispec.
|
||||
|
||||
Ele tem um sistema de injeção de dependência integrado, inspirado pelo Angular dois. É necessário fazer o pré-registro dos "injetáveis" (como todos os sistemas de injeção de dependência que conheço), então, adicionando verbosidade e repetição de código.
|
||||
|
||||
Como os parâmetros são descritos com tipos TypeScript (similar aos _type hints_ do Python), o suporte ao editor é muito bom.
|
||||
|
||||
Mas como os dados TypeScript não são preservados após a compilação para o JavaScript, ele não pode depender dos tipos para definir a validação, serialização e documentação ao mesmo tempo. Devido a isso e a algumas decisões de projeto, para pegar a validação, serialização e geração automática do _schema_, é necessário adicionar decoradores em muitos lugares. Então, ele se torna muito verboso.
|
||||
|
||||
Ele também não controla modelos aninhados muito bem. Então, se o corpo JSON na requisição for um objeto JSON que contém campos internos que contém objetos JSON aninhados, ele não consegue ser validado e documentado apropriadamente.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Usar tipos Python para ter um ótimo suporte do editor.
|
||||
|
||||
Ter um sistema de injeção de dependência poderoso. Achar um jeito de minimizar repetição de código.
|
||||
|
||||
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
|
||||
|
||||
Ele foi um dos primeiros frameworks Python extremamente rápido baseado em `asyncio`. Ele foi feito para ser muito similar ao Flask.
|
||||
|
||||
!!! note "Detalhes técnicos"
|
||||
Ele utiliza <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> ao invés do '_loop_' `asyncio` padrão do Python. É isso que deixa ele tão rápido.
|
||||
|
||||
Ele claramente inspirou Uvicorn e Starlette, que são atualmente mais rápidos que o Sanic em testes de performance abertos.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Achar um jeito de ter uma performance insana.
|
||||
|
||||
É por isso que o **FastAPI** é baseado em Starlette, para que ele seja o framework mais rápido disponível (performance testada por terceiros).
|
||||
|
||||
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
|
||||
|
||||
Falcon é outro framework Python de alta performance, e é projetado para ser minimalista, e funciona como fundação de outros frameworks como Hug.
|
||||
|
||||
Ele usa o padrão anterior para frameworks web Python (WSGI) que é síncrono, então ele não pode controlar _WebSockets_ e outros casos de uso. No entanto, ele também tem uma boa performance.
|
||||
|
||||
Ele é projetado para ter funções que recebem dois parâmetros, uma "requisição" e uma "resposta". Então você "lê" as partes da requisição, e "escreve" partes para a resposta. Devido ao seu design, não é possível declarar parâmetros de requisição e corpos com _type hints_ Python padrão como parâmetros de funções.
|
||||
|
||||
Então, validação de dados, serialização e documentação tem que ser feitos no código, não automaticamente. Ou eles terão que ser implementados como um framework acima do Falcon, como o Hug. Essa mesma distinção acontece em outros frameworks que são inspirados pelo design do Falcon, tendo um objeto de requisição e um objeto de resposta como parâmetros.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Achar jeitos de conseguir melhor performance.
|
||||
|
||||
Juntamente com Hug (como Hug é baseado no Falcon) inspirou **FastAPI** para declarar um parâmetro de `resposta`nas funções.
|
||||
|
||||
Embora no FastAPI seja opcional, é utilizado principalmente para configurar cabeçalhos, cookies e códigos de status alternativos.
|
||||
|
||||
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
|
||||
|
||||
Eu descobri Molten nos primeiros estágios da construção do **FastAPI**. E ele tem umas idéias bem similares:
|
||||
|
||||
* Baseado em _type hints_ Python.
|
||||
* Validação e documentação desses tipos.
|
||||
* Sistema de injeção de dependência.
|
||||
|
||||
Ele não utiliza validação de dados, seriallização e documentação de bibliotecas de terceiros como o Pydantic, ele tem seu prórpio. Então, essas definições de tipo de dados não podem ser reutilizados tão facilmente.
|
||||
|
||||
Ele exige um pouco mais de verbosidade nas configurações. E como é baseado no WSGI (ao invés de ASGI), ele não é projetado para ter a vantagem da alta performance fornecida por ferramentas como Uvicorn, Starlette e Sanic.
|
||||
|
||||
O sistema de injeção de dependência exige pré-registro das dependências e as dependências são resolvidas baseadas nos tipos declarados. Então, não é possível declarar mais do que um "componente" que fornece um certo tipo.
|
||||
|
||||
Rotas são declaradas em um único lugar, usando funções declaradas em outros lugares (ao invés de usar decoradores que possam ser colocados diretamente acima da função que controla o _endpoint_). Isso é mais perto de como o Django faz isso do que como Flask (e Starlette) faz. Ele separa no código coisas que são relativamente amarradas.
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Definir validações extras para tipos de dados usando valores "padrão" de atributos dos modelos. Isso melhora o suporte do editor, e não estava disponível no Pydantic antes.
|
||||
|
||||
Isso na verdade inspirou a atualização de partes do Pydantic, para dar suporte ao mesmo estilo de declaração da validação (toda essa funcionalidade já está disponível no Pydantic).
|
||||
|
||||
### <a href="http://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug foi um dos primeiros frameworks a implementar a declaração de tipos de parâmetros usando Python _type hints_. Isso foi uma ótima idéia que inspirou outras ferramentas a fazer o mesmo.
|
||||
|
||||
Ele usou tipos customizados em suas declarações ao invés dos tipos padrão Python, mas mesmo assim foi um grande passo.
|
||||
|
||||
Ele também foi um dos primeiros frameworks a gerar um _schema_ customizado declarando a API inteira em JSON.
|
||||
|
||||
Ele não era baseado em um padrão como OpenAPI e JSON Schema. Então não poderia ter interação direta com outras ferramentas, como Swagger UI. Mas novamente, era uma idéia muito inovadora.
|
||||
|
||||
Hug tinha um incomum, interessante recurso: usando o mesmo framework, é possível criar tanto APIs como CLIs.
|
||||
|
||||
Como é baseado nos padrões anteriores de frameworks web síncronos (WSGI), ele não pode controlar _Websockets_ e outras coisas, embora ele ainda tenha uma alta performance também.
|
||||
|
||||
!!! info
|
||||
Hug foi criado por Timothy Crosley, o mesmo criador do <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, uma grande ferramenta para ordenação automática de _imports_ em arquivos Python.
|
||||
|
||||
!!! check "Idéias inspiradas para o **FastAPI**"
|
||||
Hug inspirou partes do APIStar, e foi uma das ferramentas que eu achei mais promissora, ao lado do APIStar.
|
||||
|
||||
Hug ajudou a inspirar o **FastAPI** a usar _type hints_ do Python para declarar parâmetros, e para gerar um _schema_ definindo a API automaticamente.
|
||||
|
||||
Hug inspirou **FastAPI** a declarar um parâmetro de `resposta` em funções para definir cabeçalhos e cookies.
|
||||
|
||||
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5)
|
||||
|
||||
Antes de decidir construir **FastAPI** eu encontrei o servidor **APIStar**. Tinha quase tudo que eu estava procurando e tinha um grande projeto.
|
||||
|
||||
Ele foi uma das primeiras implementações de um framework usando Python _type hints_ para declarar parâmetros e requisições que eu nunca vi (antes no NestJS e Molten). Eu encontrei ele mais ou menos na mesma época que o Hug. Mas o APIStar utilizava o padrão OpenAPI.
|
||||
|
||||
Ele tinha validação de dados automática, serialização de dados e geração de _schema_ OpenAPI baseado nos mesmos _type hints_ em vários locais.
|
||||
|
||||
Definições de _schema_ de corpo não utilizavam os mesmos Python _type hints_ como Pydantic, ele era um pouco mais similar ao Marshmallow, então, o suporte ao editor não seria tão bom, ainda assim, APIStar era a melhor opção disponível.
|
||||
|
||||
Ele obteve as melhores performances em testes na época (somente batido por Starlette).
|
||||
|
||||
A princípio, ele não tinha uma interface web com documentação automática da API, mas eu sabia que poderia adicionar o Swagger UI a ele.
|
||||
|
||||
Ele tinha um sistema de injeção de dependência. Ele exigia pré-registro dos componentes, como outras ferramentas já discutidas acima. Mas ainda era um grande recurso.
|
||||
|
||||
Eu nunca fui capaz de usar ele num projeto inteiro, por não ter integração de segurança, então, eu não pude substituir todos os recursos que eu tinha com os geradores _full-stack_ baseados no Flask-apispec. Eu tive em minha gaveta de projetos a idéia de criar um _pull request_ adicionando essa funcionalidade.
|
||||
|
||||
Mas então, o foco do projeto mudou.
|
||||
|
||||
Ele não era mais um framework web API, como o criador precisava focar no Starlette.
|
||||
|
||||
Agora APIStar é um conjunto de ferramentas para validar especificações OpenAPI, não um framework web.
|
||||
|
||||
!!! info
|
||||
APIStar foi criado por Tom Christie. O mesmo cara que criou:
|
||||
|
||||
* Django REST Framework
|
||||
* Starlette (no qual **FastAPI** é baseado)
|
||||
* Uvicorn (usado por Starlette e **FastAPI**)
|
||||
|
||||
!!! check "**FastAPI** inspirado para"
|
||||
Existir.
|
||||
|
||||
A idéia de declarar múltiplas coisas (validação de dados, serialização e documentação) com os mesmos tipos Python, que ao mesmo tempo fornecesse grande suporte ao editor, era algo que eu considerava uma brilhante idéia.
|
||||
|
||||
E após procurar por um logo tempo por um framework similar e testar muitas alternativas diferentes, APIStar foi a melhor opção disponível.
|
||||
|
||||
Então APIStar parou de existir como um servidor e Starlette foi criado, e foi uma nova melhor fundação para tal sistema. Essa foi a inspiração final para construir **FastAPI**.
|
||||
|
||||
Eu considero **FastAPI** um "sucessor espiritual" para o APIStar, evoluindo e melhorando os recursos, sistema de tipagem e outras partes, baseado na aprendizagem de todas essas ferramentas acima.
|
||||
|
||||
## Usados por **FastAPI**
|
||||
|
||||
### <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>
|
||||
|
||||
Pydantic é uma biblioteca para definir validação de dados, serialização e documentação (usando JSON Schema) baseado nos Python _type hints_.
|
||||
|
||||
Isso faz dele extremamente intuitivo.
|
||||
|
||||
Ele é comparável ao Marshmallow. Embora ele seja mais rápido que Marshmallow em testes de performance. E ele é baseado nos mesmos Python _type hints_, o suporte ao editor é ótimo.
|
||||
|
||||
!!! check "**FastAPI** usa isso para"
|
||||
Controlar toda a validação de dados, serialização de dados e modelo de documentação automática (baseado no JSON Schema).
|
||||
|
||||
**FastAPI** então pega dados do JSON Schema e coloca eles no OpenAPI, à parte de todas as outras coisas que ele faz.
|
||||
|
||||
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
|
||||
|
||||
Starlette é um framework/caixa de ferramentas <abbr title="O novo padrão para construção de Python web assíncrono">ASGI</abbr> peso leve, o que é ideal para construir serviços assíncronos de alta performance.
|
||||
|
||||
Ele é muito simples e intuitivo. É projetado para ser extensível facilmente, e ter componentes modulares.
|
||||
|
||||
Ele tem:
|
||||
|
||||
* Performance seriamente impressionante.
|
||||
* Suporte a WebSocket.
|
||||
* Suporte a GraphQL.
|
||||
* Tarefas de processamento interno por trás dos panos.
|
||||
* Eventos de inicialização e encerramento.
|
||||
* Cliente de testes construído com requests.
|
||||
* Respostas CORS, GZip, Arquivos Estáticos, Streaming.
|
||||
* Suporte para Sessão e Cookie.
|
||||
* 100% coberto por testes.
|
||||
* Código base 100% anotado com tipagem.
|
||||
* Dependências complexas Zero.
|
||||
|
||||
Starlette é atualmente o mais rápido framework Python testado. Somente ultrapassado pelo Uvicorn, que não é um framework, mas um servidor.
|
||||
|
||||
Starlette fornece toda a funcionalidade básica de um microframework web.
|
||||
|
||||
Mas ele não fornece validação de dados automática, serialização e documentação.
|
||||
|
||||
Essa é uma das principais coisas que **FastAPI** adiciona no topo, tudo baseado em Python _type hints_ (usando Pydantic). Isso, mais o sistema de injeção de dependência, utilidades de segurança, geração de _schema_ OpenAPI, etc.
|
||||
|
||||
!!! note "Detalhes Técnicos"
|
||||
ASGI é um novo "padrão" sendo desenvolvido pelos membros do time central do Django. Ele ainda não está como "Padrão Python" (PEP), embora eles estejam em processo de fazer isso.
|
||||
|
||||
No entanto, ele já está sendo utilizado como "padrão" por diversas ferramentas. Isso melhora enormemente a interoperabilidade, como você poderia trocar Uvicorn por qualquer outro servidor ASGI (como Daphne ou Hypercorn), ou você poderia adicionar ferramentas compatíveis com ASGI, como `python-socketio`.
|
||||
|
||||
!!! check "**FastAPI** usa isso para"
|
||||
Controlar todas as partes web centrais. Adiciona recursos no topo.
|
||||
|
||||
A classe `FastAPI` em si herda `Starlette`.
|
||||
|
||||
Então, qualquer coisa que você faz com Starlette, você pode fazer diretamente com **FastAPI**, pois ele é basicamente um Starlette com esteróides.
|
||||
|
||||
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>
|
||||
|
||||
Uvicorn é um servidor ASGI peso leve, construído com uvloop e httptools.
|
||||
|
||||
Ele não é um framework web, mas sim um servidor. Por exemplo, ele não fornece ferramentas para roteamento por rotas. Isso é algo que um framework como Starlette (ou **FastAPI**) poderia fornecer por cima.
|
||||
|
||||
Ele é o servidor recomendado para Starlette e **FastAPI**.
|
||||
|
||||
!!! check "**FastAPI** recomenda isso para"
|
||||
O principal servidor web para rodar aplicações **FastAPI**.
|
||||
|
||||
Você pode combinar ele com o Gunicorn, para ter um servidor multi-processos assíncrono.
|
||||
|
||||
Verifique mais detalhes na seção [Deployment](deployment.md){.internal-link target=_blank}.
|
||||
|
||||
## Performance e velocidade
|
||||
|
||||
Para entender, comparar e ver a diferença entre Uvicorn, Starlette e FastAPI, verifique a seção sobre [Benchmarks](benchmarks.md){.internal-link target=_blank}.
|
||||
@@ -1,12 +1,8 @@
|
||||
|
||||
{!../../../docs/missing-translation.md!}
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
<em>Framework FastAPI, alta performance, fácil de aprender, fácil de codar, pronto para produção</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
@@ -25,80 +21,79 @@
|
||||
|
||||
---
|
||||
|
||||
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
**Documentação**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
**Código fonte**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||
FastAPI é um moderno e rápido (alta performance) _framework web_ para construção de APIs com Python 3.6 ou superior, baseado nos _type hints_ padrões do Python.
|
||||
|
||||
The key features are:
|
||||
Os recursos chave são:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
* **Rápido**: alta performance, equivalente a **NodeJS** e **Go** (graças ao Starlette e Pydantic). [Um dos frameworks mais rápidos disponíveis](#performance).
|
||||
* **Rápido para codar**: Aumenta a velocidade para desenvolver recursos entre 200% a 300%. *
|
||||
* **Poucos bugs**: Reduz cerca de 40% de erros iduzidos por humanos (desenvolvedores). *
|
||||
* **Intuitivo**: Grande suporte a _IDEs_. <abbr title="também conhecido como _auto-complete_, _autocompletion_, _IntelliSense_">_Auto-Complete_</abbr> em todos os lugares. Menos tempo debugando.
|
||||
* **Fácil**: Projetado para ser fácil de aprender e usar. Menos tempo lendo documentação.
|
||||
* **Enxuto**: Minimize duplicação de código. Múltiplos recursos para cada declaração de parâmetro. Menos bugs.
|
||||
* **Robusto**: Tenha código pronto para produção. E com documentação interativa automática.
|
||||
* **Baseado em padrões**: Baseado em (e totalmente compatível com) os padrões abertos para APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (anteriormente conhecido como Swagger) e <a href="http://json-schema.org/" class="external-link" target="_blank">_JSON Schema_</a>.
|
||||
|
||||
* **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. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
|
||||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
<small>* estimativas baseadas em testes realizados com equipe interna de desenvolvimento, construindo aplicações em produção.</small>
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
## Opiniões
|
||||
|
||||
## 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.*"
|
||||
"*[...] Estou usando **FastAPI** muito esses dias. [...] Estou na verdade planejando utilizar ele em todos os times de **serviços _Machine Learning_ na Microsoft**. Alguns deles estão sendo integrados no _core_ do produto **Windows** e alguns produtos **Office**.*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*I’m over the moon excited about **FastAPI**. It’s so fun!*"
|
||||
"*Estou extremamente entusiasmado com o **FastAPI**. É tão divertido!*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcaster</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*"
|
||||
"*Honestamente, o que você construiu parece super sólido e rebuscado. De muitas formas, eu queria que o **Hug** fosse assim - é realmente inspirador ver alguém que construiu ele.*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>criador do<a href="http://www.hug.rest/" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]*"
|
||||
"*Se você está procurando aprender um **_framework_ moderno** para construir aplicações _REST_, dê uma olhada no **FastAPI** [...] É rápido, fácil de usar e fácil de aprender [...]*"
|
||||
|
||||
"*We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]*"
|
||||
"*Nós trocamos nossas **APIs** por **FastAPI** [...] Acredito que vocês gostarão dele [...]*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong>fundadores da <a href="https://explosion.ai" target="_blank">Explosion AI</a> - criadores da <a href="https://spacy.io" target="_blank">spaCy</a></strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]*"
|
||||
"*Nós adotamos a biblioteca **FastAPI** para criar um servidor **REST** que possa ser chamado para obter **predições**. [para o Ludwig]*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin e Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
## **Typer**, o FastAPI das interfaces de linhas de comando
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
Se você estiver construindo uma aplicação <abbr title="Command Line Interface">_CLI_</abbr> para ser utilizada em um terminal ao invés de uma aplicação web, dê uma olhada no <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
|
||||
**Typer** é o irmão menor do FastAPI. E seu propósito é ser o **FastAPI das _CLIs_**. ⌨️ 🚀
|
||||
|
||||
## Requirements
|
||||
## Requisitos
|
||||
|
||||
Python 3.6+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
FastAPI está nos ombros de gigantes:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> para as partes web.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> para a parte de dados.
|
||||
|
||||
## Installation
|
||||
## Instalação
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -110,7 +105,7 @@ $ pip install fastapi
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
Você também precisará de um servidor ASGI para produção, tal como <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> ou <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -122,11 +117,11 @@ $ pip install uvicorn
|
||||
|
||||
</div>
|
||||
|
||||
## Example
|
||||
## Exemplo
|
||||
|
||||
### Create it
|
||||
### Crie
|
||||
|
||||
* Create a file `main.py` with:
|
||||
* Crie um arquivo `main.py` com:
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
@@ -145,9 +140,9 @@ def read_item(item_id: int, q: str = None):
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Or use <code>async def</code>...</summary>
|
||||
<summary>Ou use <code>async def</code>...</summary>
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
Se seu código utiliza `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
from fastapi import FastAPI
|
||||
@@ -165,79 +160,79 @@ async def read_item(item_id: int, q: str = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Note**:
|
||||
**Nota**:
|
||||
|
||||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
Se você não sabe, verifique a seção _"In a hurry?"_ sobre <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` e `await` nas docs</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Run it
|
||||
### Rode
|
||||
|
||||
Run the server with:
|
||||
Rode o servidor com:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
<span style="color: green;">INFO</span>: Started reloader process [28720]
|
||||
<span style="color: green;">INFO</span>: Started server process [28722]
|
||||
<span style="color: green;">INFO</span>: Waiting for application startup.
|
||||
<span style="color: green;">INFO</span>: Application startup complete.
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
|
||||
<summary>Sobre o comando <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
The command `uvicorn main:app` refers to:
|
||||
O comando `uvicorn main:app` se refere a:
|
||||
|
||||
* `main`: the file `main.py` (the Python "module").
|
||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||
* `--reload`: make the server restart after code changes. Only do this for development.
|
||||
* `main`: o arquivo `main.py` (o "módulo" Python).
|
||||
* `app`: o objeto criado dentro de `main.py` com a linha `app = FastAPI()`.
|
||||
* `--reload`: faz o servidor recarregar após mudanças de código. Somente faça isso para desenvolvimento.
|
||||
|
||||
</details>
|
||||
|
||||
### Check it
|
||||
### Verifique
|
||||
|
||||
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
Abra seu navegador em <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
You will see the JSON response as:
|
||||
Você verá a resposta JSON como:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
You already created an API that:
|
||||
Você acabou de criar uma API que:
|
||||
|
||||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
|
||||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
|
||||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
||||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
||||
* Recebe requisições HTTP nas _rotas_ `/` e `/items/{item_id}`.
|
||||
* Ambas _rotas_ fazem <em>operações</em> `GET` (também conhecido como _métodos_ HTTP).
|
||||
* A _rota_ `/items/{item_id}` tem um _parâmetro de rota_ `item_id` que deve ser um `int`.
|
||||
* A _rota_ `/items/{item_id}` tem um _parâmetro query_ `q` `str` opcional.
|
||||
|
||||
### Interactive API docs
|
||||
### Documentação Interativa da API
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
Agora vá para <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
Você verá a documentação automática interativa da API (fornecida por <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Alternative API docs
|
||||
### Documentação Alternativa da API
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
E agora, vá para <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
Você verá a documentação automática alternativa (fornecida por <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Example upgrade
|
||||
## Evoluindo o Exemplo
|
||||
|
||||
Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
Agora modifique o arquivo `main.py` para receber um corpo para uma requisição `PUT`.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
Declare o corpo utilizando tipos padrão Python, graças ao Pydantic.
|
||||
|
||||
```Python hl_lines="2 7 8 9 10 23 24 25"
|
||||
from fastapi import FastAPI
|
||||
@@ -267,175 +262,175 @@ def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
|
||||
O servidor deverá recarregar automaticamente (porquê você adicionou `--reload` ao comando `uvicorn` acima).
|
||||
|
||||
### Interactive API docs upgrade
|
||||
### Evoluindo a Documentação Interativa da API
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
Agora vá para <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* The interactive API documentation will be automatically updated, including the new body:
|
||||
* A documentação interativa da API será automaticamente atualizada, incluindo o novo corpo:
|
||||
|
||||

|
||||
|
||||
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
|
||||
* Clique no botão "Try it out", ele permiirá que você preencha os parâmetros e interaja diretamente com a API:
|
||||
|
||||

|
||||
|
||||
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
|
||||
* Então clique no botão "Execute", a interface do usuário irá se comunicar com a API, enviar os parâmetros, pegar os resultados e mostrá-los na tela:
|
||||
|
||||

|
||||
|
||||
### Alternative API docs upgrade
|
||||
### Evoluindo a Documentação Alternativa da API
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
E agora, vá para <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* The alternative documentation will also reflect the new query parameter and body:
|
||||
* A documentação alternativa também irá refletir o novo parâmetro da _query_ e o corpo:
|
||||
|
||||

|
||||
|
||||
### Recap
|
||||
### Recapitulando
|
||||
|
||||
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
|
||||
Resumindo, você declara **uma vez** os tipos dos parâmetros, corpo etc. como parâmetros de função.
|
||||
|
||||
You do that with standard modern Python types.
|
||||
Você faz com tipos padrão do Python moderno.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
Você não terá que aprender uma nova sintaxe, métodos ou classes de uma biblioteca específica etc.
|
||||
|
||||
Just standard **Python 3.6+**.
|
||||
Apenas **Python 3.6+** padrão.
|
||||
|
||||
For example, for an `int`:
|
||||
Por exemplo, para um `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
or for a more complex `Item` model:
|
||||
ou para um modelo mais complexo, `Item`:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...and with that single declaration you get:
|
||||
...e com essa única declaração você tem:
|
||||
|
||||
* Editor support, including:
|
||||
* Completion.
|
||||
* Type checks.
|
||||
* Validation of data:
|
||||
* Automatic and clear errors when the data is invalid.
|
||||
* Validation even for deeply nested JSON objects.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
|
||||
* Suporte ao Editor, incluindo:
|
||||
* Completação.
|
||||
* Verificação de tipos.
|
||||
* Validação de dados:
|
||||
* Erros automáticos e claros quando o dado é inválido.
|
||||
* Validação até para objetos JSON profundamente aninhados.
|
||||
* <abbr title="também conhecido como: serialization, parsing, marshalling">Conversão</abbr> de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler:
|
||||
* JSON.
|
||||
* Path parameters.
|
||||
* Query parameters.
|
||||
* Cookies.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Files.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
|
||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||
* `datetime` objects.
|
||||
* `UUID` objects.
|
||||
* Database models.
|
||||
* ...and many more.
|
||||
* Automatic interactive API documentation, including 2 alternative user interfaces:
|
||||
* Parâmetros de rota.
|
||||
* Parâmetros de _query_ .
|
||||
* _Cookies_.
|
||||
* Cabeçalhos.
|
||||
* Formulários.
|
||||
* Arquivos.
|
||||
* <abbr title="também conhecido como: serialization, parsing, marshalling">Conversão</abbr> de dados de saída de tipos e dados Python para dados de rede (como JSON):
|
||||
* Converte tipos Python (`str`, `int`, `float`, `bool`, `list` etc).
|
||||
* Objetos `datetime`.
|
||||
* Objetos `UUID`.
|
||||
* Modelos de Banco de Dados.
|
||||
* ...e muito mais.
|
||||
* Documentação interativa automática da API, incluindo 2 alternativas de interface de usuário:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Coming back to the previous code example, **FastAPI** will:
|
||||
Voltando ao código do exemplo anterior, **FastAPI** irá:
|
||||
|
||||
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
|
||||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
|
||||
* If it is not, the client will see a useful, clear error.
|
||||
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
|
||||
* As the `q` parameter is declared with `= None`, it is optional.
|
||||
* Without the `None` it would be required (as is the body in the case with `PUT`).
|
||||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
|
||||
* Check that it has a required attribute `name` that should be a `str`.
|
||||
* Check that it has a required attribute `price` that has to be a `float`.
|
||||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
|
||||
* All this would also work for deeply nested JSON objects.
|
||||
* Convert from and to JSON automatically.
|
||||
* Document everything with OpenAPI, that can be used by:
|
||||
* Interactive documentation systems.
|
||||
* Automatic client code generation systems, for many languages.
|
||||
* Provide 2 interactive documentation web interfaces directly.
|
||||
* Validar que existe um `item_id` na rota para requisições `GET` e `PUT`.
|
||||
* Validar que `item_id` é do tipo `int` para requisições `GET` e `PUT`.
|
||||
* Se não é validado, o cliente verá um útil, claro erro.
|
||||
* Verificar se existe um parâmetro de _query_ opcional nomeado como `q` (como em `http://127.0.0.1:8000/items/foo?q=somequery`) para requisições `GET`.
|
||||
* Como o parâmetro `q` é declarado com `= None`, ele é opcional.
|
||||
* Sem o `None` ele poderia ser obrigatório (como o corpo no caso de `PUT`).
|
||||
* Para requisições `PUT` para `/items/{item_id}`, lerá o corpo como JSON e:
|
||||
* Verifica que tem um atributo obrigatório `name` que deve ser `str`.
|
||||
* Verifica que tem um atributo obrigatório `price` que deve ser `float`.
|
||||
* Verifica que tem an atributo opcional `is_offer`, que deve ser `bool`, se presente.
|
||||
* Tudo isso também funciona para objetos JSON profundamente aninhados.
|
||||
* Converter de e para JSON automaticamente.
|
||||
* Documentar tudo com OpenAPI, que poderá ser usado por:
|
||||
* Sistemas de documentação interativos.
|
||||
* Sistemas de clientes de geração de código automáticos, para muitas linguagens.
|
||||
* Fornecer diretamente 2 interfaces _web_ de documentação interativa.
|
||||
|
||||
---
|
||||
|
||||
We just scratched the surface, but you already get the idea of how it all works.
|
||||
Nós arranhamos apenas a superfície, mas você já tem idéia de como tudo funciona.
|
||||
|
||||
Try changing the line with:
|
||||
Experimente mudar a seguinte linha:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...from:
|
||||
...de:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...to:
|
||||
...para:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...and see how your editor will auto-complete the attributes and know their types:
|
||||
...e veja como seu editor irá auto-completar os atributos e saberá os tipos:
|
||||
|
||||

|
||||
|
||||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
|
||||
Para um exemplo mais completo incluindo mais recursos, veja <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - Guia do Usuário</a>.
|
||||
|
||||
**Spoiler alert**: the tutorial - user guide includes:
|
||||
**Alerta de Spoiler**: o tutorial - guia do usuário inclui:
|
||||
|
||||
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
|
||||
* How to set **validation constraints** as `maximum_length` or `regex`.
|
||||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
|
||||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
|
||||
* Many extra features (thanks to Starlette) as:
|
||||
* Declaração de **parâmetetros** de diferentes lugares como: **cabeçalhos**, **cookies**, **campos de formulários** e **arquivos**.
|
||||
* Como configurar **Limitações de Validação** como `maximum_length` ou `regex`.
|
||||
* Um poderoso e fácil de usar sistema de **<abbr title="também conhecido como componentes, recursos, fornecedores, serviços, injetáveis">Injeção de Dependência</abbr>**.
|
||||
* Segurança e autenticação, incluindo suporte para **OAuth2** com autenticação **JWT tokens** e **HTTP Basic**.
|
||||
* Técnicas mais avançadas (mas igualmente fáceis) para declaração de **modelos JSON profundamente aninhados** (graças ao Pydantic).
|
||||
* Muitos recursos extras (graças ao Starlette) como:
|
||||
* **WebSockets**
|
||||
* **GraphQL**
|
||||
* extremely easy tests based on `requests` and `pytest`
|
||||
* testes extrememamente fáceis baseados em `requests` e `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
* ...e mais.
|
||||
|
||||
## Performance
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
Testes de performance da _Independent TechEmpower_ mostram aplicações **FastAPI** rodando sob Uvicorn como <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">um dos _frameworks_ Python mais rápidos disponíveis</a>, somente atrás de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*)
|
||||
|
||||
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
Para entender mais sobre performance, veja a seção <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## Optional Dependencies
|
||||
## Dependências opcionais
|
||||
|
||||
Used by Pydantic:
|
||||
Usados por Pydantic:
|
||||
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - para JSON mais rápido <abbr title="converte uma string que chega de uma requisição HTTP para dados Python">"parsing"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - para validação de email.
|
||||
|
||||
Used by Starlette:
|
||||
Usados por Starlette:
|
||||
|
||||
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
|
||||
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Required if you want to use `FileResponse` or `StaticFiles`.
|
||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
||||
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Necessário se você quiser utilizar o `TestClient`.
|
||||
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Necessário se você quiser utilizar o `FileResponse` ou `StaticFiles`.
|
||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Necessário se você quiser utilizar a configuração padrão de templates.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Necessário se você quiser suporte com <abbr title="converte uma string que chega de uma requisição HTTP para dados Python">"parsing"</abbr> de formulário, com `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Necessário para suporte a `SessionMiddleware`.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Necessário para suporte a `SchemaGenerator` da Starlette (você provavelmente não precisará disso com o FastAPI).
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Necessário para suporte a `GraphQLApp`.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Necessário se você quer utilizar `UJSONResponse`.
|
||||
|
||||
Used by FastAPI / Starlette:
|
||||
Usados por FastAPI / Starlette:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - para o servidor que carrega e serve sua aplicação.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Necessário se você quer utilizar `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install fastapi[all]`.
|
||||
Você pode instalar todas essas dependências com `pip install fastapi[all]`.
|
||||
|
||||
## License
|
||||
## Licença
|
||||
|
||||
This project is licensed under the terms of the MIT license.
|
||||
Esse projeto é licenciado sob os termos da licença MIT.
|
||||
|
||||
@@ -27,6 +27,7 @@ nav:
|
||||
- features.md
|
||||
- Tutorial - Guia de Usuário:
|
||||
- tutorial/index.md
|
||||
- alternatives.md
|
||||
- history-design-future.md
|
||||
- benchmarks.md
|
||||
markdown_extensions:
|
||||
|
||||
286
docs/zh/docs/python-types.md
Normal file
286
docs/zh/docs/python-types.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# Python 类型提示简介
|
||||
|
||||
**Python 3.6+ 版本**加入了对"类型提示"的支持。
|
||||
|
||||
这些**"类型提示"**是一种新的语法(在 Python 3.6 版本加入)用来声明一个变量的<abbr title="例如:str、int、float、bool">类型</abbr>。
|
||||
|
||||
通过声明变量的类型,编辑器和一些工具能给你提供更好的支持。
|
||||
|
||||
这只是一个关于 Python 类型提示的**快速入门 / 复习**。它仅涵盖与 **FastAPI** 一起使用所需的最少部分...实际上只有很少一点。
|
||||
|
||||
整个 **FastAPI** 都基于这些类型提示构建,它们带来了许多优点和好处。
|
||||
|
||||
但即使你不会用到 **FastAPI**,了解一下类型提示也会让你从中受益。
|
||||
|
||||
!!! note
|
||||
如果你已经精通 Python,并且了解关于类型提示的一切知识,直接跳到下一章节吧。
|
||||
|
||||
## 动机
|
||||
|
||||
让我们从一个简单的例子开始:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
运行这段程序将输出:
|
||||
|
||||
```
|
||||
John Doe
|
||||
```
|
||||
|
||||
这个函数做了下面这些事情:
|
||||
|
||||
* 接收 `first_name` 和 `last_name` 参数。
|
||||
* 通过 `title()` 将每个参数的第一个字母转换为大写形式。
|
||||
* 中间用一个空格来<abbr title="将它们按顺序放置组合成一个整体。">拼接</abbr>它们。
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
### 修改示例
|
||||
|
||||
这是一个非常简单的程序。
|
||||
|
||||
现在假设你将从头开始编写这段程序。
|
||||
|
||||
在某一时刻,你开始定义函数,并且准备好了参数...。
|
||||
|
||||
现在你需要调用一个"将第一个字母转换为大写形式的方法"。
|
||||
|
||||
等等,那个方法是什么来着?`upper`?还是 `uppercase`?`first_uppercase`?`capitalize`?
|
||||
|
||||
然后你尝试向程序员老手的朋友——编辑器自动补全寻求帮助。
|
||||
|
||||
输入函数的第一个参数 `first_name`,输入点号(`.`)然后敲下 `Ctrl+Space` 来触发代码补全。
|
||||
|
||||
但遗憾的是并没有起什么作用:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/python-types/image01.png">
|
||||
|
||||
### 添加类型
|
||||
|
||||
让我们来修改上面例子的一行代码。
|
||||
|
||||
我们将把下面这段代码中的函数参数从:
|
||||
|
||||
```Python
|
||||
first_name, last_name
|
||||
```
|
||||
|
||||
改成:
|
||||
|
||||
```Python
|
||||
first_name: str, last_name: str
|
||||
```
|
||||
|
||||
就是这样。
|
||||
|
||||
这些就是"类型提示":
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial002.py!}
|
||||
```
|
||||
|
||||
这和声明默认值是不同的,例如:
|
||||
|
||||
```Python
|
||||
first_name="john", last_name="doe"
|
||||
```
|
||||
|
||||
这两者不一样。
|
||||
|
||||
我们用的是冒号(`:`),不是等号(`=`)。
|
||||
|
||||
而且添加类型提示一般不会改变原来的运行结果。
|
||||
|
||||
现在假设我们又一次正在创建这个函数,这次添加了类型提示。
|
||||
|
||||
在同样的地方,通过 `Ctrl+Space` 触发自动补全,你会发现:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/python-types/image02.png">
|
||||
|
||||
这样,你可以滚动查看选项,直到你找到看起来眼熟的那个:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/python-types/image03.png">
|
||||
|
||||
## 更多动机
|
||||
|
||||
下面是一个已经有类型提示的函数:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial003.py!}
|
||||
```
|
||||
|
||||
因为编辑器已经知道了这些变量的类型,所以不仅能对代码进行补全,还能检查其中的错误:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/python-types/image04.png">
|
||||
|
||||
现在你知道了必须先修复这个问题,通过 `str(age)` 把 `age` 转换成字符串:
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/python_types/tutorial004.py!}
|
||||
```
|
||||
|
||||
## 声明类型
|
||||
|
||||
你刚刚看到的就是声明类型提示的主要场景。用于函数的参数。
|
||||
|
||||
这也是你将在 **FastAPI** 中使用它们的主要场景。
|
||||
|
||||
### 简单类型
|
||||
|
||||
不只是 `str`,你能够声明所有的标准 Python 类型。
|
||||
|
||||
比如以下类型:
|
||||
|
||||
* `int`
|
||||
* `float`
|
||||
* `bool`
|
||||
* `bytes`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial005.py!}
|
||||
```
|
||||
|
||||
### 嵌套类型
|
||||
|
||||
有些容器数据结构可以包含其他的值,比如 `dict`、`list`、`set` 和 `tuple`。它们内部的值也会拥有自己的类型。
|
||||
|
||||
你可以使用 Python 的 `typing` 标准库来声明这些类型以及子类型。
|
||||
|
||||
它专门用来支持这些类型提示。
|
||||
|
||||
#### 列表
|
||||
|
||||
例如,让我们来定义一个由 `str` 组成的 `list` 变量。
|
||||
|
||||
从 `typing` 模块导入 `List`(注意是大写的 `L`):
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
同样以冒号(`:`)来声明这个变量。
|
||||
|
||||
输入 `List` 作为类型。
|
||||
|
||||
由于列表是带有"子类型"的类型,所以我们把子类型放在方括号中:
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
这表示:"变量 `items` 是一个 `list`,并且这个列表里的每一个元素都是 `str`"。
|
||||
|
||||
这样,即使在处理列表中的元素时,你的编辑器也可以提供支持。
|
||||
|
||||
没有类型,几乎是不可能实现下面这样:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/python-types/image05.png">
|
||||
|
||||
注意,变量 `item` 是列表 `items` 中的元素之一。
|
||||
|
||||
而且,编辑器仍然知道它是一个 `str`,并为此提供了支持。
|
||||
|
||||
#### 元组和集合
|
||||
|
||||
声明 `tuple` 和 `set` 的方法也是一样的:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
|
||||
这表示:
|
||||
|
||||
* 变量 `items_t` 是一个 `tuple`,其中的每个元素都是 `int` 类型。
|
||||
* 变量 `items_s` 是一个 `set`,其中的每个元素都是 `bytes` 类型。
|
||||
|
||||
#### 字典
|
||||
|
||||
定义 `dict` 时,需要传入两个子类型,用逗号进行分隔。
|
||||
|
||||
第一个子类型声明 `dict` 的所有键。
|
||||
|
||||
第二个子类型声明 `dict` 的所有值:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
|
||||
这表示:
|
||||
|
||||
* 变量 `prices` 是一个 `dict`:
|
||||
* 这个 `dict` 的所有键为 `str` 类型(可以看作是字典内每个元素的名称)。
|
||||
* 这个 `dict` 的所有值为 `float` 类型(可以看作是字典内每个元素的价格)。
|
||||
|
||||
### 类作为类型
|
||||
|
||||
你也可以将类声明为变量的类型。
|
||||
|
||||
假设你有一个名为 `Person` 的类,拥有 name 属性:
|
||||
|
||||
```Python hl_lines="1 2 3"
|
||||
{!../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
接下来,你可以将一个变量声明为 `Person` 类型:
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
然后,你将再次获得所有的编辑器支持:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/python-types/image06.png">
|
||||
|
||||
## Pydantic 模型
|
||||
|
||||
<a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> 是一个用来用来执行数据校验的 Python 库。
|
||||
|
||||
你可以将数据的"结构"声明为具有属性的类。
|
||||
|
||||
每个属性都拥有类型。
|
||||
|
||||
接着你用一些值来创建这个类的实例,这些值会被校验,并被转换为适当的类型(在需要的情况下),返回一个包含所有数据的对象。
|
||||
|
||||
然后,你将获得这个对象的所有编辑器支持。
|
||||
|
||||
下面的例子来自 Pydantic 官方文档:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
想进一步了解 <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic,请阅读其文档</a>.
|
||||
|
||||
整个 **FastAPI** 建立在 Pydantic 的基础之上。
|
||||
|
||||
实际上你将在 [教程 - 用户指南](tutorial/index.md){.internal-link target=_blank} 看到很多这种情况。
|
||||
|
||||
## **FastAPI** 中的类型提示
|
||||
|
||||
**FastAPI** 利用这些类型提示来做下面几件事。
|
||||
|
||||
使用 **FastAPI** 时用类型提示声明参数可以获得:
|
||||
|
||||
* **编辑器支持**。
|
||||
* **类型检查**。
|
||||
|
||||
...并且 **FastAPI** 还会用这些类型声明来:
|
||||
|
||||
* **定义参数要求**:声明对请求路径参数、查询参数、请求头、请求体、依赖等的要求。
|
||||
* **转换数据**:将来自请求的数据转换为需要的类型。
|
||||
* **校验数据**: 对于每一个请求:
|
||||
* 当数据校验失败时自动生成**错误信息**返回给客户端。
|
||||
* 使用 OpenAPI **记录** API:
|
||||
* 然后用于自动生成交互式文档的用户界面。
|
||||
|
||||
听上去有点抽象。不过不用担心。你将在 [教程 - 用户指南](tutorial/index.md){.internal-link target=_blank} 中看到所有的实战。
|
||||
|
||||
最重要的是,通过使用标准的 Python 类型,只需要在一个地方声明(而不是添加更多的类、装饰器等),**FastAPI** 会为你完成很多的工作。
|
||||
|
||||
!!! info
|
||||
如果你已经阅读了所有教程,回过头来想了解有关类型的更多信息,<a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">来自 `mypy` 的"速查表"</a>是不错的资源。
|
||||
@@ -25,6 +25,7 @@ nav:
|
||||
- pt: /pt/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- python-types.md
|
||||
- 教程 - 用户指南:
|
||||
- tutorial/index.md
|
||||
- deployment.md
|
||||
|
||||
8
docs_src/behind_a_proxy/tutorial001.py
Normal file
8
docs_src/behind_a_proxy/tutorial001.py
Normal file
@@ -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")}
|
||||
8
docs_src/behind_a_proxy/tutorial002.py
Normal file
8
docs_src/behind_a_proxy/tutorial002.py
Normal file
@@ -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")}
|
||||
@@ -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"
|
||||
|
||||
@@ -13,8 +13,8 @@ app = FastAPI()
|
||||
|
||||
# Dependency
|
||||
def get_db():
|
||||
db = SessionLocal()
|
||||
try:
|
||||
db = SessionLocal()
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
@@ -8,7 +8,7 @@ def read_main():
|
||||
return {"message": "Hello World from main app"}
|
||||
|
||||
|
||||
subapi = FastAPI(openapi_prefix="/subapi")
|
||||
subapi = FastAPI()
|
||||
|
||||
|
||||
@subapi.get("/sub")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.54.2"
|
||||
__version__ = "0.56.0"
|
||||
|
||||
from starlette import status
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from fastapi.exception_handlers import (
|
||||
request_validation_exception_handler,
|
||||
)
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.logger import logger
|
||||
from fastapi.openapi.docs import (
|
||||
get_redoc_html,
|
||||
get_swagger_ui_html,
|
||||
@@ -36,7 +37,6 @@ class FastAPI(Starlette):
|
||||
description: str = "",
|
||||
version: str = "0.1.0",
|
||||
openapi_url: Optional[str] = "/openapi.json",
|
||||
openapi_prefix: str = "",
|
||||
default_response_class: Type[Response] = JSONResponse,
|
||||
docs_url: Optional[str] = "/docs",
|
||||
redoc_url: Optional[str] = "/redoc",
|
||||
@@ -46,6 +46,8 @@ class FastAPI(Starlette):
|
||||
exception_handlers: Dict[Union[int, Type[Exception]], Callable] = None,
|
||||
on_startup: Sequence[Callable] = None,
|
||||
on_shutdown: Sequence[Callable] = None,
|
||||
openapi_prefix: str = "",
|
||||
root_path: str = "",
|
||||
**extra: Dict[str, Any],
|
||||
) -> None:
|
||||
self.default_response_class = default_response_class
|
||||
@@ -68,7 +70,15 @@ class FastAPI(Starlette):
|
||||
self.description = description
|
||||
self.version = version
|
||||
self.openapi_url = openapi_url
|
||||
self.openapi_prefix = openapi_prefix.rstrip("/")
|
||||
# TODO: remove when discarding the openapi_prefix parameter
|
||||
if openapi_prefix:
|
||||
logger.warning(
|
||||
'"openapi_prefix" has been deprecated in favor of "root_path", which '
|
||||
"follows more closely the ASGI standard, is simpler, and more "
|
||||
"automatic. Check the docs at "
|
||||
"https://fastapi.tiangolo.com/advanced/sub-applications-proxy/"
|
||||
)
|
||||
self.root_path = root_path or openapi_prefix
|
||||
self.docs_url = docs_url
|
||||
self.redoc_url = redoc_url
|
||||
self.swagger_ui_oauth2_redirect_url = swagger_ui_oauth2_redirect_url
|
||||
@@ -84,7 +94,7 @@ class FastAPI(Starlette):
|
||||
self.openapi_schema: Optional[Dict[str, Any]] = None
|
||||
self.setup()
|
||||
|
||||
def openapi(self) -> Dict:
|
||||
def openapi(self, openapi_prefix: str = "") -> Dict:
|
||||
if not self.openapi_schema:
|
||||
self.openapi_schema = get_openapi(
|
||||
title=self.title,
|
||||
@@ -92,7 +102,7 @@ class FastAPI(Starlette):
|
||||
openapi_version=self.openapi_version,
|
||||
description=self.description,
|
||||
routes=self.routes,
|
||||
openapi_prefix=self.openapi_prefix,
|
||||
openapi_prefix=openapi_prefix,
|
||||
)
|
||||
return self.openapi_schema
|
||||
|
||||
@@ -100,17 +110,22 @@ class FastAPI(Starlette):
|
||||
if self.openapi_url:
|
||||
|
||||
async def openapi(req: Request) -> JSONResponse:
|
||||
return JSONResponse(self.openapi())
|
||||
root_path = req.scope.get("root_path", "").rstrip("/")
|
||||
return JSONResponse(self.openapi(root_path))
|
||||
|
||||
self.add_route(self.openapi_url, openapi, include_in_schema=False)
|
||||
openapi_url = self.openapi_prefix + self.openapi_url
|
||||
if self.openapi_url and self.docs_url:
|
||||
|
||||
async def swagger_ui_html(req: Request) -> HTMLResponse:
|
||||
root_path = req.scope.get("root_path", "").rstrip("/")
|
||||
openapi_url = root_path + self.openapi_url
|
||||
oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url
|
||||
if oauth2_redirect_url:
|
||||
oauth2_redirect_url = root_path + oauth2_redirect_url
|
||||
return get_swagger_ui_html(
|
||||
openapi_url=openapi_url,
|
||||
title=self.title + " - Swagger UI",
|
||||
oauth2_redirect_url=self.swagger_ui_oauth2_redirect_url,
|
||||
oauth2_redirect_url=oauth2_redirect_url,
|
||||
init_oauth=self.swagger_ui_init_oauth,
|
||||
)
|
||||
|
||||
@@ -129,6 +144,8 @@ class FastAPI(Starlette):
|
||||
if self.openapi_url and self.redoc_url:
|
||||
|
||||
async def redoc_html(req: Request) -> HTMLResponse:
|
||||
root_path = req.scope.get("root_path", "").rstrip("/")
|
||||
openapi_url = root_path + self.openapi_url
|
||||
return get_redoc_html(
|
||||
openapi_url=openapi_url, title=self.title + " - ReDoc"
|
||||
)
|
||||
@@ -140,6 +157,8 @@ class FastAPI(Starlette):
|
||||
)
|
||||
|
||||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
||||
if self.root_path:
|
||||
scope["root_path"] = self.root_path
|
||||
if AsyncExitStack:
|
||||
async with AsyncExitStack() as stack:
|
||||
scope["fastapi_astack"] = stack
|
||||
|
||||
@@ -188,6 +188,16 @@ def get_flat_dependant(
|
||||
return flat_dependant
|
||||
|
||||
|
||||
def get_flat_params(dependant: Dependant) -> List[ModelField]:
|
||||
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
|
||||
return (
|
||||
flat_dependant.path_params
|
||||
+ flat_dependant.query_params
|
||||
+ flat_dependant.header_params
|
||||
+ flat_dependant.cookie_params
|
||||
)
|
||||
|
||||
|
||||
def is_scalar_field(field: ModelField) -> bool:
|
||||
field_info = get_field_info(field)
|
||||
if not (
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import http.client
|
||||
from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, cast
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
|
||||
|
||||
from fastapi import routing
|
||||
from fastapi.dependencies.models import Dependant
|
||||
from fastapi.dependencies.utils import get_flat_dependant
|
||||
from fastapi.dependencies.utils import get_flat_dependant, get_flat_params
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.openapi.constants import (
|
||||
METHODS_WITH_BODY,
|
||||
@@ -15,11 +16,14 @@ from fastapi.params import Body, Param
|
||||
from fastapi.utils import (
|
||||
generate_operation_id_for_path,
|
||||
get_field_info,
|
||||
get_flat_models_from_routes,
|
||||
get_model_definitions,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
from pydantic.schema import field_schema, get_model_name_map
|
||||
from pydantic.schema import (
|
||||
field_schema,
|
||||
get_flat_models_from_fields,
|
||||
get_model_name_map,
|
||||
)
|
||||
from pydantic.utils import lenient_issubclass
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.routing import BaseRoute
|
||||
@@ -64,16 +68,6 @@ status_code_ranges: Dict[str, str] = {
|
||||
}
|
||||
|
||||
|
||||
def get_openapi_params(dependant: Dependant) -> List[ModelField]:
|
||||
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
|
||||
return (
|
||||
flat_dependant.path_params
|
||||
+ flat_dependant.query_params
|
||||
+ flat_dependant.header_params
|
||||
+ flat_dependant.cookie_params
|
||||
)
|
||||
|
||||
|
||||
def get_openapi_security_definitions(flat_dependant: Dependant) -> Tuple[Dict, List]:
|
||||
security_definitions = {}
|
||||
operation_security = []
|
||||
@@ -90,17 +84,22 @@ def get_openapi_security_definitions(flat_dependant: Dependant) -> Tuple[Dict, L
|
||||
|
||||
|
||||
def get_openapi_operation_parameters(
|
||||
*,
|
||||
all_route_params: Sequence[ModelField],
|
||||
model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str]
|
||||
) -> List[Dict[str, Any]]:
|
||||
parameters = []
|
||||
for param in all_route_params:
|
||||
field_info = get_field_info(param)
|
||||
field_info = cast(Param, field_info)
|
||||
# ignore mypy error until enum schemas are released
|
||||
parameter = {
|
||||
"name": param.alias,
|
||||
"in": field_info.in_.value,
|
||||
"required": param.required,
|
||||
"schema": field_schema(param, model_name_map={})[0],
|
||||
"schema": field_schema(
|
||||
param, model_name_map=model_name_map, ref_prefix=REF_PREFIX # type: ignore
|
||||
)[0],
|
||||
}
|
||||
if field_info.description:
|
||||
parameter["description"] = field_info.description
|
||||
@@ -111,13 +110,16 @@ def get_openapi_operation_parameters(
|
||||
|
||||
|
||||
def get_openapi_operation_request_body(
|
||||
*, body_field: Optional[ModelField], model_name_map: Dict[Type[BaseModel], str]
|
||||
*,
|
||||
body_field: Optional[ModelField],
|
||||
model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str]
|
||||
) -> Optional[Dict]:
|
||||
if not body_field:
|
||||
return None
|
||||
assert isinstance(body_field, ModelField)
|
||||
# ignore mypy error until enum schemas are released
|
||||
body_schema, _, _ = field_schema(
|
||||
body_field, model_name_map=model_name_map, ref_prefix=REF_PREFIX
|
||||
body_field, model_name_map=model_name_map, ref_prefix=REF_PREFIX # type: ignore
|
||||
)
|
||||
field_info = cast(Body, get_field_info(body_field))
|
||||
request_media_type = field_info.media_type
|
||||
@@ -176,8 +178,10 @@ def get_openapi_path(
|
||||
operation.setdefault("security", []).extend(operation_security)
|
||||
if security_definitions:
|
||||
security_schemes.update(security_definitions)
|
||||
all_route_params = get_openapi_params(route.dependant)
|
||||
operation_parameters = get_openapi_operation_parameters(all_route_params)
|
||||
all_route_params = get_flat_params(route.dependant)
|
||||
operation_parameters = get_openapi_operation_parameters(
|
||||
all_route_params=all_route_params, model_name_map=model_name_map
|
||||
)
|
||||
parameters.extend(operation_parameters)
|
||||
if parameters:
|
||||
operation["parameters"] = list(
|
||||
@@ -270,6 +274,38 @@ def get_openapi_path(
|
||||
return path, security_schemes, definitions
|
||||
|
||||
|
||||
def get_flat_models_from_routes(
|
||||
routes: Sequence[BaseRoute],
|
||||
) -> Set[Union[Type[BaseModel], Type[Enum]]]:
|
||||
body_fields_from_routes: List[ModelField] = []
|
||||
responses_from_routes: List[ModelField] = []
|
||||
request_fields_from_routes: List[ModelField] = []
|
||||
callback_flat_models: Set[Union[Type[BaseModel], Type[Enum]]] = set()
|
||||
for route in routes:
|
||||
if getattr(route, "include_in_schema", None) and isinstance(
|
||||
route, routing.APIRoute
|
||||
):
|
||||
if route.body_field:
|
||||
assert isinstance(
|
||||
route.body_field, ModelField
|
||||
), "A request body must be a Pydantic Field"
|
||||
body_fields_from_routes.append(route.body_field)
|
||||
if route.response_field:
|
||||
responses_from_routes.append(route.response_field)
|
||||
if route.response_fields:
|
||||
responses_from_routes.extend(route.response_fields.values())
|
||||
if route.callbacks:
|
||||
callback_flat_models |= get_flat_models_from_routes(route.callbacks)
|
||||
params = get_flat_params(route.dependant)
|
||||
request_fields_from_routes.extend(params)
|
||||
|
||||
flat_models = callback_flat_models | get_flat_models_from_fields(
|
||||
body_fields_from_routes + responses_from_routes + request_fields_from_routes,
|
||||
known_models=set(),
|
||||
)
|
||||
return flat_models
|
||||
|
||||
|
||||
def get_openapi(
|
||||
*,
|
||||
title: str,
|
||||
@@ -286,9 +322,11 @@ def get_openapi(
|
||||
components: Dict[str, Dict] = {}
|
||||
paths: Dict[str, Dict] = {}
|
||||
flat_models = get_flat_models_from_routes(routes)
|
||||
model_name_map = get_model_name_map(flat_models)
|
||||
# ignore mypy error until enum schemas are released
|
||||
model_name_map = get_model_name_map(flat_models) # type: ignore
|
||||
# ignore mypy error until enum schemas are released
|
||||
definitions = get_model_definitions(
|
||||
flat_models=flat_models, model_name_map=model_name_map
|
||||
flat_models=flat_models, model_name_map=model_name_map # type: ignore
|
||||
)
|
||||
for route in routes:
|
||||
if isinstance(route, routing.APIRoute):
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import functools
|
||||
import re
|
||||
from dataclasses import is_dataclass
|
||||
from typing import Any, Dict, List, Optional, Sequence, Set, Type, Union, cast
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, Optional, Set, Type, Union, cast
|
||||
|
||||
import fastapi
|
||||
from fastapi import routing
|
||||
from fastapi.logger import logger
|
||||
from fastapi.openapi.constants import REF_PREFIX
|
||||
from pydantic import BaseConfig, BaseModel, create_model
|
||||
from pydantic.class_validators import Validator
|
||||
from pydantic.schema import get_flat_models_from_fields, model_process_schema
|
||||
from pydantic.schema import model_process_schema
|
||||
from pydantic.utils import lenient_issubclass
|
||||
from starlette.routing import BaseRoute
|
||||
|
||||
try:
|
||||
from pydantic.fields import FieldInfo, ModelField, UndefinedType
|
||||
@@ -50,38 +49,16 @@ def warning_response_model_skip_defaults_deprecated() -> None:
|
||||
)
|
||||
|
||||
|
||||
def get_flat_models_from_routes(routes: Sequence[BaseRoute]) -> Set[Type[BaseModel]]:
|
||||
body_fields_from_routes: List[ModelField] = []
|
||||
responses_from_routes: List[ModelField] = []
|
||||
callback_flat_models: Set[Type[BaseModel]] = set()
|
||||
for route in routes:
|
||||
if getattr(route, "include_in_schema", None) and isinstance(
|
||||
route, routing.APIRoute
|
||||
):
|
||||
if route.body_field:
|
||||
assert isinstance(
|
||||
route.body_field, ModelField
|
||||
), "A request body must be a Pydantic Field"
|
||||
body_fields_from_routes.append(route.body_field)
|
||||
if route.response_field:
|
||||
responses_from_routes.append(route.response_field)
|
||||
if route.response_fields:
|
||||
responses_from_routes.extend(route.response_fields.values())
|
||||
if route.callbacks:
|
||||
callback_flat_models |= get_flat_models_from_routes(route.callbacks)
|
||||
flat_models = callback_flat_models | get_flat_models_from_fields(
|
||||
body_fields_from_routes + responses_from_routes, known_models=set()
|
||||
)
|
||||
return flat_models
|
||||
|
||||
|
||||
def get_model_definitions(
|
||||
*, flat_models: Set[Type[BaseModel]], model_name_map: Dict[Type[BaseModel], str]
|
||||
*,
|
||||
flat_models: Set[Union[Type[BaseModel], Type[Enum]]],
|
||||
model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str],
|
||||
) -> Dict[str, Any]:
|
||||
definitions: Dict[str, Dict] = {}
|
||||
for model in flat_models:
|
||||
# ignore mypy error until enum schemas are released
|
||||
m_schema, m_definitions, m_nested_models = model_process_schema(
|
||||
model, model_name_map=model_name_map, ref_prefix=REF_PREFIX
|
||||
model, model_name_map=model_name_map, ref_prefix=REF_PREFIX # type: ignore
|
||||
)
|
||||
definitions.update(m_definitions)
|
||||
model_name = model_name_map[model]
|
||||
|
||||
@@ -3,4 +3,4 @@ set -x
|
||||
|
||||
autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place docs_src fastapi tests scripts --exclude=__init__.py
|
||||
black fastapi tests docs_src scripts
|
||||
isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --thirdparty fastapi --apply fastapi tests docs_src scripts
|
||||
isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --thirdparty fastapi --thirdparty pydantic --thirdparty starlette --apply fastapi tests docs_src scripts
|
||||
|
||||
@@ -5,4 +5,4 @@ set -x
|
||||
|
||||
mypy fastapi
|
||||
black fastapi tests --check
|
||||
isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --check-only --thirdparty fastapi fastapi tests
|
||||
isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --check-only --thirdparty fastapi --thirdparty fastapi --thirdparty pydantic --thirdparty starlette fastapi tests
|
||||
|
||||
43
tests/test_deprecated_openapi_prefix.py
Normal file
43
tests/test_deprecated_openapi_prefix.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
app = FastAPI(openapi_prefix="/api/v1")
|
||||
|
||||
|
||||
@app.get("/app")
|
||||
def read_main(request: Request):
|
||||
return {"message": "Hello World", "root_path": request.scope.get("root_path")}
|
||||
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/api/v1/app": {
|
||||
"get": {
|
||||
"summary": "Read Main",
|
||||
"operationId": "read_main_app_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_main():
|
||||
response = client.get("/app")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"message": "Hello World", "root_path": "/api/v1"}
|
||||
0
tests/test_tutorial/test_behind_a_proxy/__init__.py
Normal file
0
tests/test_tutorial/test_behind_a_proxy/__init__.py
Normal file
36
tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py
Normal file
36
tests/test_tutorial/test_behind_a_proxy/test_tutorial001.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from behind_a_proxy.tutorial001 import app
|
||||
|
||||
client = TestClient(app, root_path="/api/v1")
|
||||
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/api/v1/app": {
|
||||
"get": {
|
||||
"summary": "Read Main",
|
||||
"operationId": "read_main_app_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_main():
|
||||
response = client.get("/app")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"message": "Hello World", "root_path": "/api/v1"}
|
||||
36
tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py
Normal file
36
tests/test_tutorial/test_behind_a_proxy/test_tutorial002.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from behind_a_proxy.tutorial002 import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
openapi_schema = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/api/v1/app": {
|
||||
"get": {
|
||||
"summary": "Read Main",
|
||||
"operationId": "read_main_app_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == openapi_schema
|
||||
|
||||
|
||||
def test_main():
|
||||
response = client.get("/app")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"message": "Hello World", "root_path": "/api/v1"}
|
||||
@@ -76,10 +76,84 @@ openapi_schema = {
|
||||
}
|
||||
|
||||
|
||||
openapi_schema2 = {
|
||||
"openapi": "3.0.2",
|
||||
"info": {"title": "FastAPI", "version": "0.1.0"},
|
||||
"paths": {
|
||||
"/model/{model_name}": {
|
||||
"get": {
|
||||
"summary": "Get Model",
|
||||
"operationId": "get_model_model__model_name__get",
|
||||
"parameters": [
|
||||
{
|
||||
"required": True,
|
||||
"schema": {"$ref": "#/components/schemas/ModelName"},
|
||||
"name": "model_name",
|
||||
"in": "path",
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {"application/json": {"schema": {}}},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/ValidationError"},
|
||||
}
|
||||
},
|
||||
},
|
||||
"ModelName": {
|
||||
"title": "ModelName",
|
||||
"enum": ["alexnet", "resnet", "lenet"],
|
||||
"type": "string",
|
||||
"description": "An enumeration.",
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": ["loc", "msg", "type"],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
},
|
||||
"msg": {"title": "Message", "type": "string"},
|
||||
"type": {"title": "Error Type", "type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_openapi():
|
||||
response = client.get("/openapi.json")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == openapi_schema
|
||||
data = response.json()
|
||||
assert data == openapi_schema or data == openapi_schema2
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
Reference in New Issue
Block a user