@ -19,18 +19,16 @@ jobs: |
|||
run: | |
|||
rm -rf ./site |
|||
mkdir ./site |
|||
- name: Download Artifact Docs |
|||
id: download |
|||
uses: dawidd6/[email protected] |
|||
- uses: actions/download-artifact@v4 |
|||
with: |
|||
if_no_artifact_found: ignore |
|||
github_token: ${{ secrets.FASTAPI_PREVIEW_DOCS_DOWNLOAD_ARTIFACTS }} |
|||
workflow: build-docs.yml |
|||
run_id: ${{ github.event.workflow_run.id }} |
|||
name: docs-site |
|||
path: ./site/ |
|||
pattern: docs-site-* |
|||
merge-multiple: true |
|||
github-token: ${{ secrets.FASTAPI_PREVIEW_DOCS_DOWNLOAD_ARTIFACTS }} |
|||
run-id: ${{ github.event.workflow_run.id }} |
|||
- name: Deploy to Cloudflare Pages |
|||
if: steps.download.outputs.found_artifact == 'true' |
|||
# hashFiles returns an empty string if there are no files |
|||
if: hashFiles('./site/*') |
|||
id: deploy |
|||
uses: cloudflare/pages-action@v1 |
|||
with: |
|||
|
@ -8,6 +8,13 @@ on: |
|||
jobs: |
|||
publish: |
|||
runs-on: ubuntu-latest |
|||
strategy: |
|||
matrix: |
|||
package: |
|||
- fastapi |
|||
- fastapi-slim |
|||
permissions: |
|||
id-token: write |
|||
steps: |
|||
- name: Dump GitHub context |
|||
env: |
|||
@ -21,19 +28,14 @@ jobs: |
|||
# Issue ref: https://github.com/actions/setup-python/issues/436 |
|||
# cache: "pip" |
|||
# cache-dependency-path: pyproject.toml |
|||
- uses: actions/cache@v4 |
|||
id: cache |
|||
with: |
|||
path: ${{ env.pythonLocation }} |
|||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish |
|||
- name: Install build dependencies |
|||
run: pip install build |
|||
- name: Build distribution |
|||
env: |
|||
TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} |
|||
run: python -m build |
|||
- name: Publish |
|||
uses: pypa/[email protected] |
|||
with: |
|||
password: ${{ secrets.PYPI_API_TOKEN }} |
|||
- name: Dump GitHub context |
|||
env: |
|||
GITHUB_CONTEXT: ${{ toJson(github) }} |
|||
|
@ -24,13 +24,14 @@ jobs: |
|||
|
|||
- run: pip install smokeshow |
|||
|
|||
- uses: dawidd6/[email protected].4 |
|||
- uses: actions/download-artifact@v4 |
|||
with: |
|||
github_token: ${{ secrets.FASTAPI_SMOKESHOW_DOWNLOAD_ARTIFACTS }} |
|||
workflow: test.yml |
|||
commit: ${{ github.event.workflow_run.head_sha }} |
|||
name: coverage-html |
|||
path: htmlcov |
|||
github-token: ${{ secrets.FASTAPI_SMOKESHOW_DOWNLOAD_ARTIFACTS }} |
|||
run-id: ${{ github.event.workflow_run.id }} |
|||
|
|||
- run: smokeshow upload coverage-html |
|||
- run: smokeshow upload htmlcov |
|||
env: |
|||
SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage} |
|||
SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100 |
|||
|
@ -199,7 +199,7 @@ Next, you would run the server passing the configurations as environment variabl |
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" uvicorn main:app |
|||
$ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.py |
|||
|
|||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
|||
``` |
|||
@ -369,7 +369,7 @@ Here we define the config `env_file` inside of your Pydantic `Settings` class, a |
|||
|
|||
### Creating the `Settings` only once with `lru_cache` |
|||
|
|||
Reading a file from disk is normally a costly (slow) operation, so you probably want to do it only once and then re-use the same settings object, instead of reading it for each request. |
|||
Reading a file from disk is normally a costly (slow) operation, so you probably want to do it only once and then reuse the same settings object, instead of reading it for each request. |
|||
|
|||
But every time we do: |
|||
|
|||
|
@ -0,0 +1,80 @@ |
|||
# FastAPI CLI |
|||
|
|||
**FastAPI CLI** is a command line program that you can use to serve your FastAPI app, manage your FastAPI project, and more. |
|||
|
|||
When you install FastAPI (e.g. with `pip install fastapi`), it includes a package called `fastapi-cli`, this package provides the `fastapi` command in the terminal. |
|||
|
|||
To run your FastAPI app for development, you can use the `fastapi dev` command: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u> |
|||
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font> |
|||
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font> |
|||
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files |
|||
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font> |
|||
|
|||
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮ |
|||
│ │ |
|||
│ 🐍 main.py │ |
|||
│ │ |
|||
╰──────────────────────╯ |
|||
|
|||
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font> |
|||
<font color="#3465A4">INFO </font> Found importable FastAPI app |
|||
|
|||
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮ |
|||
│ │ |
|||
│ <span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span> │ |
|||
│ │ |
|||
╰──────────────────────────╯ |
|||
|
|||
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font> |
|||
|
|||
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ </font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"> │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span> |
|||
|
|||
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] |
|||
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit) |
|||
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font> |
|||
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>] |
|||
<font color="#4E9A06">INFO</font>: Waiting for application startup. |
|||
<font color="#4E9A06">INFO</font>: Application startup complete. |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
The command line program called `fastapi` is **FastAPI CLI**. |
|||
|
|||
FastAPI CLI takes the path to your Python program (e.g. `main.py`) and automatically detects the `FastAPI` instance (commonly named `app`), determines the correct import process, and then serves it. |
|||
|
|||
For production you would use `fastapi run` instead. 🚀 |
|||
|
|||
Internally, **FastAPI CLI** uses <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>, a high-performance, production-ready, ASGI server. 😎 |
|||
|
|||
## `fastapi dev` |
|||
|
|||
Running `fastapi dev` initiates development mode. |
|||
|
|||
By default, **auto-reload** is enabled, automatically reloading the server when you make changes to your code. This is resource-intensive and could be less stable than when it's disabled. You should only use it for development. It also listens on the IP address `127.0.0.1`, which is the IP for your machine to communicate with itself alone (`localhost`). |
|||
|
|||
## `fastapi run` |
|||
|
|||
Executing `fastapi run` starts FastAPI in production mode by default. |
|||
|
|||
By default, **auto-reload** is disabled. It also listens on the IP address `0.0.0.0`, which means all the available IP addresses, this way it will be publicly accessible to anyone that can communicate with the machine. This is how you would normally run it in production, for example, in a container. |
|||
|
|||
In most cases you would (and should) have a "termination proxy" handling HTTPS for you on top, this will depend on how you deploy your application, your provider might do this for you, or you might need to set it up yourself. |
|||
|
|||
!!! tip |
|||
You can learn more about it in the [deployment documentation](deployment/index.md){.internal-link target=_blank}. |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,56 @@ |
|||
# GraphQL |
|||
|
|||
Como **FastAPI** está basado en el estándar **ASGI**, es muy fácil integrar cualquier library **GraphQL** que sea compatible con ASGI. |
|||
|
|||
Puedes combinar *operaciones de path* regulares de la library de FastAPI con GraphQL en la misma aplicación. |
|||
|
|||
!!! tip |
|||
**GraphQL** resuelve algunos casos de uso específicos. |
|||
|
|||
Tiene **ventajas** y **desventajas** cuando lo comparas con **APIs web** comunes. |
|||
|
|||
Asegúrate de evaluar si los **beneficios** para tu caso de uso compensan las **desventajas.** 🤓 |
|||
|
|||
## Librerías GraphQL |
|||
|
|||
Aquí hay algunas de las libraries de **GraphQL** que tienen soporte con **ASGI** las cuales podrías usar con **FastAPI**: |
|||
|
|||
* <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a> 🍓 |
|||
* Con <a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">documentación para FastAPI</a> |
|||
* <a href="https://ariadnegraphql.org/" class="external-link" target="_blank">Ariadne</a> |
|||
* Con <a href="https://ariadnegraphql.org/docs/fastapi-integration" class="external-link" target="_blank">documentación para FastAPI</a> |
|||
* <a href="https://tartiflette.io/" class="external-link" target="_blank">Tartiflette</a> |
|||
* Con <a href="https://tartiflette.github.io/tartiflette-asgi/" class="external-link" target="_blank">Tartiflette ASGI</a> para proveer integración con ASGI |
|||
* <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a> |
|||
* Con <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a> |
|||
|
|||
## GraphQL con Strawberry |
|||
|
|||
Si necesitas o quieres trabajar con **GraphQL**, <a href="https://strawberry.rocks/" class="external-link" target="_blank">**Strawberry**</a> es la library **recomendada** por el diseño más cercano a **FastAPI**, el cual es completamente basado en **anotaciones de tipo**. |
|||
|
|||
Dependiendo de tus casos de uso, podrías preferir usar una library diferente, pero si me preguntas, probablemente te recomendaría **Strawberry**. |
|||
|
|||
Aquí hay una pequeña muestra de cómo podrías integrar Strawberry con FastAPI: |
|||
|
|||
```Python hl_lines="3 22 25-26" |
|||
{!../../../docs_src/graphql/tutorial001.py!} |
|||
``` |
|||
|
|||
Puedes aprender más sobre Strawberry en la <a href="https://strawberry.rocks/" class="external-link" target="_blank">documentación de Strawberry</a>. |
|||
|
|||
Y también en la documentación sobre <a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">Strawberry con FastAPI</a>. |
|||
|
|||
## Clase obsoleta `GraphQLApp` en Starlette |
|||
|
|||
Versiones anteriores de Starlette incluyen la clase `GraphQLApp` para integrarlo con <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a>. |
|||
|
|||
Esto fue marcado como obsoleto en Starlette, pero si aún tienes código que lo usa, puedes fácilmente **migrar** a <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a>, la cual cubre el mismo caso de uso y tiene una **interfaz casi idéntica.** |
|||
|
|||
!!! tip |
|||
Si necesitas GraphQL, te recomendaría revisar <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a>, que es basada en anotaciones de tipo en vez de clases y tipos personalizados. |
|||
|
|||
## Aprende más |
|||
|
|||
Puedes aprender más acerca de **GraphQL** en la <a href="https://graphql.org/" class="external-link" target="_blank">documentación oficial de GraphQL</a>. |
|||
|
|||
También puedes leer más acerca de cada library descrita anteriormente en sus enlaces. |
@ -0,0 +1,5 @@ |
|||
# Apprendre |
|||
|
|||
Voici les sections introductives et les tutoriels pour apprendre **FastAPI**. |
|||
|
|||
Vous pouvez considérer ceci comme un **manuel**, un **cours**, la **méthode officielle** et recommandée pour appréhender FastAPI. 😎 |
@ -0,0 +1,130 @@ |
|||
# 추가 데이터 자료형 |
|||
|
|||
지금까지 일반적인 데이터 자료형을 사용했습니다. 예를 들면 다음과 같습니다: |
|||
|
|||
* `int` |
|||
* `float` |
|||
* `str` |
|||
* `bool` |
|||
|
|||
하지만 더 복잡한 데이터 자료형 또한 사용할 수 있습니다. |
|||
|
|||
그리고 지금까지와 같은 기능들을 여전히 사용할 수 있습니다. |
|||
|
|||
* 훌륭한 편집기 지원. |
|||
* 들어오는 요청의 데이터 변환. |
|||
* 응답 데이터의 데이터 변환. |
|||
* 데이터 검증. |
|||
* 자동 어노테이션과 문서화. |
|||
|
|||
## 다른 데이터 자료형 |
|||
|
|||
아래의 추가적인 데이터 자료형을 사용할 수 있습니다: |
|||
|
|||
* `UUID`: |
|||
* 표준 "범용 고유 식별자"로, 많은 데이터베이스와 시스템에서 ID로 사용됩니다. |
|||
* 요청과 응답에서 `str`로 표현됩니다. |
|||
* `datetime.datetime`: |
|||
* 파이썬의 `datetime.datetime`. |
|||
* 요청과 응답에서 `2008-09-15T15:53:00+05:00`와 같은 ISO 8601 형식의 `str`로 표현됩니다. |
|||
* `datetime.date`: |
|||
* 파이썬의 `datetime.date`. |
|||
* 요청과 응답에서 `2008-09-15`와 같은 ISO 8601 형식의 `str`로 표현됩니다. |
|||
* `datetime.time`: |
|||
* 파이썬의 `datetime.time`. |
|||
* 요청과 응답에서 `14:23:55.003`와 같은 ISO 8601 형식의 `str`로 표현됩니다. |
|||
* `datetime.timedelta`: |
|||
* 파이썬의 `datetime.timedelta`. |
|||
* 요청과 응답에서 전체 초(seconds)의 `float`로 표현됩니다. |
|||
* Pydantic은 "ISO 8601 시차 인코딩"으로 표현하는 것 또한 허용합니다. <a href="https://docs.pydantic.dev/latest/concepts/serialization/#json_encoders" class="external-link" target="_blank">더 많은 정보는 이 문서에서 확인하십시오.</a>. |
|||
* `frozenset`: |
|||
* 요청과 응답에서 `set`와 동일하게 취급됩니다: |
|||
* 요청 시, 리스트를 읽어 중복을 제거하고 `set`로 변환합니다. |
|||
* 응답 시, `set`는 `list`로 변환됩니다. |
|||
* 생성된 스키마는 (JSON 스키마의 `uniqueItems`를 이용해) `set`의 값이 고유함을 명시합니다. |
|||
* `bytes`: |
|||
* 표준 파이썬의 `bytes`. |
|||
* 요청과 응답에서 `str`로 취급됩니다. |
|||
* 생성된 스키마는 이것이 `binary` "형식"의 `str`임을 명시합니다. |
|||
* `Decimal`: |
|||
* 표준 파이썬의 `Decimal`. |
|||
* 요청과 응답에서 `float`와 동일하게 다뤄집니다. |
|||
* 여기에서 모든 유효한 pydantic 데이터 자료형을 확인할 수 있습니다: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic 데이터 자료형</a>. |
|||
|
|||
## 예시 |
|||
|
|||
위의 몇몇 자료형을 매개변수로 사용하는 *경로 작동* 예시입니다. |
|||
|
|||
=== "Python 3.10+" |
|||
|
|||
```Python hl_lines="1 3 12-16" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="1 3 12-16" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="1 3 13-17" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.10+ non-Annotated" |
|||
|
|||
!!! tip |
|||
Prefer to use the `Annotated` version if possible. |
|||
|
|||
```Python hl_lines="1 2 11-15" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip |
|||
Prefer to use the `Annotated` version if possible. |
|||
|
|||
```Python hl_lines="1 2 12-16" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001.py!} |
|||
``` |
|||
|
|||
함수 안의 매개변수가 그들만의 데이터 자료형을 가지고 있으며, 예를 들어, 다음과 같이 날짜를 조작할 수 있음을 참고하십시오: |
|||
|
|||
=== "Python 3.10+" |
|||
|
|||
```Python hl_lines="18-19" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="18-19" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="19-20" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.10+ non-Annotated" |
|||
|
|||
!!! tip |
|||
Prefer to use the `Annotated` version if possible. |
|||
|
|||
```Python hl_lines="17-18" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip |
|||
Prefer to use the `Annotated` version if possible. |
|||
|
|||
```Python hl_lines="18-19" |
|||
{!> ../../../docs_src/extra_data_types/tutorial001.py!} |
|||
``` |
@ -0,0 +1,178 @@ |
|||
# Ludzie FastAPI |
|||
|
|||
FastAPI posiada wspaniałą społeczność, która jest otwarta dla ludzi z każdego środowiska. |
|||
|
|||
## Twórca - Opienik |
|||
|
|||
Cześć! 👋 |
|||
|
|||
To ja: |
|||
|
|||
{% if people %} |
|||
<div class="user-list user-list-center"> |
|||
{% for user in people.maintainers %} |
|||
|
|||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Liczba odpowiedzi: {{ user.answers }}</div><div class="count">Pull Requesty: {{ user.prs }}</div></div> |
|||
{% endfor %} |
|||
|
|||
</div> |
|||
{% endif %} |
|||
|
|||
Jestem twórcą i opiekunem **FastAPI**. Możesz przeczytać więcej na ten temat w [Pomoc FastAPI - Uzyskaj pomoc - Skontaktuj się z autorem](help-fastapi.md#connect-with-the-author){.internal-link target=_blank}. |
|||
|
|||
...Ale tutaj chcę pokazać Ci społeczność. |
|||
|
|||
--- |
|||
|
|||
**FastAPI** otrzymuje wiele wsparcia od społeczności. Chciałbym podkreślić ich wkład. |
|||
|
|||
To są ludzie, którzy: |
|||
|
|||
* [Pomagają innym z pytaniami na GitHub](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank}. |
|||
* [Tworzą Pull Requesty](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}. |
|||
* Oceniają Pull Requesty, [to szczególnie ważne dla tłumaczeń](contributing.md#translations){.internal-link target=_blank}. |
|||
|
|||
Proszę o brawa dla nich. 👏 🙇 |
|||
|
|||
## Najaktywniejsi użytkownicy w zeszłym miesiącu |
|||
|
|||
Oto niektórzy użytkownicy, którzy [pomagali innym w największej liczbie pytań na GitHubie](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank} podczas ostatniego miesiąca. ☕ |
|||
|
|||
{% if people %} |
|||
<div class="user-list user-list-center"> |
|||
{% for user in people.last_month_active %} |
|||
|
|||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Udzielonych odpowiedzi: {{ user.count }}</div></div> |
|||
{% endfor %} |
|||
|
|||
</div> |
|||
{% endif %} |
|||
|
|||
## Eksperci |
|||
|
|||
Oto **eksperci FastAPI**. 🤓 |
|||
|
|||
To użytkownicy, którzy [pomogli innym z największa liczbą pytań na GitHubie](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank} od *samego początku*. |
|||
|
|||
Poprzez pomoc wielu innym, udowodnili, że są ekspertami. ✨ |
|||
|
|||
{% if people %} |
|||
<div class="user-list user-list-center"> |
|||
{% for user in people.experts %} |
|||
|
|||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Udzielonych odpowiedzi: {{ user.count }}</div></div> |
|||
{% endfor %} |
|||
|
|||
</div> |
|||
{% endif %} |
|||
|
|||
## Najlepsi Kontrybutorzy |
|||
|
|||
Oto **Najlepsi Kontrybutorzy**. 👷 |
|||
|
|||
Ci użytkownicy [stworzyli najwięcej Pull Requestów](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}, które zostały *wcalone*. |
|||
|
|||
Współtworzyli kod źródłowy, dokumentację, tłumaczenia itp. 📦 |
|||
|
|||
{% if people %} |
|||
<div class="user-list user-list-center"> |
|||
{% for user in people.top_contributors %} |
|||
|
|||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Pull Requesty: {{ user.count }}</div></div> |
|||
{% endfor %} |
|||
|
|||
</div> |
|||
{% endif %} |
|||
|
|||
Jest wielu więcej kontrybutorów (ponad setka), możesz zobaczyć ich wszystkich na stronie <a href="https://github.com/tiangolo/fastapi/graphs/contributors" class="external-link" target="_blank">Kontrybutorzy FastAPI na GitHub</a>. 👷 |
|||
|
|||
## Najlepsi Oceniajacy |
|||
|
|||
Ci uzytkownicy są **Najlepszymi oceniającymi**. 🕵️ |
|||
|
|||
### Oceny Tłumaczeń |
|||
|
|||
Ja mówię tylko kilkoma językami (i to niezbyt dobrze 😅). Zatem oceniający są tymi, którzy mają [**moc zatwierdzania tłumaczeń**](contributing.md#translations){.internal-link target=_blank} dokumentacji. Bez nich nie byłoby dokumentacji w kilku innych językach. |
|||
|
|||
--- |
|||
|
|||
**Najlepsi Oceniający** 🕵️ przejrzeli więcej Pull Requestów, niż inni, zapewniając jakość kodu, dokumentacji, a zwłaszcza **tłumaczeń**. |
|||
|
|||
{% if people %} |
|||
<div class="user-list user-list-center"> |
|||
{% for user in people.top_reviewers %} |
|||
|
|||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Liczba ocen: {{ user.count }}</div></div> |
|||
{% endfor %} |
|||
|
|||
</div> |
|||
{% endif %} |
|||
|
|||
## Sponsorzy |
|||
|
|||
Oto **Sponsorzy**. 😎 |
|||
|
|||
Wspierają moją pracę nad **FastAPI** (i innymi), głównie poprzez <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub Sponsors</a>. |
|||
|
|||
{% if sponsors %} |
|||
|
|||
{% if sponsors.gold %} |
|||
|
|||
### Złoci Sponsorzy |
|||
|
|||
{% for sponsor in sponsors.gold -%} |
|||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a> |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
{% if sponsors.silver %} |
|||
|
|||
### Srebrni Sponsorzy |
|||
|
|||
{% for sponsor in sponsors.silver -%} |
|||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a> |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
{% if sponsors.bronze %} |
|||
|
|||
### Brązowi Sponsorzy |
|||
|
|||
{% for sponsor in sponsors.bronze -%} |
|||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a> |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
{% endif %} |
|||
|
|||
### Indywidualni Sponsorzy |
|||
|
|||
{% if github_sponsors %} |
|||
{% for group in github_sponsors.sponsors %} |
|||
|
|||
<div class="user-list user-list-center"> |
|||
|
|||
{% for user in group %} |
|||
{% if user.login not in sponsors_badge.logins %} |
|||
|
|||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div> |
|||
|
|||
{% endif %} |
|||
{% endfor %} |
|||
|
|||
</div> |
|||
|
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
## Techniczne szczegóły danych |
|||
|
|||
Głównym celem tej strony jest podkreślenie wysiłku społeczności w pomaganiu innym. |
|||
|
|||
Szczególnie włączając wysiłki, które są zwykle mniej widoczne, a w wielu przypadkach bardziej żmudne, tak jak pomaganie innym z pytaniami i ocenianie Pull Requestów z tłumaczeniami. |
|||
|
|||
Dane są obliczane każdego miesiąca, możesz przeczytać <a href="https://github.com/tiangolo/fastapi/blob/master/.github/actions/people/app/main.py" class="external-link" target="_blank">kod źródłowy tutaj</a>. |
|||
|
|||
Tutaj również podkreślam wkład od sponsorów. |
|||
|
|||
Zastrzegam sobie prawo do aktualizacji algorytmu, sekcji, progów itp. (na wszelki wypadek 🤷). |
@ -0,0 +1,240 @@ |
|||
# Retornos Adicionais no OpenAPI |
|||
|
|||
!!! warning "Aviso" |
|||
Este é um tema bem avançado. |
|||
|
|||
Se você está começando com o **FastAPI**, provavelmente você não precisa disso. |
|||
|
|||
Você pode declarar retornos adicionais, com códigos de status adicionais, media types, descrições, etc. |
|||
|
|||
Essas respostas adicionais serão incluídas no esquema do OpenAPI, e também aparecerão na documentação da API. |
|||
|
|||
Porém para as respostas adicionais, você deve garantir que está retornando um `Response` como por exemplo o `JSONResponse` diretamente, junto com o código de status e o conteúdo. |
|||
|
|||
## Retorno Adicional com `model` |
|||
|
|||
Você pode fornecer o parâmetro `responses` aos seus *decoradores de caminho*. |
|||
|
|||
Este parâmetro recebe um `dict`, as chaves são os códigos de status para cada retorno, como por exemplo `200`, e os valores são um outro `dict` com a informação de cada um deles. |
|||
|
|||
Cada um desses `dict` de retorno pode ter uma chave `model`, contendo um modelo do Pydantic, assim como o `response_model`. |
|||
|
|||
O **FastAPI** pegará este modelo, gerará o esquema JSON dele e incluirá no local correto do OpenAPI. |
|||
|
|||
Por exemplo, para declarar um outro retorno com o status code `404` e um modelo do Pydantic chamado `Message`, você pode escrever: |
|||
|
|||
```Python hl_lines="18 22" |
|||
{!../../../docs_src/additional_responses/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! note "Nota" |
|||
Lembre-se que você deve retornar o `JSONResponse` diretamente. |
|||
|
|||
!!! info "Informação" |
|||
A chave `model` não é parte do OpenAPI. |
|||
|
|||
O **FastAPI** pegará o modelo do Pydantic, gerará o `JSON Schema`, e adicionará no local correto. |
|||
|
|||
O local correto é: |
|||
|
|||
* Na chave `content`, que tem como valor um outro objeto JSON (`dict`) que contém: |
|||
* Uma chave com o media type, como por exemplo `application/json`, que contém como valor um outro objeto JSON, contendo:: |
|||
* Uma chave `schema`, que contém como valor o JSON Schema do modelo, sendo este o local correto. |
|||
* O **FastAPI** adiciona aqui a referência dos esquemas JSON globais que estão localizados em outro lugar, ao invés de incluí-lo diretamente. Deste modo, outras aplicações e clientes podem utilizar estes esquemas JSON diretamente, fornecer melhores ferramentas de geração de código, etc. |
|||
|
|||
O retorno gerado no OpenAI para esta *operação de caminho* será: |
|||
|
|||
```JSON hl_lines="3-12" |
|||
{ |
|||
"responses": { |
|||
"404": { |
|||
"description": "Additional Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/Message" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/Item" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"422": { |
|||
"description": "Validation Error", |
|||
"content": { |
|||
"application/json": { |
|||
"schema": { |
|||
"$ref": "#/components/schemas/HTTPValidationError" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Os esquemas são referenciados em outro local dentro do esquema OpenAPI: |
|||
|
|||
```JSON hl_lines="4-16" |
|||
{ |
|||
"components": { |
|||
"schemas": { |
|||
"Message": { |
|||
"title": "Message", |
|||
"required": [ |
|||
"message" |
|||
], |
|||
"type": "object", |
|||
"properties": { |
|||
"message": { |
|||
"title": "Message", |
|||
"type": "string" |
|||
} |
|||
} |
|||
}, |
|||
"Item": { |
|||
"title": "Item", |
|||
"required": [ |
|||
"id", |
|||
"value" |
|||
], |
|||
"type": "object", |
|||
"properties": { |
|||
"id": { |
|||
"title": "Id", |
|||
"type": "string" |
|||
}, |
|||
"value": { |
|||
"title": "Value", |
|||
"type": "string" |
|||
} |
|||
} |
|||
}, |
|||
"ValidationError": { |
|||
"title": "ValidationError", |
|||
"required": [ |
|||
"loc", |
|||
"msg", |
|||
"type" |
|||
], |
|||
"type": "object", |
|||
"properties": { |
|||
"loc": { |
|||
"title": "Location", |
|||
"type": "array", |
|||
"items": { |
|||
"type": "string" |
|||
} |
|||
}, |
|||
"msg": { |
|||
"title": "Message", |
|||
"type": "string" |
|||
}, |
|||
"type": { |
|||
"title": "Error Type", |
|||
"type": "string" |
|||
} |
|||
} |
|||
}, |
|||
"HTTPValidationError": { |
|||
"title": "HTTPValidationError", |
|||
"type": "object", |
|||
"properties": { |
|||
"detail": { |
|||
"title": "Detail", |
|||
"type": "array", |
|||
"items": { |
|||
"$ref": "#/components/schemas/ValidationError" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Media types adicionais para o retorno principal |
|||
|
|||
Você pode utilizar o mesmo parâmetro `responses` para adicionar diferentes media types para o mesmo retorno principal. |
|||
|
|||
Por exemplo, você pode adicionar um media type adicional de `image/png`, declarando que a sua *operação de caminho* pode retornar um objeto JSON (com o media type `application/json`) ou uma imagem PNG: |
|||
|
|||
```Python hl_lines="19-24 28" |
|||
{!../../../docs_src/additional_responses/tutorial002.py!} |
|||
``` |
|||
|
|||
!!! note "Nota" |
|||
Note que você deve retornar a imagem utilizando um `FileResponse` diretamente. |
|||
|
|||
!!! info "Informação" |
|||
A menos que você especifique um media type diferente explicitamente em seu parâmetro `responses`, o FastAPI assumirá que o retorno possui o mesmo media type contido na classe principal de retorno (padrão `application/json`). |
|||
|
|||
Porém se você especificou uma classe de retorno com o valor `None` como media type, o FastAPI utilizará `application/json` para qualquer retorno adicional que possui um modelo associado. |
|||
|
|||
## Combinando informações |
|||
|
|||
Você também pode combinar informações de diferentes lugares, incluindo os parâmetros `response_model`, `status_code`, e `responses`. |
|||
|
|||
Você pode declarar um `response_model`, utilizando o código de status padrão `200` (ou um customizado caso você precise), e depois adicionar informações adicionais para esse mesmo retorno em `responses`, diretamente no esquema OpenAPI. |
|||
|
|||
O **FastAPI** manterá as informações adicionais do `responses`, e combinará com o esquema JSON do seu modelo. |
|||
|
|||
Por exemplo, você pode declarar um retorno com o código de status `404` que utiliza um modelo do Pydantic que possui um `description` customizado. |
|||
|
|||
E um retorno com o código de status `200` que utiliza o seu `response_model`, porém inclui um `example` customizado: |
|||
|
|||
```Python hl_lines="20-31" |
|||
{!../../../docs_src/additional_responses/tutorial003.py!} |
|||
``` |
|||
|
|||
Isso será combinado e incluído em seu OpenAPI, e disponibilizado na documentação da sua API: |
|||
|
|||
<img src="/img/tutorial/additional-responses/image01.png"> |
|||
|
|||
## Combinar retornos predefinidos e personalizados |
|||
|
|||
Você pode querer possuir alguns retornos predefinidos que são aplicados para diversas *operações de caminho*, porém você deseja combinar com retornos personalizados que são necessários para cada *operação de caminho*. |
|||
|
|||
Para estes casos, você pode utilizar a técnica do Python de "desempacotamento" de um `dict` utilizando `**dict_to_unpack`: |
|||
|
|||
```Python |
|||
old_dict = { |
|||
"old key": "old value", |
|||
"second old key": "second old value", |
|||
} |
|||
new_dict = {**old_dict, "new key": "new value"} |
|||
``` |
|||
|
|||
Aqui, o `new_dict` terá todos os pares de chave-valor do `old_dict` mais o novo par de chave-valor: |
|||
|
|||
```Python |
|||
{ |
|||
"old key": "old value", |
|||
"second old key": "second old value", |
|||
"new key": "new value", |
|||
} |
|||
``` |
|||
|
|||
Você pode utilizar essa técnica para reutilizar alguns retornos predefinidos nas suas *operações de caminho* e combiná-las com personalizações adicionais. |
|||
|
|||
Por exemplo: |
|||
|
|||
```Python hl_lines="13-17 26" |
|||
{!../../../docs_src/additional_responses/tutorial004.py!} |
|||
``` |
|||
|
|||
## Mais informações sobre retornos OpenAPI |
|||
|
|||
Para verificar exatamente o que você pode incluir nos retornos, você pode conferir estas seções na especificação do OpenAPI: |
|||
|
|||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, inclui o `Response Object`. |
|||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responseObject" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que você declara diferentes media types e esquemas JSON), e `links`. |
@ -0,0 +1,69 @@ |
|||
# Códigos de status adicionais |
|||
|
|||
Por padrão, o **FastAPI** retornará as respostas utilizando o `JSONResponse`, adicionando o conteúdo do retorno da sua *operação de caminho* dentro do `JSONResponse`. |
|||
|
|||
Ele usará o código de status padrão ou o que você definir na sua *operação de caminho*. |
|||
|
|||
## Códigos de status adicionais |
|||
|
|||
Caso você queira retornar códigos de status adicionais além do código principal, você pode fazer isso retornando um `Response` diretamente, como por exemplo um `JSONResponse`, e definir os códigos de status adicionais diretamente. |
|||
|
|||
Por exemplo, vamos dizer que você deseja ter uma *operação de caminho* que permita atualizar itens, e retornar um código de status HTTP 200 "OK" quando for bem sucedido. |
|||
|
|||
Mas você também deseja aceitar novos itens. E quando os itens não existiam, ele os cria, e retorna o código de status HTTP 201 "Created. |
|||
|
|||
Para conseguir isso, importe `JSONResponse` e retorne o seu conteúdo diretamente, definindo o `status_code` que você deseja: |
|||
|
|||
=== "Python 3.10+" |
|||
|
|||
```Python hl_lines="4 25" |
|||
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="4 25" |
|||
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="4 26" |
|||
{!> ../../../docs_src/additional_status_codes/tutorial001_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.10+ non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Faça uso da versão `Annotated` quando possível. |
|||
|
|||
```Python hl_lines="2 23" |
|||
{!> ../../../docs_src/additional_status_codes/tutorial001_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Faça uso da versão `Annotated` quando possível. |
|||
|
|||
```Python hl_lines="4 25" |
|||
{!> ../../../docs_src/additional_status_codes/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! warning "Aviso" |
|||
Quando você retorna um `Response` diretamente, como no exemplo acima, ele será retornado diretamente. |
|||
|
|||
Ele não será serializado com um modelo, etc. |
|||
|
|||
Garanta que ele tenha toda informação que você deseja, e que os valores sejam um JSON válido (caso você esteja usando `JSONResponse`). |
|||
|
|||
!!! note "Detalhes técnicos" |
|||
Você também pode utilizar `from starlette.responses import JSONResponse`. |
|||
|
|||
O **FastAPI** disponibiliza o `starlette.responses` como `fastapi.responses` apenas por conveniência para você, o programador. Porém a maioria dos retornos disponíveis vem diretamente do Starlette. O mesmo com `status`. |
|||
|
|||
## OpenAPI e documentação da API |
|||
|
|||
Se você retorna códigos de status adicionais e retornos diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado. |
|||
|
|||
Mas você pode documentar isso no seu código, utilizando: [Retornos Adicionais](additional-responses.md){.internal-link target=_blank}. |
@ -0,0 +1,138 @@ |
|||
# Dependências avançadas |
|||
|
|||
## Dependências parametrizadas |
|||
|
|||
Todas as dependências que vimos até agora são funções ou classes fixas. |
|||
|
|||
Mas podem ocorrer casos onde você deseja ser capaz de definir parâmetros na dependência, sem ter a necessidade de declarar diversas funções ou classes. |
|||
|
|||
Vamos imaginar que queremos ter uma dependência que verifica se o parâmetro de consulta `q` possui um valor fixo. |
|||
|
|||
Porém nós queremos poder parametrizar o conteúdo fixo. |
|||
|
|||
## Uma instância "chamável" |
|||
|
|||
Em Python existe uma maneira de fazer com que uma instância de uma classe seja um "chamável". |
|||
|
|||
Não propriamente a classe (que já é um chamável), mas a instância desta classe. |
|||
|
|||
Para fazer isso, nós declaramos o método `__call__`: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="12" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="11" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Prefira utilizar a versão `Annotated` se possível. |
|||
|
|||
```Python hl_lines="10" |
|||
{!> ../../../docs_src/dependencies/tutorial011.py!} |
|||
``` |
|||
|
|||
Neste caso, o `__call__` é o que o **FastAPI** utilizará para verificar parâmetros adicionais e sub dependências, e isso é o que será chamado para passar o valor ao parâmetro na sua *função de operação de rota* posteriormente. |
|||
|
|||
## Parametrizar a instância |
|||
|
|||
E agora, nós podemos utilizar o `__init__` para declarar os parâmetros da instância que podemos utilizar para "parametrizar" a dependência: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="9" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="8" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Prefira utilizar a versão `Annotated` se possível. |
|||
|
|||
```Python hl_lines="7" |
|||
{!> ../../../docs_src/dependencies/tutorial011.py!} |
|||
``` |
|||
|
|||
Neste caso, o **FastAPI** nunca tocará ou se importará com o `__init__`, nós vamos utilizar diretamente em nosso código. |
|||
|
|||
## Crie uma instância |
|||
|
|||
Nós poderíamos criar uma instância desta classe com: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="18" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="17" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Prefira utilizar a versão `Annotated` se possível. |
|||
|
|||
```Python hl_lines="16" |
|||
{!> ../../../docs_src/dependencies/tutorial011.py!} |
|||
``` |
|||
|
|||
E deste modo nós podemos "parametrizar" a nossa dependência, que agora possui `"bar"` dentro dele, como o atributo `checker.fixed_content`. |
|||
|
|||
## Utilize a instância como dependência |
|||
|
|||
Então, nós podemos utilizar este `checker` em um `Depends(checker)`, no lugar de `Depends(FixedContentQueryChecker)`, porque a dependência é a instância, `checker`, e não a própria classe. |
|||
|
|||
E quando a dependência for resolvida, o **FastAPI** chamará este `checker` como: |
|||
|
|||
```Python |
|||
checker(q="somequery") |
|||
``` |
|||
|
|||
...e passar o que quer que isso retorne como valor da dependência em nossa *função de operação de rota* como o parâmetro `fixed_content_included`: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="22" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="21" |
|||
{!> ../../../docs_src/dependencies/tutorial011_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Prefira utilizar a versão `Annotated` se possível. |
|||
|
|||
```Python hl_lines="20" |
|||
{!> ../../../docs_src/dependencies/tutorial011.py!} |
|||
``` |
|||
|
|||
!!! tip "Dica" |
|||
Tudo isso parece não ser natural. E pode não estar muito claro ou aparentar ser útil ainda. |
|||
|
|||
Estes exemplos são intencionalmente simples, porém mostram como tudo funciona. |
|||
|
|||
Nos capítulos sobre segurança, existem funções utilitárias que são implementadas desta maneira. |
|||
|
|||
Se você entendeu tudo isso, você já sabe como essas funções utilitárias para segurança funcionam por debaixo dos panos. |
@ -0,0 +1,95 @@ |
|||
# Testes Assíncronos |
|||
|
|||
Você já viu como testar as suas aplicações **FastAPI** utilizando o `TestClient` que é fornecido. Até agora, você viu apenas como escrever testes síncronos, sem utilizar funções `async`. |
|||
|
|||
Ser capaz de utilizar funções assíncronas em seus testes pode ser útil, por exemplo, quando você está realizando uma consulta em seu banco de dados de maneira assíncrona. Imagine que você deseja testar realizando requisições para a sua aplicação FastAPI e depois verificar que a sua aplicação inseriu corretamente as informações no banco de dados, ao utilizar uma biblioteca assíncrona para banco de dados. |
|||
|
|||
Vamos ver como nós podemos fazer isso funcionar. |
|||
|
|||
## pytest.mark.anyio |
|||
|
|||
Se quisermos chamar funções assíncronas em nossos testes, as nossas funções de teste precisam ser assíncronas. O AnyIO oferece um plugin bem legal para isso, que nos permite especificar que algumas das nossas funções de teste precisam ser chamadas de forma assíncrona. |
|||
|
|||
## HTTPX |
|||
|
|||
Mesmo que a sua aplicação **FastAPI** utilize funções normais com `def` no lugar de `async def`, ela ainda é uma aplicação `async` por baixo dos panos. |
|||
|
|||
O `TestClient` faz algumas mágicas para invocar a aplicação FastAPI assíncrona em suas funções `def` normais, utilizando o pytest padrão. Porém a mágica não acontece mais quando nós estamos utilizando dentro de funções assíncronas. Ao executar os nossos testes de forma assíncrona, nós não podemos mais utilizar o `TestClient` dentro das nossas funções de teste. |
|||
|
|||
O `TestClient` é baseado no <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, e felizmente nós podemos utilizá-lo diretamente para testar a API. |
|||
|
|||
## Exemplo |
|||
|
|||
Para um exemplos simples, vamos considerar uma estrutura de arquivos semelhante ao descrito em [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} e [Testing](../tutorial/testing.md){.internal-link target=_blank}: |
|||
|
|||
``` |
|||
. |
|||
├── app |
|||
│ ├── __init__.py |
|||
│ ├── main.py |
|||
│ └── test_main.py |
|||
``` |
|||
|
|||
O arquivo `main.py` teria: |
|||
|
|||
```Python |
|||
{!../../../docs_src/async_tests/main.py!} |
|||
``` |
|||
|
|||
O arquivo `test_main.py` teria os testes para para o arquivo `main.py`, ele poderia ficar assim: |
|||
|
|||
```Python |
|||
{!../../../docs_src/async_tests/test_main.py!} |
|||
``` |
|||
|
|||
## Executá-lo |
|||
|
|||
Você pode executar os seus testes normalmente via: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pytest |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
## Em Detalhes |
|||
|
|||
O marcador `@pytest.mark.anyio` informa ao pytest que esta função de teste deve ser invocada de maneira assíncrona: |
|||
|
|||
```Python hl_lines="7" |
|||
{!../../../docs_src/async_tests/test_main.py!} |
|||
``` |
|||
|
|||
!!! tip "Dica" |
|||
Note que a função de teste é `async def` agora, no lugar de apenas `def` como quando estávamos utilizando o `TestClient` anteriormente. |
|||
|
|||
Então podemos criar um `AsyncClient` com a aplicação, e enviar requisições assíncronas para ela utilizando `await`. |
|||
|
|||
```Python hl_lines="9-10" |
|||
{!../../../docs_src/async_tests/test_main.py!} |
|||
``` |
|||
|
|||
Isso é equivalente a: |
|||
|
|||
```Python |
|||
response = client.get('/') |
|||
``` |
|||
|
|||
...que nós utilizamos para fazer as nossas requisições utilizando o `TestClient`. |
|||
|
|||
!!! tip "Dica" |
|||
Note que nós estamos utilizando async/await com o novo `AsyncClient` - a requisição é assíncrona. |
|||
|
|||
!!! warning "Aviso" |
|||
Se a sua aplicação depende dos eventos de vida útil (*lifespan*), o `AsyncClient` não acionará estes eventos. Para garantir que eles são acionados, utilize o `LifespanManager` do <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>. |
|||
|
|||
## Outras Chamadas de Funções Assíncronas |
|||
|
|||
Como a função de teste agora é assíncrona, você pode chamar (e `esperar`) outras funções `async` além de enviar requisições para a sua aplicação FastAPI em seus testes, exatamente como você as chamaria em qualquer outro lugar do seu código. |
|||
|
|||
!!! tip "Dica" |
|||
Se você se deparar com um `RuntimeError: Task attached to a different loop` ao integrar funções assíncronas em seus testes (e.g. ao utilizar o <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MotorClient do MongoDB</a>) Lembre-se de instanciar objetos que precisam de um loop de eventos (*event loop*) apenas em funções assíncronas, e.g. um *"callback"* `'@app.on_event("startup")`. |
@ -0,0 +1,34 @@ |
|||
# Benchmarks |
|||
|
|||
Benchmarks independentes da TechEmpower mostram que aplicações **FastAPI** rodando com o 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>, ficando atrás apenas do Starlette e Uvicorn (utilizado internamente pelo FastAPI). |
|||
|
|||
Porém, ao verificar benchmarks e comparações você deve prestar atenção ao seguinte: |
|||
|
|||
## Benchmarks e velocidade |
|||
|
|||
Quando você verifica os benchmarks, é comum ver diversas ferramentas de diferentes tipos comparados como se fossem equivalentes. |
|||
|
|||
Especificamente, para ver o Uvicorn, Starlette e FastAPI comparados entre si (entre diversas outras ferramentas). |
|||
|
|||
Quanto mais simples o problema resolvido pela ferramenta, melhor será a performance. E a maioria das análises não testa funcionalidades adicionais que são oferecidas pela ferramenta. |
|||
|
|||
A hierarquia é: |
|||
|
|||
* **Uvicorn**: um servidor ASGI |
|||
* **Starlette**: (utiliza Uvicorn) um microframework web |
|||
* **FastAPI**: (utiliza Starlette) um microframework para APIs com diversas funcionalidades adicionais para a construção de APIs, com validação de dados, etc. |
|||
|
|||
* **Uvicorn**: |
|||
* Terá a melhor performance, pois não possui muito código além do próprio servidor. |
|||
* Você não escreveria uma aplicação utilizando o Uvicorn diretamente. Isso significaria que o seu código teria que incluir pelo menos todo o código fornecido pelo Starlette (ou o **FastAPI**). E caso você fizesse isso, a sua aplicação final teria a mesma sobrecarga que teria se utilizasse um framework, minimizando o código e os bugs. |
|||
* Se você está comparando o Uvicorn, compare com os servidores de aplicação Daphne, Hypercorn, uWSGI, etc. |
|||
* **Starlette**: |
|||
* Terá o melhor desempenho, depois do Uvicorn. Na verdade, o Starlette utiliza o Uvicorn para rodar. Portanto, ele pode ficar mais "devagar" que o Uvicorn apenas por ter que executar mais código. |
|||
* Mas ele fornece as ferramentas para construir aplicações web simples, com roteamento baseado em caminhos, etc. |
|||
* Se você está comparando o Starlette, compare-o com o Sanic, Flask, Django, etc. Frameworks web (ou microframeworks). |
|||
* **FastAPI**: |
|||
* Da mesma forma que o Starlette utiliza o Uvicorn e não consegue ser mais rápido que ele, o **FastAPI** utiliza o Starlette, portanto, ele não consegue ser mais rápido que ele. |
|||
* O FastAPI provê mais funcionalidades em cima do Starlette. Funcionalidades que você quase sempre precisará quando estiver construindo APIs, como validação de dados e serialização. E ao utilizá-lo, você obtém documentação automática sem custo nenhum (a documentação automática sequer adiciona sobrecarga nas aplicações rodando, pois ela é gerada na inicialização). |
|||
* Caso você não utilize o FastAPI e faz uso do Starlette diretamente (ou outra ferramenta, como o Sanic, Flask, Responder, etc) você mesmo teria que implementar toda a validação de dados e serialização. Então, a sua aplicação final ainda teria a mesma sobrecarga caso estivesse usando o FastAPI. E em muitos casos, validação de dados e serialização é a maior parte do código escrito em aplicações. |
|||
* Então, ao utilizar o FastAPI, você está economizando tempo de programação, evitando bugs, linhas de código, e provavelmente terá a mesma performance (ou até melhor) do que teria caso você não o utilizasse (já que você teria que implementar tudo no seu código). |
|||
* Se você está comparando o FastAPI, compare-o com frameworks de aplicações web (ou conjunto de ferramentas) que oferecem validação de dados, serialização e documentação, como por exemplo o Flask-apispec, NestJS, Molten, etc. Frameworks que possuem validação integrada de dados, serialização e documentação. |
@ -0,0 +1,51 @@ |
|||
# Webhooks OpenAPI |
|||
|
|||
Existem situações onde você deseja informar os **usuários** da sua API que a sua aplicação pode chamar a aplicação *deles* (enviando uma requisição) com alguns dados, normalmente para **notificar** algum tipo de **evento**. |
|||
|
|||
Isso significa que no lugar do processo normal de seus usuários enviarem requisições para a sua API, é a **sua API** (ou sua aplicação) que poderia **enviar requisições para o sistema deles** (para a API deles, a aplicação deles). |
|||
|
|||
Isso normalmente é chamado de **webhook**. |
|||
|
|||
## Etapas dos Webhooks |
|||
|
|||
Normalmente, o processo é que **você define** em seu código qual é a mensagem que você irá mandar, o **corpo da sua requisição**. |
|||
|
|||
Você também define de alguma maneira em quais **momentos** a sua aplicação mandará essas requisições ou eventos. |
|||
|
|||
E os **seus usuários** definem de alguma forma (em algum painel por exemplo) a **URL** que a sua aplicação deve enviar essas requisições. |
|||
|
|||
Toda a **lógica** sobre como cadastrar as URLs para os webhooks e o código para enviar de fato as requisições cabe a você definir. Você escreve da maneira que você desejar no **seu próprio código**. |
|||
|
|||
## Documentando webhooks com o FastAPI e OpenAPI |
|||
|
|||
Com o **FastAPI**, utilizando o OpenAPI, você pode definir os nomes destes webhooks, os tipos das operações HTTP que a sua aplicação pode enviar (e.g. `POST`, `PUT`, etc.) e os **corpos** da requisição que a sua aplicação enviaria. |
|||
|
|||
Isto pode facilitar bastante para os seus usuários **implementarem as APIs deles** para receber as requisições dos seus **webhooks**, eles podem inclusive ser capazes de gerar parte do código da API deles. |
|||
|
|||
!!! info "Informação" |
|||
Webhooks estão disponíveis a partir do OpenAPI 3.1.0, e possui suporte do FastAPI a partir da versão `0.99.0`. |
|||
|
|||
## Uma aplicação com webhooks |
|||
|
|||
Quando você cria uma aplicação com o **FastAPI**, existe um atributo chamado `webhooks`, que você utilizar para defini-los da mesma maneira que você definiria as suas **operações de rotas**, utilizando por exemplo `@app.webhooks.post()`. |
|||
|
|||
```Python hl_lines="9-13 36-53" |
|||
{!../../../docs_src/openapi_webhooks/tutorial001.py!} |
|||
``` |
|||
|
|||
Os webhooks que você define aparecerão no esquema do **OpenAPI** e na **página de documentação** gerada automaticamente. |
|||
|
|||
!!! info "Informação" |
|||
O objeto `app.webhooks` é na verdade apenas um `APIRouter`, o mesmo tipo que você utilizaria ao estruturar a sua aplicação com diversos arquivos. |
|||
|
|||
Note que utilizando webhooks você não está de fato declarando uma **rota** (como `/items/`), o texto que informa é apenas um **identificador** do webhook (o nome do evento), por exemplo em `@app.webhooks.post("new-subscription")`, o nome do webhook é `new-subscription`. |
|||
|
|||
Isto porque espera-se que os **seus usuários** definam o verdadeiro **caminho da URL** onde eles desejam receber a requisição do webhook de algum outra maneira. (e.g. um painel). |
|||
|
|||
### Confira a documentação |
|||
|
|||
Agora você pode iniciar a sua aplicação e ir até <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. |
|||
|
|||
Você verá que a sua documentação possui as *operações de rota* normais e agora também possui alguns **webhooks**: |
|||
|
|||
<img src="/img/tutorial/openapi-webhooks/image01.png"> |
@ -0,0 +1,485 @@ |
|||
# Configurações e Variáveis de Ambiente |
|||
|
|||
Em muitos casos a sua aplicação pode precisar de configurações externas, como chaves secretas, credenciais de banco de dados, credenciais para serviços de email, etc. |
|||
|
|||
A maioria dessas configurações é variável (podem mudar), como URLs de bancos de dados. E muitas delas podem conter dados sensíveis, como tokens secretos. |
|||
|
|||
Por isso é comum prover essas configurações como variáveis de ambiente que são utilizidas pela aplicação. |
|||
|
|||
## Variáveis de Ambiente |
|||
|
|||
!!! dica |
|||
Se você já sabe o que são variáveis de ambiente e como utilizá-las, sinta-se livre para avançar para o próximo tópico. |
|||
|
|||
Uma <a href="https://pt.wikipedia.org/wiki/Variável_de_ambiente" class="external-link" target="_blank">variável de ambiente</a> (abreviada em inglês para "env var") é uma variável definida fora do código Python, no sistema operacional, e pode ser lida pelo seu código Python (ou por outros programas). |
|||
|
|||
Você pode criar e utilizar variáveis de ambiente no terminal, sem precisar utilizar Python: |
|||
|
|||
=== "Linux, macOS, Windows Bash" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
// Você pode criar uma env var MY_NAME usando |
|||
$ export MY_NAME="Wade Wilson" |
|||
|
|||
// E utilizá-la em outros programas, como |
|||
$ echo "Hello $MY_NAME" |
|||
|
|||
Hello Wade Wilson |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
=== "Windows PowerShell" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
// Criando env var MY_NAME |
|||
$ $Env:MY_NAME = "Wade Wilson" |
|||
|
|||
// Usando em outros programas, como |
|||
$ echo "Hello $Env:MY_NAME" |
|||
|
|||
Hello Wade Wilson |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
### Lendo variáveis de ambiente com Python |
|||
|
|||
Você também pode criar variáveis de ambiente fora do Python, no terminal (ou com qualquer outro método), e realizar a leitura delas no Python. |
|||
|
|||
Por exemplo, você pode definir um arquivo `main.py` com o seguinte código: |
|||
|
|||
```Python hl_lines="3" |
|||
import os |
|||
|
|||
name = os.getenv("MY_NAME", "World") |
|||
print(f"Hello {name} from Python") |
|||
``` |
|||
|
|||
!!! dica |
|||
O segundo parâmetro em <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> é o valor padrão para o retorno. |
|||
|
|||
Se nenhum valor for informado, `None` é utilizado por padrão, aqui definimos `"World"` como o valor padrão a ser utilizado. |
|||
|
|||
E depois você pode executar esse arquivo: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
// Aqui ainda não definimos a env var |
|||
$ python main.py |
|||
|
|||
// Por isso obtemos o valor padrão |
|||
|
|||
Hello World from Python |
|||
|
|||
// Mas se definirmos uma variável de ambiente primeiro |
|||
$ export MY_NAME="Wade Wilson" |
|||
|
|||
// E executarmos o programa novamente |
|||
$ python main.py |
|||
|
|||
// Agora ele pode ler a variável de ambiente |
|||
|
|||
Hello Wade Wilson from Python |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
Como variáveis de ambiente podem ser definidas fora do código da aplicação, mas acessadas pela aplicação, e não precisam ser armazenadas (versionadas com `git`) junto dos outros arquivos, é comum utilizá-las para guardar configurações. |
|||
|
|||
Você também pode criar uma variável de ambiente específica para uma invocação de um programa, que é acessível somente para esse programa, e somente enquanto ele estiver executando. |
|||
|
|||
Para fazer isso, crie a variável imediatamente antes de iniciar o programa, na mesma linha: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
// Criando uma env var MY_NAME na mesma linha da execução do programa |
|||
$ MY_NAME="Wade Wilson" python main.py |
|||
|
|||
// Agora a aplicação consegue ler a variável de ambiente |
|||
|
|||
Hello Wade Wilson from Python |
|||
|
|||
// E a variável deixa de existir após isso |
|||
$ python main.py |
|||
|
|||
Hello World from Python |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
!!! dica |
|||
Você pode ler mais sobre isso em: <a href="https://12factor.net/pt_br/config" class="external-link" target="_blank">The Twelve-Factor App: Configurações</a>. |
|||
|
|||
### Tipagem e Validação |
|||
|
|||
Essas variáveis de ambiente suportam apenas strings, por serem externas ao Python e por que precisam ser compatíveis com outros programas e o resto do sistema (e até mesmo com outros sistemas operacionais, como Linux, Windows e macOS). |
|||
|
|||
Isso significa que qualquer valor obtido de uma variável de ambiente em Python terá o tipo `str`, e qualquer conversão para um tipo diferente ou validação deve ser realizada no código. |
|||
|
|||
## Pydantic `Settings` |
|||
|
|||
Por sorte, o Pydantic possui uma funcionalidade para lidar com essas configurações vindas de variáveis de ambiente utilizando <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a>. |
|||
|
|||
### Instalando `pydantic-settings` |
|||
|
|||
Primeiro, instale o pacote `pydantic-settings`: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install pydantic-settings |
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
Ele também está incluído no fastapi quando você instala com a opção `all`: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install "fastapi[all]" |
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
!!! info |
|||
Na v1 do Pydantic ele estava incluído no pacote principal. Agora ele está distribuido como um pacote independente para que você possa optar por instalar ou não caso você não precise dessa funcionalidade. |
|||
|
|||
### Criando o objeto `Settings` |
|||
|
|||
Importe a classe `BaseSettings` do Pydantic e crie uma nova subclasse, de forma parecida com um modelo do Pydantic. |
|||
|
|||
Os atributos da classe são declarados com anotações de tipo, e possíveis valores padrão, da mesma maneira que os modelos do Pydantic. |
|||
|
|||
Você pode utilizar todas as ferramentas e funcionalidades de validação que são utilizadas nos modelos do Pydantic, como tipos de dados diferentes e validações adicionei com `Field()`. |
|||
|
|||
=== "Pydantic v2" |
|||
|
|||
```Python hl_lines="2 5-8 11" |
|||
{!> ../../../docs_src/settings/tutorial001.py!} |
|||
``` |
|||
|
|||
=== "Pydantic v1" |
|||
|
|||
!!! Info |
|||
Na versão 1 do Pydantic você importaria `BaseSettings` diretamente do módulo `pydantic` em vez do módulo `pydantic_settings`. |
|||
|
|||
```Python hl_lines="2 5-8 11" |
|||
{!> ../../../docs_src/settings/tutorial001_pv1.py!} |
|||
``` |
|||
|
|||
!!! dica |
|||
Se você quiser algo pronto para copiar e colar na sua aplicação, não use esse exemplo, mas sim o exemplo abaixo. |
|||
|
|||
Portanto, quando você cria uma instância da classe `Settings` (nesse caso, o objeto `settings`), o Pydantic lê as variáveis de ambiente sem diferenciar maiúsculas e minúsculas, por isso, uma variável maiúscula `APP_NAME` será usada para o atributo `app_name`. |
|||
|
|||
Depois ele irá converter e validar os dados. Assim, quando você utilizar aquele objeto `settings`, os dados terão o tipo que você declarou (e.g. `items_per_user` será do tipo `int`). |
|||
|
|||
### Usando o objeto `settings` |
|||
|
|||
Depois, Você pode utilizar o novo objeto `settings` na sua aplicação: |
|||
|
|||
```Python hl_lines="18-20" |
|||
{!../../../docs_src/settings/tutorial001.py!} |
|||
``` |
|||
|
|||
### Executando o servidor |
|||
|
|||
No próximo passo, você pode inicializar o servidor passando as configurações em forma de variáveis de ambiente, por exemplo, você poderia definir `ADMIN_EMAIL` e `APP_NAME` da seguinte forma: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.py |
|||
|
|||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
!!! dica |
|||
Para definir múltiplas variáveis de ambiente para um único comando basta separá-las utilizando espaços, e incluir todas elas antes do comando. |
|||
|
|||
Assim, o atributo `admin_email` seria definido como `"[email protected]"`. |
|||
|
|||
`app_name` seria `"ChimichangApp"`. |
|||
|
|||
E `items_per_user` manteria o valor padrão de `50`. |
|||
|
|||
## Configurações em um módulo separado |
|||
|
|||
Você também pode incluir essas configurações em um arquivo de um módulo separado como visto em [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=\_blank}. |
|||
|
|||
Por exemplo, você pode adicionar um arquivo `config.py` com: |
|||
|
|||
```Python |
|||
{!../../../docs_src/settings/app01/config.py!} |
|||
``` |
|||
|
|||
E utilizar essa configuração em `main.py`: |
|||
|
|||
```Python hl_lines="3 11-13" |
|||
{!../../../docs_src/settings/app01/main.py!} |
|||
``` |
|||
|
|||
!!! dica |
|||
Você também precisa incluir um arquivo `__init__.py` como visto em [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=\_blank}. |
|||
|
|||
## Configurações em uma dependência |
|||
|
|||
Em certas ocasiões, pode ser útil fornecer essas configurações a partir de uma dependência, em vez de definir um objeto global `settings` que é utilizado em toda a aplicação. |
|||
|
|||
Isso é especialmente útil durante os testes, já que é bastante simples sobrescrever uma dependência com suas configurações personalizadas. |
|||
|
|||
### O arquivo de configuração |
|||
|
|||
Baseando-se no exemplo anterior, seu arquivo `config.py` seria parecido com isso: |
|||
|
|||
```Python hl_lines="10" |
|||
{!../../../docs_src/settings/app02/config.py!} |
|||
``` |
|||
|
|||
Perceba que dessa vez não criamos uma instância padrão `settings = Settings()`. |
|||
|
|||
### O arquivo principal da aplicação |
|||
|
|||
Agora criamos a dependência que retorna um novo objeto `config.Settings()`. |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="6 12-13" |
|||
{!> ../../../docs_src/settings/app02_an_py39/main.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="6 12-13" |
|||
{!> ../../../docs_src/settings/app02_an/main.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! dica |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="5 11-12" |
|||
{!> ../../../docs_src/settings/app02/main.py!} |
|||
``` |
|||
|
|||
!!! dica |
|||
Vamos discutir sobre `@lru_cache` logo mais. |
|||
|
|||
Por enquanto, você pode considerar `get_settings()` como uma função normal. |
|||
|
|||
E então podemos declarar essas configurações como uma dependência na função de operação da rota e utilizar onde for necessário. |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="17 19-21" |
|||
{!> ../../../docs_src/settings/app02_an_py39/main.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="17 19-21" |
|||
{!> ../../../docs_src/settings/app02_an/main.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! dica |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="16 18-20" |
|||
{!> ../../../docs_src/settings/app02/main.py!} |
|||
``` |
|||
|
|||
### Configurações e testes |
|||
|
|||
Então seria muito fácil fornecer uma configuração diferente durante a execução dos testes sobrescrevendo a dependência de `get_settings`: |
|||
|
|||
```Python hl_lines="9-10 13 21" |
|||
{!../../../docs_src/settings/app02/test_main.py!} |
|||
``` |
|||
|
|||
Na sobrescrita da dependência, definimos um novo valor para `admin_email` quando instanciamos um novo objeto `Settings`, e então retornamos esse novo objeto. |
|||
|
|||
Após isso, podemos testar se o valor está sendo utilizado. |
|||
|
|||
## Lendo um arquivo `.env` |
|||
|
|||
Se você tiver muitas configurações que variem bastante, talvez em ambientes distintos, pode ser útil colocá-las em um arquivo e depois lê-las como se fossem variáveis de ambiente. |
|||
|
|||
Essa prática é tão comum que possui um nome, essas variáveis de ambiente normalmente são colocadas em um arquivo `.env`, e esse arquivo é chamado de "dotenv". |
|||
|
|||
!!! dica |
|||
Um arquivo iniciando com um ponto final (`.`) é um arquivo oculto em sistemas baseados em Unix, como Linux e MacOS. |
|||
|
|||
Mas um arquivo dotenv não precisa ter esse nome exato. |
|||
|
|||
Pydantic suporta a leitura desses tipos de arquivos utilizando uma biblioteca externa. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>. |
|||
|
|||
!!! dica |
|||
Para que isso funcione você precisa executar `pip install python-dotenv`. |
|||
|
|||
### O arquivo `.env` |
|||
|
|||
Você pode definir um arquivo `.env` com o seguinte conteúdo: |
|||
|
|||
```bash |
|||
ADMIN_EMAIL="[email protected]" |
|||
APP_NAME="ChimichangApp" |
|||
``` |
|||
|
|||
### Obtendo configurações do `.env` |
|||
|
|||
E então adicionar o seguinte código em `config.py`: |
|||
|
|||
=== "Pydantic v2" |
|||
|
|||
```Python hl_lines="9" |
|||
{!> ../../../docs_src/settings/app03_an/config.py!} |
|||
``` |
|||
|
|||
!!! dica |
|||
O atributo `model_config` é usado apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>. |
|||
|
|||
=== "Pydantic v1" |
|||
|
|||
```Python hl_lines="9-10" |
|||
{!> ../../../docs_src/settings/app03_an/config_pv1.py!} |
|||
``` |
|||
|
|||
!!! dica |
|||
A classe `Config` é usada apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>. |
|||
|
|||
!!! info |
|||
Na versão 1 do Pydantic a configuração é realizada por uma classe interna `Config`, na versão 2 do Pydantic isso é feito com o atributo `model_config`. Esse atributo recebe um `dict`, para utilizar o autocomplete e checagem de erros do seu editor de texto você pode importar e utilizar `SettingsConfigDict` para definir esse `dict`. |
|||
|
|||
Aqui definimos a configuração `env_file` dentro da classe `Settings` do Pydantic, e definimos o valor como o nome do arquivo dotenv que queremos utilizar. |
|||
|
|||
### Declarando `Settings` apenas uma vez com `lru_cache` |
|||
|
|||
Ler o conteúdo de um arquivo em disco normalmente é uma operação custosa (lenta), então você provavelmente quer fazer isso apenas um vez e reutilizar o mesmo objeto settings depois, em vez de ler os valores a cada requisição. |
|||
|
|||
Mas cada vez que fazemos: |
|||
|
|||
```Python |
|||
Settings() |
|||
``` |
|||
|
|||
um novo objeto `Settings` é instanciado, e durante a instanciação, o arquivo `.env` é lido novamente. |
|||
|
|||
Se a função da dependência fosse apenas: |
|||
|
|||
```Python |
|||
def get_settings(): |
|||
return Settings() |
|||
``` |
|||
|
|||
Iriamos criar um novo objeto a cada requisição, e estaríamos lendo o arquivo `.env` a cada requisição. ⚠️ |
|||
|
|||
Mas como estamos utilizando o decorador `@lru_cache` acima, o objeto `Settings` é criado apenas uma vez, na primeira vez que a função é chamada. ✔️ |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="1 11" |
|||
{!> ../../../docs_src/settings/app03_an_py39/main.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="1 11" |
|||
{!> ../../../docs_src/settings/app03_an/main.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! dica |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="1 10" |
|||
{!> ../../../docs_src/settings/app03/main.py!} |
|||
``` |
|||
|
|||
Dessa forma, todas as chamadas da função `get_settings()` nas dependências das próximas requisições, em vez de executar o código interno de `get_settings()` e instanciar um novo objeto `Settings`, irão retornar o mesmo objeto que foi retornado na primeira chamada, de novo e de novo. |
|||
|
|||
#### Detalhes Técnicos de `lru_cache` |
|||
|
|||
`@lru_cache` modifica a função decorada para retornar o mesmo valor que foi retornado na primeira vez, em vez de calculá-lo novamente, executando o código da função toda vez. |
|||
|
|||
Assim, a função abaixo do decorador é executada uma única vez para cada combinação dos argumentos passados. E os valores retornados para cada combinação de argumentos são sempre reutilizados para cada nova chamada da função com a mesma combinação de argumentos. |
|||
|
|||
Por exemplo, se você definir uma função: |
|||
|
|||
```Python |
|||
@lru_cache |
|||
def say_hi(name: str, salutation: str = "Ms."): |
|||
return f"Hello {salutation} {name}" |
|||
``` |
|||
|
|||
Seu programa poderia executar dessa forma: |
|||
|
|||
```mermaid |
|||
sequenceDiagram |
|||
|
|||
participant code as Código |
|||
participant function as say_hi() |
|||
participant execute as Executar Função |
|||
|
|||
rect rgba(0, 255, 0, .1) |
|||
code ->> function: say_hi(name="Camila") |
|||
function ->> execute: executar código da função |
|||
execute ->> code: retornar o resultado |
|||
end |
|||
|
|||
rect rgba(0, 255, 255, .1) |
|||
code ->> function: say_hi(name="Camila") |
|||
function ->> code: retornar resultado armazenado |
|||
end |
|||
|
|||
rect rgba(0, 255, 0, .1) |
|||
code ->> function: say_hi(name="Rick") |
|||
function ->> execute: executar código da função |
|||
execute ->> code: retornar o resultado |
|||
end |
|||
|
|||
rect rgba(0, 255, 0, .1) |
|||
code ->> function: say_hi(name="Rick", salutation="Mr.") |
|||
function ->> execute: executar código da função |
|||
execute ->> code: retornar o resultado |
|||
end |
|||
|
|||
rect rgba(0, 255, 255, .1) |
|||
code ->> function: say_hi(name="Rick") |
|||
function ->> code: retornar resultado armazenado |
|||
end |
|||
|
|||
rect rgba(0, 255, 255, .1) |
|||
code ->> function: say_hi(name="Camila") |
|||
function ->> code: retornar resultado armazenado |
|||
end |
|||
``` |
|||
|
|||
No caso da nossa dependência `get_settings()`, a função não recebe nenhum argumento, então ela sempre retorna o mesmo valor. |
|||
|
|||
Dessa forma, ela se comporta praticamente como uma variável global, mas ao ser utilizada como uma função de uma dependência, pode facilmente ser sobrescrita durante os testes. |
|||
|
|||
`@lru_cache` é definido no módulo `functools` que faz parte da biblioteca padrão do Python, você pode ler mais sobre esse decorador no link <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python Docs sobre `@lru_cache`</a>. |
|||
|
|||
## Recapitulando |
|||
|
|||
Você pode usar o módulo Pydantic Settings para gerenciar as configurações de sua aplicação, utilizando todo o poder dos modelos Pydantic. |
|||
|
|||
- Utilizar dependências simplifica os testes. |
|||
- Você pode utilizar arquivos .env junto das configurações do Pydantic. |
|||
- Utilizar o decorador `@lru_cache` evita que o arquivo .env seja lido de novo e de novo para cada requisição, enquanto permite que você sobrescreva durante os testes. |
@ -0,0 +1,84 @@ |
|||
# FastAPI CLI |
|||
|
|||
**FastAPI CLI** é uma interface por linha de comando do `fastapi` que você pode usar para rodar sua app FastAPI, gerenciar seu projeto FastAPI e mais. |
|||
|
|||
Quando você instala o FastAPI (ex.: com `pip install fastapi`), isso inclui um pacote chamado `fastapi-cli`. Esse pacote disponibiliza o comando `fastapi` no terminal. |
|||
|
|||
Para rodar seu app FastAPI em desenvolvimento, você pode usar o comando `fastapi dev`: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u> |
|||
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font> |
|||
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font> |
|||
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files |
|||
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font> |
|||
|
|||
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮ |
|||
│ │ |
|||
│ 🐍 main.py │ |
|||
│ │ |
|||
╰──────────────────────╯ |
|||
|
|||
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font> |
|||
<font color="#3465A4">INFO </font> Found importable FastAPI app |
|||
|
|||
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮ |
|||
│ │ |
|||
│ <span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span> │ |
|||
│ │ |
|||
╰──────────────────────────╯ |
|||
|
|||
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font> |
|||
|
|||
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ </font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"> │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span> |
|||
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span> |
|||
|
|||
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] |
|||
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit) |
|||
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font> |
|||
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>] |
|||
<font color="#4E9A06">INFO</font>: Waiting for application startup. |
|||
<font color="#4E9A06">INFO</font>: Application startup complete. |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
Aquele commando por linha de programa chamado `fastapi` é o **FastAPI CLI**. |
|||
|
|||
O FastAPI CLI recebe o caminho do seu programa Python, detecta automaticamente a variável com o FastAPI (comumente nomeada `app`) e como importá-la, e então a serve. |
|||
|
|||
Para produção você usaria `fastapi run` no lugar. 🚀 |
|||
|
|||
Internamente, **FastAPI CLI** usa <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>, um servidor ASGI de alta performance e pronto para produção. 😎 |
|||
|
|||
## `fastapi dev` |
|||
|
|||
Quando você roda `fastapi dev`, isso vai executar em modo de desenvolvimento. |
|||
|
|||
Por padrão, teremos o **recarregamento automático** ativo, então o programa irá recarregar o servidor automaticamente toda vez que você fizer mudanças no seu código. Isso usa muitos recursos e pode ser menos estável. Você deve apenas usá-lo em modo de desenvolvimento. |
|||
|
|||
O servidor de desenvolvimento escutará no endereço de IP `127.0.0.1` por padrão, este é o IP que sua máquina usa para se comunicar com ela mesma (`localhost`). |
|||
|
|||
## `fastapi run` |
|||
|
|||
Quando você rodar `fastapi run`, isso executará em modo de produção por padrão. |
|||
|
|||
Este modo terá **recarregamento automático desativado** por padrão. |
|||
|
|||
Isso irá escutar no endereço de IP `0.0.0.0`, o que significa todos os endereços IP disponíveis, dessa forma o programa estará acessível publicamente para qualquer um que consiga se comunicar com a máquina. Isso é como você normalmente roda em produção em um contêiner, por exemplo. |
|||
|
|||
Em muitos casos você pode ter (e deveria ter) um "proxy de saída" tratando HTTPS no topo, isso dependerá de como você fará o deploy da sua aplicação, seu provedor pode fazer isso pra você ou talvez seja necessário fazer você mesmo. |
|||
|
|||
!!! tip |
|||
Você pode aprender mais sobre em [documentação de deployment](deployment/index.md){.internal-link target=_blank}. |
@ -0,0 +1,39 @@ |
|||
# Geral - Como Fazer - Receitas |
|||
|
|||
Aqui estão vários links para outros locais na documentação, para perguntas gerais ou frequentes |
|||
|
|||
## Filtro de dados- Segurança |
|||
|
|||
Para assegurar que você não vai retornar mais dados do que deveria, leia a seção [Tutorial - Response Model - Return Type](../tutorial/response-model.md){.internal-link target=_blank}. |
|||
|
|||
## Tags de Documentação - OpenAPI |
|||
Para adicionar tags às suas *rotas* e agrupá-las na UI da documentação, leia a seção [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. |
|||
|
|||
## Resumo e Descrição da documentação - OpenAPI |
|||
|
|||
Para adicionar um resumo e uma descrição às suas *rotas* e exibi-los na UI da documentação, leia a seção [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}. |
|||
|
|||
## Documentação das Descrições de Resposta - OpenAPI |
|||
|
|||
Para definir a descrição de uma resposta exibida na interface da documentação, leia a seção [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}. |
|||
|
|||
## Documentação para Depreciar uma *Operação de Rota* - OpenAPI |
|||
|
|||
Para depreciar uma *operação de rota* e exibi-la na interface da documentação, leia a seção [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}. |
|||
|
|||
## Converter qualquer dado para JSON |
|||
|
|||
|
|||
Para converter qualquer dado para um formato compatível com JSON, leia a seção [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}. |
|||
|
|||
## OpenAPI Metadata - Docs |
|||
|
|||
Para adicionar metadados ao seu esquema OpenAPI, incluindo licensa, versão, contato, etc, leia a seção [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md){.internal-link target=_blank}. |
|||
|
|||
## OpenAPI com URL customizada |
|||
|
|||
Para customizar a URL do OpenAPI (ou removê-la), leia a seção [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. |
|||
|
|||
## URLs de documentação do OpenAPI |
|||
|
|||
Para alterar as URLs usadas para as interfaces de usuário da documentação gerada automaticamente, leia a seção [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. |
@ -0,0 +1,11 @@ |
|||
# Como Fazer - Exemplos Práticos |
|||
|
|||
Aqui você encontrará diferentes exemplos práticos ou tutoriais de "como fazer" para vários tópicos. |
|||
|
|||
A maioria dessas ideias será mais ou menos **independente**, e na maioria dos casos você só precisará estudá-las se elas se aplicarem diretamente ao **seu projeto**. |
|||
|
|||
Se algo parecer interessante e útil para o seu projeto, vá em frente e dê uma olhada. Caso contrário, você pode simplesmente ignorá-lo. |
|||
|
|||
!!! tip |
|||
|
|||
Se você deseja **aprender FastAPI** de forma estruturada (recomendado), leia capítulo por capítulo [Tutorial - Guia de Usuário](../tutorial/index.md){.internal-link target=_blank} em vez disso. |