Compare commits

...

30 Commits

Author SHA1 Message Date
Sebastián Ramírez
0a38c51b9e 🔖 Release 0.66.1 2021-07-19 21:26:52 +02:00
Sebastián Ramírez
db5b2bdf56 📝 Update release notes 2021-07-19 21:21:40 +02:00
github-actions
5ac84120b3 📝 Update release notes 2021-07-19 19:15:35 +00:00
Thomas Grainger
2d296c5d07 🔧 Configure strict pytest options and update/refactor tests (#2790)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-19 21:14:58 +02:00
github-actions
71c96d9eb9 📝 Update release notes 2021-07-19 12:49:41 +00:00
Mark H
5342a0a00f 🌐 Add basic setup for German translations (#3522) 2021-07-19 14:49:09 +02:00
github-actions
163b086f21 📝 Update release notes 2021-07-19 12:47:20 +00:00
oandersonmagalhaes
0876d3df1d 🌐 Add Portuguese translation for docs/tutorial/security/index.md (#3507)
Co-authored-by: Izabela Guerreiro <izaguerreiro@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-19 14:46:39 +02:00
github-actions
50baf5e804 📝 Update release notes 2021-07-19 12:33:34 +00:00
Lucas
3d6da2c32d 🌐 Add Portuguese translation for docs/deployment/index.md (#3337) 2021-07-19 14:32:54 +02:00
github-actions
e721d04350 📝 Update release notes 2021-07-05 11:45:43 +00:00
Sebastián Ramírez
8cc6f9baac ⬆️ Upgrade python-jose dependency for tests (#3468) 2021-07-05 13:45:03 +02:00
Sebastián Ramírez
dfd453e001 📝 Update release notes 2021-07-04 21:18:45 +02:00
Sebastián Ramírez
7e9d5aacf8 🔖 Release version 0.66.0 2021-07-04 20:59:46 +02:00
Sebastián Ramírez
d27a218bc3 📝 Update release notes 2021-07-04 20:58:49 +02:00
github-actions
0c4ded88fe 📝 Update release notes 2021-07-04 18:54:19 +00:00
Rubikoid
0e0931d308 🐛 Fix include/exclude for dicts in jsonable_encoder (#2016)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-04 20:53:40 +02:00
github-actions
dcfa9eb8fe 📝 Update release notes 2021-07-04 17:35:19 +00:00
Camila Gutierrez
6ebf60b175 🌐 Add Spanish translation for tutorial/query-params.md (#2243)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-04 19:34:46 +02:00
github-actions
a4d0724a97 📝 Update release notes 2021-07-04 17:06:51 +00:00
Juan Funez
c235e9b78c 🌐 Add Spanish translation for advanced/response-directly.md (#1253)
Co-authored-by: Camila Gutierrez <mariacamilagl30@gmail.com>
2021-07-04 19:06:18 +02:00
github-actions
5fa3e239db 📝 Update release notes 2021-07-04 14:15:04 +00:00
Juan Funez
3d1b107d70 🌐 Add Spanish translation for advanced/additional-status-codes.md (#1252)
Co-authored-by: Camila Gutierrez <mariacamilagl30@gmail.com>
2021-07-04 16:14:29 +02:00
github-actions
18e0828daf 📝 Update release notes 2021-07-04 12:50:02 +00:00
Juan Funez
f16c7729bd 🌐 Add Spanish translation for advanced/path-operation-advanced-configuration.md (#1251)
Co-authored-by: Camila Gutierrez <mariacamilagl@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: Camila Gutierrez <mariacamilagl30@gmail.com>
2021-07-04 14:49:31 +02:00
Sebastián Ramírez
9f3c8cd139 📝 Update release notes, add links to docs 2021-07-03 21:59:39 +02:00
github-actions
a7a35aee61 📝 Update release notes 2021-07-03 19:52:03 +00:00
Sebastián Ramírez
dc5a966548 Allow setting the response_class to RedirectResponse and returning the URL from the function (#3457) 2021-07-03 21:51:28 +02:00
github-actions
ea8d7f689e 📝 Update release notes 2021-07-03 17:16:33 +00:00
Jacob Magnusson
0ed6c92341 🐛 Support custom OpenAPI / JSON Schema fields in the generated output OpenAPI (#1429)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-07-03 19:15:59 +02:00
49 changed files with 1682 additions and 107 deletions

467
docs/de/docs/index.md Normal file
View File

@@ -0,0 +1,467 @@
{!../../../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>
</p>
<p align="center">
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
</a>
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
</p>
---
**Documentation**: <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>
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
The key features are:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
* **Intuitive**: Great editor support. <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="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* estimation based on tests on an internal development team, building production applications.</small>
## Sponsors
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
## 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._"
<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>
---
"_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>
---
"_Im over the moon excited about **FastAPI**. Its 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._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://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 [...]_"
"_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>
---
## **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>
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>.
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
## Requirements
Python 3.6+
FastAPI stands on the shoulders of giants:
* <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.
## Installation
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
You will also need an ASGI server, for production such as <a href="https://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>.
<div class="termy">
```console
$ pip install uvicorn[standard]
---> 100%
```
</div>
## Example
### Create it
* Create a file `main.py` with:
```Python
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
<details markdown="1">
<summary>Or use <code>async def</code>...</summary>
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
**Note**:
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
</details>
### Run it
Run the server with:
<div class="termy">
```console
$ uvicorn main:app --reload
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>
The command `uvicorn main:app` refers to:
* `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.
</details>
### Check it
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>.
You will see the JSON response as:
```JSON
{"item_id": 5, "q": "somequery"}
```
You already created an API that:
* 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`.
### Interactive API docs
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>.
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>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternative API docs
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>.
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Example upgrade
Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
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).
### Interactive API docs upgrade
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>.
* The interactive API documentation will be automatically updated, including the new body:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* 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:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternative API docs upgrade
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>.
* The alternative documentation will also reflect the new query parameter and body:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard **Python 3.6+**.
For example, for an `int`:
```Python
item_id: int
```
or for a more complex `Item` model:
```Python
item: Item
```
...and with that single declaration you get:
* 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:
* 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:
* Swagger UI.
* ReDoc.
---
Coming back to the previous code example, **FastAPI** will:
* 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.
---
We just scratched the surface, but you already get the idea of how it all works.
Try changing the line with:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...from:
```Python
... "item_name": item.name ...
```
...to:
```Python
... "item_price": item.price ...
```
...and see how your editor will auto-complete the attributes and know their types:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Spoiler alert**: the tutorial - user guide includes:
* 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:
* **WebSockets**
* **GraphQL**
* extremely easy tests based on `requests` and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
## 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). (*)
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Optional Dependencies
Used by 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.
Used by Starlette:
* <a href="https://requests.readthedocs.io" 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="https://jinja.palletsprojects.com" 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`.
Used by FastAPI / Starlette:
* <a href="https://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`.
You can install all of these with `pip install fastapi[all]`.
## License
This project is licensed under the terms of the MIT license.

125
docs/de/mkdocs.yml Normal file
View File

@@ -0,0 +1,125 @@
site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/de/
theme:
name: material
custom_dir: overrides
palette:
- scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to dark mode
features:
- search.suggest
- search.highlight
icon:
repo: fontawesome/brands/github-alt
logo: https://fastapi.tiangolo.com/img/icon-white.svg
favicon: https://fastapi.tiangolo.com/img/favicon.png
language: de
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
data: data
nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
- tr: /tr/
- uk: /uk/
- zh: /zh/
markdown_extensions:
- toc:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
- markdown_include.include:
base_path: docs
- admonition
- codehilite
- extra
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_div_format ''
- pymdownx.tabbed
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
link: https://www.linkedin.com/in/tiangolo
- icon: fontawesome/brands/dev
link: https://dev.to/tiangolo
- icon: fontawesome/brands/medium
link: https://medium.com/@tiangolo
- icon: fontawesome/solid/globe
link: https://tiangolo.com
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/
name: ru - русский язык
- link: /sq/
name: sq - shqip
- link: /tr/
name: tr - Türkçe
- link: /uk/
name: uk - українська мова
- link: /zh/
name: zh - 汉语
extra_css:
- https://fastapi.tiangolo.com/css/termynal.css
- https://fastapi.tiangolo.com/css/custom.css
extra_javascript:
- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
- https://fastapi.tiangolo.com/js/termynal.js
- https://fastapi.tiangolo.com/js/custom.js

0
docs/de/overrides/.gitignore vendored Normal file
View File

View File

@@ -161,10 +161,33 @@ An alternative JSON response using <a href="https://github.com/ultrajson/ultrajs
Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default.
You can return a `RedirectResponse` directly:
```Python hl_lines="2 9"
{!../../../docs_src/custom_response/tutorial006.py!}
```
---
Or you can use it in the `response_class` parameter:
```Python hl_lines="2 7 9"
{!../../../docs_src/custom_response/tutorial006b.py!}
```
If you do that, then you can return the URL directly from your *path operation* function.
In this case, the `status_code` used will be the default one for the `RedirectResponse`, which is `307`.
---
You can also use the `status_code` parameter combined with the `response_class` parameter:
```Python hl_lines="2 7 9"
{!../../../docs_src/custom_response/tutorial006c.py!}
```
### `StreamingResponse`
Takes an async generator or a normal generator/iterator and streams the response body.
@@ -175,14 +198,24 @@ Takes an async generator or a normal generator/iterator and streams the response
#### Using `StreamingResponse` with file-like objects
If you have a file-like object (e.g. the object returned by `open()`), you can return it in a `StreamingResponse`.
If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object.
That way, you don't have to read it all first in memory, and you can pass that generator function to the `StreamingResponse`, and return it.
This includes many libraries to interact with cloud storage, video processing, and others.
```Python hl_lines="2 10-11"
```{ .python .annotate hl_lines="2 10-12 14" }
{!../../../docs_src/custom_response/tutorial008.py!}
```
1. This is the generator function. It's a "generator function" because it contains `yield` statements inside.
2. By using a `with` block, we make sure that the file-like object is closed after the generator function is done. So, after it finishes sending the response.
3. This `yield from` tells the function to iterate over that thing named `file_like`. And then, for each part iterated, yield that part as coming from this generator function.
So, it is a generator function that transfers the "generating" work to something else internally.
By doing it this way, we can put it in a `with` block, and that way, ensure that it is closed after finishing.
!!! tip
Notice that here as we are using standard `open()` that doesn't support `async` and `await`, we declare the path operation with normal `def`.
@@ -203,6 +236,14 @@ File responses will include appropriate `Content-Length`, `Last-Modified` and `E
{!../../../docs_src/custom_response/tutorial009.py!}
```
You can also use the `response_class` parameter:
```Python hl_lines="2 8 10"
{!../../../docs_src/custom_response/tutorial009b.py!}
```
In this case, you can return the file path directly from your *path operation* function.
## Default response class
When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.

View File

@@ -2,6 +2,36 @@
## Latest Changes
## 0.66.1
### Translations
* 🌐 Add basic setup for German translations. PR [#3522](https://github.com/tiangolo/fastapi/pull/3522) by [@0x4Dark](https://github.com/0x4Dark).
* 🌐 Add Portuguese translation for `docs/tutorial/security/index.md`. PR [#3507](https://github.com/tiangolo/fastapi/pull/3507) by [@oandersonmagalhaes](https://github.com/oandersonmagalhaes).
* 🌐 Add Portuguese translation for `docs/deployment/index.md`. PR [#3337](https://github.com/tiangolo/fastapi/pull/3337) by [@lsglucas](https://github.com/lsglucas).
### Internal
* 🔧 Configure strict pytest options and update/refactor tests. Upgrade pytest to `>=6.2.4,<7.0.0` and pytest-cov to `>=2.12.0,<3.0.0`. Initial PR [#2790](https://github.com/tiangolo/fastapi/pull/2790) by [@graingert](https://github.com/graingert).
* ⬆️ Upgrade python-jose dependency to `>=3.3.0,<4.0.0` for tests. PR [#3468](https://github.com/tiangolo/fastapi/pull/3468) by [@tiangolo](https://github.com/tiangolo).
## 0.66.0
### Features
* ✨ Allow setting the `response_class` to `RedirectResponse` or `FileResponse` and returning the URL from the function. New and updated docs are in the tutorial section **Custom Response - HTML, Stream, File, others**, in [RedirectResponse](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse) and in [FileResponse](https://fastapi.tiangolo.com/advanced/custom-response/#fileresponse). PR [#3457](https://github.com/tiangolo/fastapi/pull/3457) by [@tiangolo](https://github.com/tiangolo).
### Fixes
* 🐛 Fix include/exclude for dicts in `jsonable_encoder`. PR [#2016](https://github.com/tiangolo/fastapi/pull/2016) by [@Rubikoid](https://github.com/Rubikoid).
* 🐛 Support custom OpenAPI / JSON Schema fields in the generated output OpenAPI. PR [#1429](https://github.com/tiangolo/fastapi/pull/1429) by [@jmagnusson](https://github.com/jmagnusson).
### Translations
* 🌐 Add Spanish translation for `tutorial/query-params.md`. PR [#2243](https://github.com/tiangolo/fastapi/pull/2243) by [@mariacamilagl](https://github.com/mariacamilagl).
* 🌐 Add Spanish translation for `advanced/response-directly.md`. PR [#1253](https://github.com/tiangolo/fastapi/pull/1253) by [@jfunez](https://github.com/jfunez).
* 🌐 Add Spanish translation for `advanced/additional-status-codes.md`. PR [#1252](https://github.com/tiangolo/fastapi/pull/1252) by [@jfunez](https://github.com/jfunez).
* 🌐 Add Spanish translation for `advanced/path-operation-advanced-configuration.md`. PR [#1251](https://github.com/tiangolo/fastapi/pull/1251) by [@jfunez](https://github.com/jfunez).
## 0.65.3

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -190,6 +191,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -0,0 +1,37 @@
# Códigos de estado adicionales
Por defecto, **FastAPI** devolverá las respuestas utilizando una `JSONResponse`, poniendo el contenido que devuelves en tu *operación de path* dentro de esa `JSONResponse`.
Utilizará el código de estado por defecto, o el que hayas asignado en tu *operación de path*.
## Códigos de estado adicionales
Si quieres devolver códigos de estado adicionales además del principal, puedes hacerlo devolviendo directamente una `Response`, como una `JSONResponse`, y asignar directamente el código de estado adicional.
Por ejemplo, digamos que quieres tener una *operación de path* que permita actualizar ítems y devolver códigos de estado HTTP 200 "OK" cuando sea exitosa.
Pero también quieres que acepte nuevos ítems. Cuando los ítems no existan anteriormente, serán creados y devolverá un código de estado HTTP 201 "Created".
Para conseguir esto importa `JSONResponse` y devuelve ahí directamente tu contenido, asignando el `status_code` que quieras:
```Python hl_lines="2 19"
{!../../../docs_src/additional_status_codes/tutorial001.py!}
```
!!! warning "Advertencia"
Cuando devuelves directamente una `Response`, como en los ejemplos anteriores, será devuelta directamente.
No será serializado con el modelo, etc.
Asegurate de que la respuesta tenga los datos que quieras, y que los valores sean JSON válidos (si estás usando `JSONResponse`).
!!! note "Detalles Técnicos"
También podrías utilizar `from starlette.responses import JSONResponse`.
**FastAPI** provee las mismas `starlette.responses` que `fastapi.responses` simplemente como una convención para ti, el desarrollador. Pero la mayoría de las respuestas disponibles vienen directamente de Starlette. Lo mismo con `status`.
## OpenAPI y documentación de API
Si quieres devolver códigos de estado y respuestas adicionales directamente, estas no estarán incluidas en el schema de OpenAPI (documentación de API), porque FastAPI no tiene una manera de conocer de antemano lo que vas a devolver.
Pero puedes documentar eso en tu código usando [Respuestas Adicionales](additional-responses.md){.internal-link target=_blank}.

View File

@@ -0,0 +1,52 @@
# Configuración avanzada de las operaciones de path
## OpenAPI operationId
!!! warning "Advertencia"
Si no eres una persona "experta" en OpenAPI, probablemente no necesitas leer esto.
Puedes asignar el `operationId` de OpenAPI para ser usado en tu *operación de path* con el parámetro `operation_id`.
En este caso tendrías que asegurarte de que sea único para cada operación.
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial001.py!}
```
### Usando el nombre de la *función de la operación de path* en el operationId
Si quieres usar tus nombres de funciones de API como `operationId`s, puedes iterar sobre todos ellos y sobrescribir `operation_id` de cada *operación de path* usando su `APIRoute.name`.
Deberías hacerlo después de adicionar todas tus *operaciones de path*.
```Python hl_lines="2 12 13 14 15 16 17 18 19 20 21 24"
{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
```
!!! tip "Consejo"
Si llamas manualmente a `app.openapi()`, debes actualizar el `operationId`s antes de hacerlo.
!!! warning "Advertencia"
Si haces esto, debes asegurarte de que cada una de tus *funciones de las operaciones de path* tenga un nombre único.
Incluso si están en diferentes módulos (archivos Python).
## Excluir de OpenAPI
Para excluir una *operación de path* del esquema OpenAPI generado (y por tanto del la documentación generada automáticamente), usa el parámetro `include_in_schema` y asigna el valor como `False`;
```Python hl_lines="6"
{!../../../docs_src/path_operation_advanced_configuration/tutorial003.py!}
```
## Descripción avanzada desde el docstring
Puedes limitar las líneas usadas desde el docstring de una *operación de path* para OpenAPI.
Agregar un `\f` (un carácter de "form feed" escapado) hace que **FastAPI** trunque el output utilizada para OpenAPI en ese punto.
No será mostrado en la documentación, pero otras herramientas (como Sphinx) serán capaces de usar el resto.
```Python hl_lines="19 20 21 22 23 24 25 26 27 28 29"
{!../../../docs_src/path_operation_advanced_configuration/tutorial004.py!}
```

View File

@@ -0,0 +1,63 @@
# Devolver una respuesta directamente
Cuando creas una *operación de path* normalmente puedes devolver cualquier dato: un `dict`, una `list`, un modelo Pydantic, un modelo de base de datos, etc.
Por defecto, **FastAPI** convertiría automáticamente ese valor devuelto a JSON usando el `jsonable_encoder` explicado en [Codificador Compatible JSON](../tutorial/encoder.md){.internal-link target=_blank}.
Luego, tras bastidores, pondría esos datos compatibles con JSON (por ejemplo, un `dict`) dentro de una `JSONResponse` que se usaría para enviar la respuesta al cliente.
Pero puedes devolver una `JSONResponse` directamente de tu *operación de path*.
Esto puede ser útil, por ejemplo, para devolver cookies o headers personalizados.
## Devolver una `Response`
De hecho, puedes devolver cualquier `Response` o cualquier subclase de la misma.
!!! tip "Consejo"
`JSONResponse` en sí misma es una subclase de `Response`.
Y cuando devuelves una `Response`, **FastAPI** la pasará directamente.
No hará ninguna conversión de datos con modelos Pydantic, no convertirá el contenido a ningún tipo, etc.
Esto te da mucha flexibilidad. Puedes devolver cualquier tipo de dato, sobrescribir cualquer declaración de datos o validación, etc.
## Usando el `jsonable_encoder` en una `Response`
Como **FastAPI** no realiza ningún cambio en la `Response` que devuelves, debes asegurarte de que el contenido está listo.
Por ejemplo, no puedes poner un modelo Pydantic en una `JSONResponse` sin primero convertirlo a un `dict` con todos los tipos de datos (como `datetime`, `UUID`, etc) convertidos a tipos compatibles con JSON.
Para esos casos, puedes usar el `jsonable_encoder` para convertir tus datos antes de pasarlos a la respuesta:
```Python hl_lines="4 6 20 21"
{!../../../docs_src/response_directly/tutorial001.py!}
```
!!! note "Detalles Técnicos"
También puedes usar `from starlette.responses import JSONResponse`.
**FastAPI** provee `starlette.responses` como `fastapi.responses`, simplemente como una conveniencia para ti, el desarrollador. Pero la mayoría de las respuestas disponibles vienen directamente de Starlette.
## Devolviendo una `Response` personalizada
El ejemplo anterior muestra las partes que necesitas, pero no es muy útil todavía, dado que podrías simplemente devolver el `item` directamente, y **FastAPI** lo pondría en una `JSONResponse` por ti, convirtiéndolo en un `dict`, etc. Todo esto por defecto.
Ahora, veamos cómo puedes usarlo para devolver una respuesta personalizada.
Digamos que quieres devolver una respuesta <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>.
Podrías poner tu contenido XML en un string, ponerlo en una `Response` y devolverlo:
```Python hl_lines="1 18"
{!../../../docs_src/response_directly/tutorial002.py!}
```
## Notas
Cuando devuelves una `Response` directamente, los datos no son validados, convertidos (serializados), ni documentados automáticamente.
Pero todavía es posible documentarlo como es descrito en [Respuestas adicionales en OpenAPI](additional-responses.md){.internal-link target=_blank}.
Puedes ver en secciones posteriores como usar/declarar esas `Response`s personalizadas aún teniendo conversión automática de datos, documentación, etc.

View File

@@ -0,0 +1,197 @@
# Parámetros de query
Cuando declaras otros parámetros de la función que no hacen parte de los parámetros de path estos se interpretan automáticamente como parámetros de "query".
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
El query es el conjunto de pares de key-value que van después del `?` en la URL, separados por caracteres `&`.
Por ejemplo, en la URL:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...los parámetros de query son:
* `skip`: con un valor de `0`
* `limit`: con un valor de `10`
Dado que son parte de la URL son strings "naturalmente".
Pero cuando los declaras con tipos de Python (en el ejemplo arriba, como `int`) son convertidos a ese tipo y son validados con él.
Todo el proceso que aplicaba a los parámetros de path también aplica a los parámetros de query:
* Soporte del editor (obviamente)
* <abbr title="convertir el string que viene de un HTTP request a datos de Python">"Parsing"</abbr> de datos
* Validación de datos
* Documentación automática
## Configuraciones por defecto
Como los parámetros de query no están fijos en una parte del path pueden ser opcionales y pueden tener valores por defecto.
El ejemplo arriba tiene `skip=0` y `limit=10` como los valores por defecto.
Entonces, si vas a la URL:
```
http://127.0.0.1:8000/items/
```
Sería lo mismo que ir a:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
Pero, si por ejemplo vas a:
```
http://127.0.0.1:8000/items/?skip=20
```
Los valores de los parámetros en tu función serán:
* `skip=20`: porque lo definiste en la URL
* `limit=10`: porque era el valor por defecto
## Parámetros opcionales
Del mismo modo puedes declarar parámetros de query opcionales definiendo el valor por defecto como `None`:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial002.py!}
```
En este caso el parámetro de la función `q` será opcional y será `None` por defecto.
!!! check "Revisa"
También puedes notar que **FastAPI** es lo suficientemente inteligente para darse cuenta de que el parámetro de path `item_id` es un parámetro de path y que `q` no lo es, y por lo tanto es un parámetro de query.
!!! note "Nota"
FastAPI sabrá que `q` es opcional por el `= None`.
El `Optional` en `Optional[str]` no es usado por FastAPI (FastAPI solo usará la parte `str`), pero el `Optional[str]` le permitirá a tu editor ayudarte a encontrar errores en tu código.
## Conversión de tipos de parámetros de query
También puedes declarar tipos `bool` y serán convertidos:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial003.py!}
```
En este caso, si vas a:
```
http://127.0.0.1:8000/items/foo?short=1
```
o
```
http://127.0.0.1:8000/items/foo?short=True
```
o
```
http://127.0.0.1:8000/items/foo?short=true
```
o
```
http://127.0.0.1:8000/items/foo?short=on
```
o
```
http://127.0.0.1:8000/items/foo?short=yes
```
o cualquier otra variación (mayúsculas, primera letra en mayúscula, etc.) tu función verá el parámetro `short` con un valor `bool` de `True`. Si no, lo verá como `False`.
## Múltiples parámetros de path y query
Puedes declarar múltiples parámetros de path y parámetros de query al mismo tiempo. **FastAPI** sabe cuál es cuál.
No los tienes que declarar en un orden específico.
Serán detectados por nombre:
```Python hl_lines="8 10"
{!../../../docs_src/query_params/tutorial004.py!}
```
## Parámetros de query requeridos
Cuando declaras un valor por defecto para los parámetros que no son de path (por ahora solo hemos visto parámetros de query), entonces no es requerido.
Si no quieres añadir un valor específico sino solo hacerlo opcional, pon el valor por defecto como `None`.
Pero cuando quieres hacer que un parámetro de query sea requerido, puedes simplemente no declararle un valor por defecto:
```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
Aquí el parámetro de query `needy` es un parámetro de query requerido, del tipo `str`.
Si abres tu navegador en una URL como:
```
http://127.0.0.1:8000/items/foo-item
```
...sin añadir el parámetro `needy` requerido, verás un error como:
```JSON
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
```
Dado que `needy` es un parámetro requerido necesitarías declararlo en la URL:
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
...esto funcionaría:
```JSON
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
```
Por supuesto que también puedes definir algunos parámetros como requeridos, con un valor por defecto y otros completamente opcionales:
```Python hl_lines="10"
{!../../../docs_src/query_params/tutorial006.py!}
```
En este caso hay 3 parámetros de query:
* `needy`, un `str` requerido.
* `skip`, un `int` con un valor por defecto de `0`.
* `limit`, un `int` opcional.
!!! tip "Consejo"
También podrías usar los `Enum`s de la misma manera que con los [Parámetros de path](path-params.md#predefined-values){.internal-link target=_blank}.

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -58,6 +59,7 @@ nav:
- tutorial/index.md
- tutorial/first-steps.md
- tutorial/path-params.md
- tutorial/query-params.md
- Guía de Usuario Avanzada:
- advanced/index.md
- async.md
@@ -96,6 +98,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -95,6 +96,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,12 +39,14 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
@@ -86,6 +88,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/
@@ -98,6 +102,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /pl/
name: pl
- link: /pt/
name: pt - português
- link: /ru/

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -87,6 +88,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -179,7 +179,7 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
これにはクラウドストレージとの連携や映像処理など、多くのライブラリが含まれています。
```Python hl_lines="2 10-11"
```Python hl_lines="2 10-12 14"
{!../../../docs_src/custom_response/tutorial008.py!}
```

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -126,6 +127,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -93,6 +94,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,8 +39,10 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
@@ -86,10 +88,14 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/

View File

@@ -0,0 +1,7 @@
# Implantação - Introdução
A implantação de uma aplicação **FastAPI** é relativamente simples.
Existem várias maneiras para fazer isso, dependendo do seu caso específico e das ferramentas que você utiliza.
Você verá mais detalhes para se ter em mente e algumas das técnicas para a implantação nas próximas seções.

View File

@@ -0,0 +1,101 @@
# Introdução à segurança
Há várias formas de lidar segurança, autenticação e autorização.
E isso normalmente é um tópico “difícil” e complexo.
Em muitos frameworks e sistemas, apenas lidar com segurança e autenticação exige muito esforço e código (em muitos casos isso pode ser 50% ou mais de todo o código escrito).
**FastAPI** tem muitas ferramentas para ajudar você com a parte de **Segurança** facilmente, rapidamente, de uma forma padrão, sem ter que estudar e aprender tudo sobre especificações de segurança.
Mas primeiro, vamos verificar alguns pequenos conceitos.
## Está com pressa?
Se você não se importa com qualquer um desses termos e só precisa adicionar segurança com autenticação baseada em usuário e senha _agora_, pule para os próximos capítulos.
## OAuth2
OAuth2 é uma especificação que define várias formas para lidar com autenticação e autorização.
Ela é bastante extensiva na especificação e cobre casos de uso muito complexos.
Ela inclui uma forma para autenticação usando “third party”/aplicações de terceiros.
Isso é o que todos os sistemas com “Login with Facebook, Google, Twitter, GitHub” usam por baixo.
### OAuth 1
Havia um OAuth 1, que é bem diferente do OAuth2, e mais complexo, isso incluía diretamente as especificações de como criptografar a comunicação.
Não é muito popular ou usado nos dias atuais.
OAuth2 não especifica como criptografar a comunicação, ele espera que você tenha sua aplicação em um servidor HTTPS.
!!! tip "Dica"
Na seção sobre **deployment** você irá ver como configurar HTTPS de modo gratuito, usando Traefik e Lets Encrypt.
## OpenID Connect
OpenID Connect é outra especificação, baseada em **OAuth2**.
Ela é apenas uma extensão do OAuth2 especificando algumas coisas que são relativamente ambíguas no OAuth2, para tentar torná-lo mais interoperável.
Por exemplo, o login do Google usa OpenID Connect (que por baixo dos panos usa OAuth2).
Mas o login do Facebook não tem suporte para OpenID Connect. Ele tem a própria implementação do OAuth2.
### OpenID (não "OpenID Connect")
Houve também uma especificação “OpenID”. Ela tentou resolver a mesma coisa que a **OpenID Connect**, mas não baseada em OAuth2.
Então, ela foi um sistema adicional completo.
Ela não é muito popular ou usada nos dias de hoje.
## OpenAPI
OpenAPI (anteriormente conhecido como Swagger) é a especificação aberta para a criação de APIs (agora parte da Linux Foundation).
**FastAPI** é baseado no **OpenAPI**.
Isso é o que torna possível ter múltiplas automações interativas de interfaces de documentação, geração de código, etc.
OpenAPI tem uma forma para definir múltiplos “esquemas” de segurança.
Por usá-los, você pode ter vantagens de todas essas ferramentas baseadas nos padrões, incluindo os sistemas de documentação interativa.
OpenAPI define os seguintes esquemas de segurança:
* `apiKey`: uma chave específica de aplicação que pode vir de:
* Um parâmetro query.
* Um header.
* Um cookie.
* `http`: padrão HTTP de sistemas autenticação, incluindo:
* `bearer`: um header de `Authorization` com valor de `Bearer` adicionado de um token. Isso é herança do OAuth2.
* HTTP Basic authentication.
* HTTP Digest, etc.
* `oauth2`: todas as formas do OAuth2 para lidar com segurança (chamados "fluxos").
* Vários desses fluxos são apropriados para construir um provedor de autenticação OAuth2 (como Google, Facebook, Twitter, GitHub, etc):
* `implicit`
* `clientCredentials`
* `authorizationCode`
* Mas existe um “fluxo” específico que pode ser perfeitamente usado para resolver autenticação diretamente na mesma aplicação:
* `password`: alguns dos próximos capítulos tratarão disso.
* `openIdConnect`: tem uma forma para definir como descobrir automaticamente o dado da autenticação OAuth2.
* Essa descoberta automática é o que é definido na especificação OpenID Connect.
!!! tip "Dica"
Integração com outros provedores de autenticação/autorização como Google, Facebook, Twitter, GitHub, etc. é bem possível e relativamente fácil.
O problema mais complexo é criar um provedor de autenticação/autorização como eles, mas o FastAPI dá a você ferramentas para fazer isso facilmente, enquanto faz o trabalho pesado para você.
## **FastAPI** utilitários
**FastAPI** fornece várias ferramentas para cada um desses esquemas de segurança no módulo `fastapi.security` que simplesmente usa esses mecanismos de segurança.
Nos próximos capítulos você irá ver como adicionar segurança à sua API usando essas ferramentas disponibilizadas pelo **FastAPI**.
E você irá ver também como isso é automaticamente integrado dentro do sistema de documentação interativo.

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -57,6 +58,10 @@ nav:
- tutorial/index.md
- tutorial/first-steps.md
- tutorial/body-fields.md
- Segurança:
- tutorial/security/index.md
- Implantação:
- deployment/index.md
- alternatives.md
- history-design-future.md
- external-links.md
@@ -96,6 +101,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -87,6 +88,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -87,6 +88,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -87,6 +88,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -87,6 +88,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -183,7 +183,7 @@ FastAPI实际上是 Starlette将自动包含 Content-Length 的头。它
包括许多与云存储,视频处理等交互的库。
```Python hl_lines="2 10 11"
```Python hl_lines="2 10-12 14"
{!../../../docs_src/custom_response/tutorial008.py!}
```

View File

@@ -39,6 +39,7 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- de: /de/
- es: /es/
- fr: /fr/
- id: /id/
@@ -133,6 +134,8 @@ extra:
alternate:
- link: /
name: en - English
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fr/

View File

@@ -5,5 +5,5 @@ app = FastAPI()
@app.get("/typer")
async def read_typer():
async def redirect_typer():
return RedirectResponse("https://typer.tiangolo.com")

View File

@@ -0,0 +1,9 @@
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/fastapi", response_class=RedirectResponse)
async def redirect_fastapi():
return "https://fastapi.tiangolo.com"

View File

@@ -0,0 +1,9 @@
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/pydantic", response_class=RedirectResponse, status_code=302)
async def redirect_pydantic():
return "https://pydantic-docs.helpmanual.io/"

View File

@@ -7,5 +7,8 @@ app = FastAPI()
@app.get("/")
def main():
file_like = open(some_file_path, mode="rb")
return StreamingResponse(file_like, media_type="video/mp4")
def iterfile(): # (1)
with open(some_file_path, mode="rb") as file_like: # (2)
yield from file_like # (3)
return StreamingResponse(iterfile(), media_type="video/mp4")

View File

@@ -0,0 +1,10 @@
from fastapi import FastAPI
from fastapi.responses import FileResponse
some_file_path = "large-video-file.mp4"
app = FastAPI()
@app.get("/", response_class=FileResponse)
async def main():
return some_file_path

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.65.3"
__version__ = "0.66.1"
from starlette import status as status

View File

@@ -206,7 +206,7 @@ class FastAPI(Starlette):
endpoint: Callable[..., Coroutine[Any, Any, Response]],
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -258,7 +258,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -351,7 +351,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -400,7 +400,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -449,7 +449,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -498,7 +498,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -547,7 +547,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -596,7 +596,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -645,7 +645,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,
@@ -694,7 +694,7 @@ class FastAPI(Starlette):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[Depends]] = None,
summary: Optional[str] = None,

View File

@@ -36,9 +36,9 @@ def jsonable_encoder(
custom_encoder: Dict[Any, Callable[[Any], Any]] = {},
sqlalchemy_safe: bool = True,
) -> Any:
if include is not None and not isinstance(include, set):
if include is not None and not isinstance(include, (set, dict)):
include = set(include)
if exclude is not None and not isinstance(exclude, set):
if exclude is not None and not isinstance(exclude, (set, dict)):
exclude = set(exclude)
if isinstance(obj, BaseModel):
encoder = getattr(obj.__config__, "json_encoders", {})

View File

@@ -117,6 +117,9 @@ class SchemaBase(BaseModel):
example: Optional[Any] = None
deprecated: Optional[bool] = None
class Config:
extra: str = "allow"
class Schema(SchemaBase):
allOf: Optional[List[SchemaBase]] = None

View File

@@ -1,4 +1,5 @@
import http.client
import inspect
from enum import Enum
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
@@ -218,7 +219,19 @@ def get_openapi_path(
)
callbacks[callback.name] = {callback.path: cb_path}
operation["callbacks"] = callbacks
status_code = str(route.status_code)
if route.status_code is not None:
status_code = str(route.status_code)
else:
# It would probably make more sense for all response classes to have an
# explicit default status_code, and to extract it from them, instead of
# doing this inspection tricks, that would probably be in the future
# TODO: probably make status_code a default class attribute for all
# responses in Starlette
response_signature = inspect.signature(current_response_class.__init__)
status_code_param = response_signature.parameters.get("status_code")
if status_code_param is not None:
if isinstance(status_code_param.default, int):
status_code = str(status_code_param.default)
operation.setdefault("responses", {}).setdefault(status_code, {})[
"description"
] = route.response_description

View File

@@ -154,7 +154,7 @@ async def run_endpoint_function(
def get_request_handler(
dependant: Dependant,
body_field: Optional[ModelField] = None,
status_code: int = 200,
status_code: Optional[int] = None,
response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),
response_field: Optional[ModelField] = None,
response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
@@ -232,11 +232,12 @@ def get_request_handler(
exclude_none=response_model_exclude_none,
is_coroutine=is_coroutine,
)
response = actual_response_class(
content=response_data,
status_code=status_code,
background=background_tasks, # type: ignore # in Starlette
)
response_args: Dict[str, Any] = {"background": background_tasks}
# If status_code was set, use it, otherwise use the default from the
# response class, in the case of redirect it's 307
if status_code is not None:
response_args["status_code"] = status_code
response = actual_response_class(response_data, **response_args)
response.headers.raw.extend(sub_response.headers.raw)
if sub_response.status_code:
response.status_code = sub_response.status_code
@@ -293,7 +294,7 @@ class APIRoute(routing.Route):
endpoint: Callable[..., Any],
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -469,7 +470,7 @@ class APIRouter(routing.Router):
endpoint: Callable[..., Any],
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -541,7 +542,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -719,7 +720,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -769,7 +770,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -819,7 +820,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -869,7 +870,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -919,7 +920,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -969,7 +970,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -1019,7 +1020,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,
@@ -1069,7 +1070,7 @@ class APIRouter(routing.Router):
path: str,
*,
response_model: Optional[Type[Any]] = None,
status_code: int = 200,
status_code: Optional[int] = None,
tags: Optional[List[str]] = None,
dependencies: Optional[Sequence[params.Depends]] = None,
summary: Optional[str] = None,

View File

@@ -43,8 +43,8 @@ Documentation = "https://fastapi.tiangolo.com/"
[tool.flit.metadata.requires-extra]
test = [
"pytest ==5.4.3",
"pytest-cov ==2.10.0",
"pytest >=6.2.4,<7.0.0",
"pytest-cov >=2.12.0,<3.0.0",
"pytest-asyncio >=0.14.0,<0.15.0",
"mypy ==0.812",
"flake8 >=3.8.3,<4.0.0",
@@ -73,7 +73,7 @@ doc = [
"pyyaml >=5.3.1,<6.0.0"
]
dev = [
"python-jose[cryptography] >=3.1.0,<4.0.0",
"python-jose[cryptography] >=3.3.0,<4.0.0",
"passlib[bcrypt] >=1.7.2,<2.0.0",
"autoflake >=1.3.1,<2.0.0",
"flake8 >=3.8.3,<4.0.0",
@@ -99,3 +99,18 @@ all = [
[tool.isort]
profile = "black"
known_third_party = ["fastapi", "pydantic", "starlette"]
[tool.pytest.ini_options]
addopts = [
"--strict-config",
"--strict-markers",
]
xfail_strict = true
junit_family = "xunit2"
filterwarnings = [
"error",
'ignore:"@coroutine" decorator is deprecated since Python 3\.8, use "async def" instead:DeprecationWarning',
# TODO: if these ignores are needed, enable them, otherwise remove them
# 'ignore:The explicit passing of coroutine objects to asyncio\.wait\(\) is deprecated since Python 3\.8:DeprecationWarning',
# 'ignore:Exception ignored in. <socket\.socket fd=-1:pytest.PytestUnraisableExceptionWarning',
]

View File

@@ -0,0 +1,51 @@
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
class Config:
schema_extra = {
"x-something-internal": {"level": 4},
}
@app.get("/foo", response_model=Item)
def foo():
return {"name": "Foo item"}
client = TestClient(app)
item_schema = {
"title": "Item",
"required": ["name"],
"type": "object",
"x-something-internal": {
"level": 4,
},
"properties": {
"name": {
"title": "Name",
"type": "string",
}
},
}
def test_custom_response_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json()["components"]["schemas"]["Item"] == item_schema
def test_response():
# For coverage
response = client.get("/foo")
assert response.status_code == 200, response.text
assert response.json() == {"name": "Foo item"}

View File

@@ -0,0 +1,175 @@
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
class Model1(BaseModel):
foo: str
bar: str
class Model2(BaseModel):
ref: Model1
baz: str
class Model3(BaseModel):
name: str
age: int
ref2: Model2
app = FastAPI()
@app.get(
"/simple_include",
response_model=Model2,
response_model_include={"baz": ..., "ref": {"foo"}},
)
def simple_include():
return Model2(
ref=Model1(foo="simple_include model foo", bar="simple_include model bar"),
baz="simple_include model2 baz",
)
@app.get(
"/simple_include_dict",
response_model=Model2,
response_model_include={"baz": ..., "ref": {"foo"}},
)
def simple_include_dict():
return {
"ref": {
"foo": "simple_include_dict model foo",
"bar": "simple_include_dict model bar",
},
"baz": "simple_include_dict model2 baz",
}
@app.get(
"/simple_exclude",
response_model=Model2,
response_model_exclude={"ref": {"bar"}},
)
def simple_exclude():
return Model2(
ref=Model1(foo="simple_exclude model foo", bar="simple_exclude model bar"),
baz="simple_exclude model2 baz",
)
@app.get(
"/simple_exclude_dict",
response_model=Model2,
response_model_exclude={"ref": {"bar"}},
)
def simple_exclude_dict():
return {
"ref": {
"foo": "simple_exclude_dict model foo",
"bar": "simple_exclude_dict model bar",
},
"baz": "simple_exclude_dict model2 baz",
}
@app.get(
"/mixed",
response_model=Model3,
response_model_include={"ref2", "name"},
response_model_exclude={"ref2": {"baz"}},
)
def mixed():
return Model3(
name="mixed model3 name",
age=3,
ref2=Model2(
ref=Model1(foo="mixed model foo", bar="mixed model bar"),
baz="mixed model2 baz",
),
)
@app.get(
"/mixed_dict",
response_model=Model3,
response_model_include={"ref2", "name"},
response_model_exclude={"ref2": {"baz"}},
)
def mixed_dict():
return {
"name": "mixed_dict model3 name",
"age": 3,
"ref2": {
"ref": {"foo": "mixed_dict model foo", "bar": "mixed_dict model bar"},
"baz": "mixed_dict model2 baz",
},
}
client = TestClient(app)
def test_nested_include_simple():
response = client.get("/simple_include")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_include model2 baz",
"ref": {"foo": "simple_include model foo"},
}
def test_nested_include_simple_dict():
response = client.get("/simple_include_dict")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_include_dict model2 baz",
"ref": {"foo": "simple_include_dict model foo"},
}
def test_nested_exclude_simple():
response = client.get("/simple_exclude")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_exclude model2 baz",
"ref": {"foo": "simple_exclude model foo"},
}
def test_nested_exclude_simple_dict():
response = client.get("/simple_exclude_dict")
assert response.status_code == 200, response.text
assert response.json() == {
"baz": "simple_exclude_dict model2 baz",
"ref": {"foo": "simple_exclude_dict model foo"},
}
def test_nested_include_mixed():
response = client.get("/mixed")
assert response.status_code == 200, response.text
assert response.json() == {
"name": "mixed model3 name",
"ref2": {
"ref": {"foo": "mixed model foo", "bar": "mixed model bar"},
},
}
def test_nested_include_mixed_dict():
response = client.get("/mixed_dict")
assert response.status_code == 200, response.text
assert response.json() == {
"name": "mixed_dict model3 name",
"ref2": {
"ref": {"foo": "mixed_dict model foo", "bar": "mixed_dict model bar"},
},
}

View File

@@ -5,6 +5,32 @@ from docs_src.custom_response.tutorial006 import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/typer": {
"get": {
"summary": "Redirect Typer",
"operationId": "redirect_typer_typer_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
}
},
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_get():
response = client.get("/typer", allow_redirects=False)
assert response.status_code == 307, response.text

View File

@@ -0,0 +1,32 @@
from fastapi.testclient import TestClient
from docs_src.custom_response.tutorial006b import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/fastapi": {
"get": {
"summary": "Redirect Fastapi",
"operationId": "redirect_fastapi_fastapi_get",
"responses": {"307": {"description": "Successful Response"}},
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_redirect_response_class():
response = client.get("/fastapi", allow_redirects=False)
assert response.status_code == 307
assert response.headers["location"] == "https://fastapi.tiangolo.com"

View File

@@ -0,0 +1,32 @@
from fastapi.testclient import TestClient
from docs_src.custom_response.tutorial006c import app
client = TestClient(app)
openapi_schema = {
"openapi": "3.0.2",
"info": {"title": "FastAPI", "version": "0.1.0"},
"paths": {
"/pydantic": {
"get": {
"summary": "Redirect Pydantic",
"operationId": "redirect_pydantic_pydantic_get",
"responses": {"302": {"description": "Successful Response"}},
}
}
},
}
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_redirect_status_code():
response = client.get("/pydantic", allow_redirects=False)
assert response.status_code == 302
assert response.headers["location"] == "https://pydantic-docs.helpmanual.io/"

View File

@@ -0,0 +1,17 @@
from pathlib import Path
from fastapi.testclient import TestClient
from docs_src.custom_response import tutorial009
from docs_src.custom_response.tutorial009 import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
tutorial009.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
assert response.content == test_content

View File

@@ -0,0 +1,17 @@
from pathlib import Path
from fastapi.testclient import TestClient
from docs_src.custom_response import tutorial009b
from docs_src.custom_response.tutorial009b import app
client = TestClient(app)
def test_get(tmp_path: Path):
file_path: Path = tmp_path / "large-video-file.mp4"
tutorial009b.some_file_path = str(file_path)
test_content = b"Fake video bytes"
file_path.write_bytes(test_content)
response = client.get("/")
assert response.content == test_content

View File

@@ -1,5 +1,3 @@
import os
from fastapi.testclient import TestClient
from docs_src.request_files.tutorial001 import app
@@ -152,35 +150,35 @@ def test_post_body_json():
assert response.json() == file_required
def test_post_file(tmpdir):
path = os.path.join(tmpdir, "test.txt")
with open(path, "wb") as file:
file.write(b"<file content>")
def test_post_file(tmp_path):
path = tmp_path / "test.txt"
path.write_bytes(b"<file content>")
client = TestClient(app)
response = client.post("/files/", files={"file": open(path, "rb")})
with path.open("rb") as file:
response = client.post("/files/", files={"file": file})
assert response.status_code == 200, response.text
assert response.json() == {"file_size": 14}
def test_post_large_file(tmpdir):
def test_post_large_file(tmp_path):
default_pydantic_max_size = 2 ** 16
path = os.path.join(tmpdir, "test.txt")
with open(path, "wb") as file:
file.write(b"x" * (default_pydantic_max_size + 1))
path = tmp_path / "test.txt"
path.write_bytes(b"x" * (default_pydantic_max_size + 1))
client = TestClient(app)
response = client.post("/files/", files={"file": open(path, "rb")})
with path.open("rb") as file:
response = client.post("/files/", files={"file": file})
assert response.status_code == 200, response.text
assert response.json() == {"file_size": default_pydantic_max_size + 1}
def test_post_upload_file(tmpdir):
path = os.path.join(tmpdir, "test.txt")
with open(path, "wb") as file:
file.write(b"<file content>")
def test_post_upload_file(tmp_path):
path = tmp_path / "test.txt"
path.write_bytes(b"<file content>")
client = TestClient(app)
response = client.post("/uploadfile/", files={"file": open(path, "rb")})
with path.open("rb") as file:
response = client.post("/uploadfile/", files={"file": file})
assert response.status_code == 200, response.text
assert response.json() == {"filename": "test.txt"}

View File

@@ -1,5 +1,3 @@
import os
from fastapi.testclient import TestClient
from docs_src.request_files.tutorial002 import app
@@ -172,42 +170,40 @@ def test_post_body_json():
assert response.json() == file_required
def test_post_files(tmpdir):
path = os.path.join(tmpdir, "test.txt")
with open(path, "wb") as file:
file.write(b"<file content>")
path2 = os.path.join(tmpdir, "test2.txt")
with open(path2, "wb") as file:
file.write(b"<file content2>")
def test_post_files(tmp_path):
path = tmp_path / "test.txt"
path.write_bytes(b"<file content>")
path2 = tmp_path / "test2.txt"
path2.write_bytes(b"<file content2>")
client = TestClient(app)
response = client.post(
"/files/",
files=(
("files", ("test.txt", open(path, "rb"))),
("files", ("test2.txt", open(path2, "rb"))),
),
)
with path.open("rb") as file, path2.open("rb") as file2:
response = client.post(
"/files/",
files=(
("files", ("test.txt", file)),
("files", ("test2.txt", file2)),
),
)
assert response.status_code == 200, response.text
assert response.json() == {"file_sizes": [14, 15]}
def test_post_upload_file(tmpdir):
path = os.path.join(tmpdir, "test.txt")
with open(path, "wb") as file:
file.write(b"<file content>")
path2 = os.path.join(tmpdir, "test2.txt")
with open(path2, "wb") as file:
file.write(b"<file content2>")
def test_post_upload_file(tmp_path):
path = tmp_path / "test.txt"
path.write_bytes(b"<file content>")
path2 = tmp_path / "test2.txt"
path2.write_bytes(b"<file content2>")
client = TestClient(app)
response = client.post(
"/uploadfiles/",
files=(
("files", ("test.txt", open(path, "rb"))),
("files", ("test2.txt", open(path2, "rb"))),
),
)
with path.open("rb") as file, path2.open("rb") as file2:
response = client.post(
"/uploadfiles/",
files=(
("files", ("test.txt", file)),
("files", ("test2.txt", file2)),
),
)
assert response.status_code == 200, response.text
assert response.json() == {"filenames": ["test.txt", "test2.txt"]}

View File

@@ -1,6 +1,3 @@
import os
from pathlib import Path
from fastapi.testclient import TestClient
from docs_src.request_forms_and_files.tutorial001 import app
@@ -163,32 +160,30 @@ def test_post_body_json():
assert response.json() == file_and_token_required
def test_post_file_no_token(tmpdir):
path = os.path.join(tmpdir, "test.txt")
with open(path, "wb") as file:
file.write(b"<file content>")
def test_post_file_no_token(tmp_path):
path = tmp_path / "test.txt"
path.write_bytes(b"<file content>")
client = TestClient(app)
response = client.post("/files/", files={"file": open(path, "rb")})
with path.open("rb") as file:
response = client.post("/files/", files={"file": file})
assert response.status_code == 422, response.text
assert response.json() == token_required
def test_post_files_and_token(tmpdir):
patha = Path(tmpdir) / "test.txt"
pathb = Path(tmpdir) / "testb.txt"
def test_post_files_and_token(tmp_path):
patha = tmp_path / "test.txt"
pathb = tmp_path / "testb.txt"
patha.write_text("<file content>")
pathb.write_text("<file b content>")
client = TestClient(app)
response = client.post(
"/files/",
data={"token": "foo"},
files={
"file": patha.open("rb"),
"fileb": ("testb.txt", pathb.open("rb"), "text/plain"),
},
)
with patha.open("rb") as filea, pathb.open("rb") as fileb:
response = client.post(
"/files/",
data={"token": "foo"},
files={"file": filea, "fileb": ("testb.txt", fileb, "text/plain")},
)
assert response.status_code == 200, response.text
assert response.json() == {
"file_size": 14,