committed by
GitHub
56 changed files with 1537 additions and 68 deletions
@ -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,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,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,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,24 @@ |
|||
# Classe `APIRouter` |
|||
|
|||
Aqui está a informação de referência para a classe `APIRouter`, com todos os seus parâmetros, atributos e métodos. |
|||
|
|||
Você pode importar a classe `APIRouter` diretamente do `fastapi`: |
|||
|
|||
```python |
|||
from fastapi import APIRouter |
|||
``` |
|||
|
|||
::: fastapi.APIRouter |
|||
options: |
|||
members: |
|||
- websocket |
|||
- include_router |
|||
- get |
|||
- put |
|||
- post |
|||
- delete |
|||
- options |
|||
- head |
|||
- patch |
|||
- trace |
|||
- on_event |
@ -0,0 +1,11 @@ |
|||
# Tarefas em Segundo Plano - `BackgroundTasks` |
|||
|
|||
Você pode declarar um parâmetro em uma *função de operação de rota* ou em uma função de dependência com o tipo `BackgroundTasks`, e então utilizá-lo para agendar a execução de tarefas em segundo plano após o envio da resposta. |
|||
|
|||
Você pode importá-lo diretamente do `fastapi`: |
|||
|
|||
```python |
|||
from fastapi import BackgroundTasks |
|||
``` |
|||
|
|||
::: fastapi.BackgroundTasks |
@ -0,0 +1,20 @@ |
|||
# Exceções - `HTTPException` e `WebSocketException` |
|||
|
|||
Essas são as exceções que você pode lançar para mostrar erros ao cliente. |
|||
|
|||
Quando você lança uma exceção, como aconteceria com o Python normal, o restante da execução é abortado. Dessa forma, você pode lançar essas exceções de qualquer lugar do código para abortar uma solicitação e mostrar o erro ao cliente. |
|||
|
|||
Você pode usar: |
|||
|
|||
* `HTTPException` |
|||
* `WebSocketException` |
|||
|
|||
Essas exceções podem ser importadas diretamente do `fastapi`: |
|||
|
|||
```python |
|||
from fastapi import HTTPException, WebSocketException |
|||
``` |
|||
|
|||
::: fastapi.HTTPException |
|||
|
|||
::: fastapi.WebSocketException |
@ -0,0 +1,6 @@ |
|||
# Referência - API de Código |
|||
|
|||
Aqui está a referência ou API de código, as classes, funções, parâmetros, atributos e todas as partes do FastAPI que você pode usar em suas aplicações. |
|||
|
|||
Se você quer **aprender FastAPI**, é muito melhor ler o |
|||
[FastAPI Tutorial](https://fastapi.tiangolo.com/tutorial/). |
@ -0,0 +1,138 @@ |
|||
# Dependências em decoradores de operações de rota |
|||
|
|||
Em alguns casos você não precisa necessariamente retornar o valor de uma dependência dentro de uma *função de operação de rota*. |
|||
|
|||
Ou a dependência não retorna nenhum valor. |
|||
|
|||
Mas você ainda precisa que ela seja executada/resolvida. |
|||
|
|||
Para esses casos, em vez de declarar um parâmetro em uma *função de operação de rota* com `Depends`, você pode adicionar um argumento `dependencies` do tipo `list` ao decorador da operação de rota. |
|||
|
|||
## Adicionando `dependencies` ao decorador da operação de rota |
|||
|
|||
O *decorador da operação de rota* recebe um argumento opcional `dependencies`. |
|||
|
|||
Ele deve ser uma lista de `Depends()`: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="19" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="18" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível |
|||
|
|||
```Python hl_lines="17" |
|||
{!> ../../../docs_src/dependencies/tutorial006.py!} |
|||
``` |
|||
Essas dependências serão executadas/resolvidas da mesma forma que dependências comuns. Mas o valor delas (se existir algum) não será passado para a sua *função de operação de rota*. |
|||
|
|||
!!! tip "Dica" |
|||
Alguns editores de texto checam parâmetros de funções não utilizados, e os mostram como erros. |
|||
|
|||
Utilizando `dependencies` no *decorador da operação de rota* você pode garantir que elas serão executadas enquanto evita errors de editores/ferramentas. |
|||
|
|||
Isso também pode ser útil para evitar confundir novos desenvolvedores que ao ver um parâmetro não usado no seu código podem pensar que ele é desnecessário. |
|||
|
|||
!!! info "Informação" |
|||
Neste exemplo utilizamos cabeçalhos personalizados inventados `X-Keys` e `X-Token`. |
|||
|
|||
Mas em situações reais, como implementações de segurança, você pode obter mais vantagens em usar as [Ferramentas de segurança integradas (o próximo capítulo)](../security/index.md){.internal-link target=_blank}. |
|||
|
|||
## Erros das dependências e valores de retorno |
|||
|
|||
Você pode utilizar as mesmas *funções* de dependências que você usaria normalmente. |
|||
|
|||
### Requisitos de Dependências |
|||
|
|||
Dependências podem declarar requisitos de requisições (como cabeçalhos) ou outras subdependências: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="8 13" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="7 12" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível |
|||
|
|||
```Python hl_lines="6 11" |
|||
{!> ../../../docs_src/dependencies/tutorial006.py!} |
|||
``` |
|||
|
|||
### Levantando exceções |
|||
|
|||
Essas dependências podem levantar exceções, da mesma forma que dependências comuns: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="10 15" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="9 14" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível |
|||
|
|||
```Python hl_lines="8 13" |
|||
{!> ../../../docs_src/dependencies/tutorial006.py!} |
|||
``` |
|||
|
|||
### Valores de retorno |
|||
|
|||
E elas também podem ou não retornar valores, eles não serão utilizados. |
|||
|
|||
Então, você pode reutilizar uma dependência comum (que retorna um valor) que já seja utilizada em outro lugar, e mesmo que o valor não seja utilizado, a dependência será executada: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="11 16" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="10 15" |
|||
{!> ../../../docs_src/dependencies/tutorial006_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível |
|||
|
|||
```Python hl_lines="9 14" |
|||
{!> ../../../docs_src/dependencies/tutorial006.py!} |
|||
``` |
|||
|
|||
## Dependências para um grupo de *operações de rota* |
|||
|
|||
Mais a frente, quando você ler sobre como estruturar aplicações maiores ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possivelmente com múltiplos arquivos, você aprenderá a declarar um único parâmetro `dependencies` para um grupo de *operações de rota*. |
|||
|
|||
## Dependências globais |
|||
|
|||
No próximo passo veremos como adicionar dependências para uma aplicação `FastAPI` inteira, para que ela seja aplicada em toda *operação de rota*. |
@ -0,0 +1,349 @@ |
|||
# Dependências com yield |
|||
|
|||
O FastAPI possui suporte para dependências que realizam <abbr title='também chamados de "código de saída", "código de cleanup", "código de teardown", "código de finalização", "código de saída para gerenciador de contextos", etc.'>alguns passos extras ao finalizar</abbr>. |
|||
|
|||
Para fazer isso, utilize `yield` em vez de `return`, e escreva os passos extras (código) depois. |
|||
|
|||
!!! tip "Dica" |
|||
Garanta que `yield` é utilizado apenas uma vez. |
|||
|
|||
!!! note "Detalhes Técnicos" |
|||
Qualquer função que possa ser utilizada com: |
|||
|
|||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> ou |
|||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a> |
|||
|
|||
pode ser utilizada como uma dependência do **FastAPI**. |
|||
|
|||
Na realidade, o FastAPI utiliza esses dois decoradores internamente. |
|||
|
|||
## Uma dependência de banco de dados com `yield` |
|||
|
|||
Por exemplo, você poderia utilizar isso para criar uma sessão do banco de dados, e fechá-la após terminar sua operação. |
|||
|
|||
Apenas o código anterior a declaração com `yield` e o código contendo essa declaração são executados antes de criar uma resposta. |
|||
|
|||
```Python hl_lines="2-4" |
|||
{!../../../docs_src/dependencies/tutorial007.py!} |
|||
``` |
|||
|
|||
O valor gerado (yielded) é o que é injetado nas *operações de rota* e outras dependências. |
|||
|
|||
```Python hl_lines="4" |
|||
{!../../../docs_src/dependencies/tutorial007.py!} |
|||
``` |
|||
|
|||
O código após o `yield` é executado após a resposta ser entregue: |
|||
|
|||
```Python hl_lines="5-6" |
|||
{!../../../docs_src/dependencies/tutorial007.py!} |
|||
``` |
|||
|
|||
!!! tip "Dica" |
|||
Você pode usar funções assíncronas (`async`) ou funções comuns. |
|||
|
|||
O **FastAPI** saberá o que fazer com cada uma, da mesma forma que as dependências comuns. |
|||
|
|||
## Uma dependência com `yield` e `try` |
|||
|
|||
Se você utilizar um bloco `try` em uma dependência com `yield`, você irá capturar qualquer exceção que for lançada enquanto a dependência é utilizada. |
|||
|
|||
Por exemplo, se algum código em um certo momento no meio da operação, em outra dependência ou em uma *operação de rota*, fizer um "rollback" de uma transação de banco de dados ou causar qualquer outro erro, você irá capturar a exceção em sua dependência. |
|||
|
|||
Então, você pode procurar por essa exceção específica dentro da dependência com `except AlgumaExcecao`. |
|||
|
|||
Da mesma forma, você pode utilizar `finally` para garantir que os passos de saída são executados, com ou sem exceções. |
|||
|
|||
```python hl_lines="3 5" |
|||
{!../../../docs_src/dependencies/tutorial007.py!} |
|||
``` |
|||
|
|||
## Subdependências com `yield` |
|||
|
|||
Você pode ter subdependências e "árvores" de subdependências de qualquer tamanho e forma, e qualquer uma ou todas elas podem utilizar `yield`. |
|||
|
|||
O **FastAPI** garantirá que o "código de saída" em cada dependência com `yield` é executado na ordem correta. |
|||
|
|||
Por exemplo, `dependency_c` pode depender de `dependency_b`, e `dependency_b` depender de `dependency_a`: |
|||
|
|||
=== "python 3.9+" |
|||
|
|||
```python hl_lines="6 14 22" |
|||
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!} |
|||
``` |
|||
|
|||
=== "python 3.8+" |
|||
|
|||
```python hl_lines="5 13 21" |
|||
{!> ../../../docs_src/dependencies/tutorial008_an.py!} |
|||
``` |
|||
|
|||
=== "python 3.8+ non-annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```python hl_lines="4 12 20" |
|||
{!> ../../../docs_src/dependencies/tutorial008.py!} |
|||
``` |
|||
|
|||
E todas elas podem utilizar `yield`. |
|||
|
|||
Neste caso, `dependency_c` precisa que o valor de `dependency_b` (nomeada de `dep_b` aqui) continue disponível para executar seu código de saída. |
|||
|
|||
E, por outro lado, `dependency_b` precisa que o valor de `dependency_a` (nomeada de `dep_a`) continue disponível para executar seu código de saída. |
|||
|
|||
=== "python 3.9+" |
|||
|
|||
```python hl_lines="18-19 26-27" |
|||
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!} |
|||
``` |
|||
|
|||
=== "python 3.8+" |
|||
|
|||
```python hl_lines="17-18 25-26" |
|||
{!> ../../../docs_src/dependencies/tutorial008_an.py!} |
|||
``` |
|||
|
|||
=== "python 3.8+ non-annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```python hl_lines="16-17 24-25" |
|||
{!> ../../../docs_src/dependencies/tutorial008.py!} |
|||
``` |
|||
|
|||
Da mesma forma, você pode ter algumas dependências com `yield` e outras com `return` e ter uma relação de dependência entre algumas dos dois tipos. |
|||
|
|||
E você poderia ter uma única dependência que precisa de diversas outras dependências com `yield`, etc. |
|||
|
|||
Você pode ter qualquer combinação de dependências que você quiser. |
|||
|
|||
O **FastAPI** se encarrega de executá-las na ordem certa. |
|||
|
|||
!!! note "Detalhes Técnicos" |
|||
Tudo isso funciona graças aos <a href="https://docs.python.org/3/library/contextlib.html" class="external-link" target="_blank">gerenciadores de contexto</a> do Python. |
|||
|
|||
O **FastAPI** utiliza eles internamente para alcançar isso. |
|||
|
|||
## Dependências com `yield` e `httpexception` |
|||
|
|||
Você viu que dependências podem ser utilizadas com `yield` e podem incluir blocos `try` para capturar exceções. |
|||
|
|||
Da mesma forma, você pode lançar uma `httpexception` ou algo parecido no código de saída, após o `yield` |
|||
|
|||
!!! tip "Dica" |
|||
|
|||
Essa é uma técnica relativamente avançada, e na maioria dos casos você não precisa dela totalmente, já que você pode lançar exceções (incluindo `httpexception`) dentro do resto do código da sua aplicação, por exemplo, em uma *função de operação de rota*. |
|||
|
|||
Mas ela existe para ser utilizada caso você precise. 🤓 |
|||
|
|||
=== "python 3.9+" |
|||
|
|||
```python hl_lines="18-22 31" |
|||
{!> ../../../docs_src/dependencies/tutorial008b_an_py39.py!} |
|||
``` |
|||
|
|||
=== "python 3.8+" |
|||
|
|||
```python hl_lines="17-21 30" |
|||
{!> ../../../docs_src/dependencies/tutorial008b_an.py!} |
|||
``` |
|||
|
|||
=== "python 3.8+ non-annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```python hl_lines="16-20 29" |
|||
{!> ../../../docs_src/dependencies/tutorial008b.py!} |
|||
``` |
|||
|
|||
Uma alternativa que você pode utilizar para capturar exceções (e possivelmente lançar outra HTTPException) é criar um [Manipulador de Exceções Customizado](../handling-errors.md#instalando-manipuladores-de-excecoes-customizados){.internal-link target=_blank}. |
|||
|
|||
## Dependências com `yield` e `except` |
|||
|
|||
Se você capturar uma exceção com `except` em uma dependência que utilize `yield` e ela não for levantada novamente (ou uma nova exceção for levantada), o FastAPI não será capaz de identifcar que houve uma exceção, da mesma forma que aconteceria com Python puro: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="15-16" |
|||
{!> ../../../docs_src/dependencies/tutorial008c_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="14-15" |
|||
{!> ../../../docs_src/dependencies/tutorial008c_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-annotated" |
|||
|
|||
!!! tip "dica" |
|||
utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="13-14" |
|||
{!> ../../../docs_src/dependencies/tutorial008c.py!} |
|||
``` |
|||
|
|||
Neste caso, o cliente irá ver uma resposta *HTTP 500 Internal Server Error* como deveria acontecer, já que não estamos levantando nenhuma `HTTPException` ou coisa parecida, mas o servidor **não terá nenhum log** ou qualquer outra indicação de qual foi o erro. 😱 |
|||
|
|||
### Sempre levante (`raise`) exceções em Dependências com `yield` e `except` |
|||
|
|||
Se você capturar uma exceção em uma dependência com `yield`, a menos que você esteja levantando outra `HTTPException` ou coisa parecida, você deveria relançar a exceção original. |
|||
|
|||
Você pode relançar a mesma exceção utilizando `raise`: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="17" |
|||
{!> ../../../docs_src/dependencies/tutorial008d_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="16" |
|||
{!> ../../../docs_src/dependencies/tutorial008d_an.py!} |
|||
``` |
|||
|
|||
=== "python 3.8+ non-annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="15" |
|||
{!> ../../../docs_src/dependencies/tutorial008d.py!} |
|||
``` |
|||
|
|||
Agora o cliente irá receber a mesma resposta *HTTP 500 Internal Server Error*, mas o servidor terá nosso `InternalError` personalizado nos logs. 😎 |
|||
|
|||
## Execução de dependências com `yield` |
|||
|
|||
A sequência de execução é mais ou menos como esse diagrama. O tempo passa do topo para baixo. E cada coluna é uma das partes interagindo ou executando código. |
|||
|
|||
```mermaid |
|||
sequenceDiagram |
|||
|
|||
participant client as Cliente |
|||
participant handler as Manipulador de exceções |
|||
participant dep as Dep com yield |
|||
participant operation as Operação de Rota |
|||
participant tasks as Tarefas de Background |
|||
|
|||
Note over client,operation: pode lançar exceções, incluindo HTTPException |
|||
client ->> dep: Iniciar requisição |
|||
Note over dep: Executar código até o yield |
|||
opt lançar Exceção |
|||
dep -->> handler: lançar Exceção |
|||
handler -->> client: resposta de erro HTTP |
|||
end |
|||
dep ->> operation: Executar dependência, e.g. sessão de BD |
|||
opt raise |
|||
operation -->> dep: Lançar exceção (e.g. HTTPException) |
|||
opt handle |
|||
dep -->> dep: Pode capturar exceções, lançar uma nova HTTPException, lançar outras exceções |
|||
end |
|||
handler -->> client: resposta de erro HTTP |
|||
end |
|||
|
|||
operation ->> client: Retornar resposta ao cliente |
|||
Note over client,operation: Resposta já foi enviada, e não pode ser modificada |
|||
opt Tarefas |
|||
operation -->> tasks: Enviar tarefas de background |
|||
end |
|||
opt Lançar outra exceção |
|||
tasks -->> tasks: Manipula exceções no código da tarefa de background |
|||
end |
|||
``` |
|||
|
|||
!!! info "Informação" |
|||
Apenas **uma resposta** será enviada para o cliente. Ela pode ser uma das respostas de erro, ou então a resposta da *operação de rota*. |
|||
|
|||
Após uma dessas respostas ser enviada, nenhuma outra resposta pode ser enviada |
|||
|
|||
!!! tip "Dica" |
|||
Esse diagrama mostra `HttpException`, mas você pode levantar qualquer outra exceção que você capture em uma dependência com `yield` ou um [Manipulador de exceções personalizado](../handling-errors.md#instalando-manipuladores-de-excecoes-customizados){.internal-link target=_blank}. |
|||
|
|||
Se você lançar qualquer exceção, ela será passada para as dependências com yield, inlcuindo a `HTTPException`. Na maioria dos casos você vai querer relançar essa mesma exceção ou uma nova a partir da dependência com `yield` para garantir que ela seja tratada adequadamente. |
|||
|
|||
## Dependências com `yield`, `HTTPException`, `except` e Tarefas de Background |
|||
|
|||
!!! warning "Aviso" |
|||
Você provavelmente não precisa desses detalhes técnicos, você pode pular essa seção e continuar na próxima seção abaixo. |
|||
|
|||
Esses detalhes são úteis principalmente se você estiver usando uma versão do FastAPI anterior à 0.106.0 e utilizando recursos de dependências com `yield` em tarefas de background. |
|||
|
|||
### Dependências com `yield` e `except`, Detalhes Técnicos |
|||
|
|||
Antes do FastAPI 0.110.0, se você utilizasse uma dependência com `yield`, e então capturasse uma dependência com `except` nessa dependência, caso a exceção não fosse relançada, ela era automaticamente lançada para qualquer manipulador de exceções ou o manipulador de erros interno do servidor. |
|||
|
|||
Isso foi modificado na versão 0.110.0 para consertar o consumo de memória não controlado das exceções relançadas automaticamente sem um manipulador (erros internos do servidor), e para manter o comportamento consistente com o código Python tradicional. |
|||
|
|||
### Tarefas de Background e Dependências com `yield`, Detalhes Técnicos |
|||
|
|||
Antes do FastAPI 0.106.0, levantar exceções após um `yield` não era possível, o código de saída nas dependências com `yield` era executado *após* a resposta ser enviada, então os [Manipuladores de Exceções](../handling-errors.md#instalando-manipuladores-de-excecoes-customizados){.internal-link target=_blank} já teriam executado. |
|||
|
|||
Isso foi implementado dessa forma principalmente para permitir que os mesmos objetos fornecidos ("yielded") pelas dependências dentro de tarefas de background fossem reutilizados, por que o código de saída era executado antes das tarefas de background serem finalizadas. |
|||
|
|||
Ainda assim, como isso exigiria esperar que a resposta navegasse pela rede enquanto mantia ativo um recurso desnecessário na dependência com yield (por exemplo, uma conexão com banco de dados), isso mudou na versão 0.106.0 do FastAPI. |
|||
|
|||
!!! tip "Dica" |
|||
|
|||
Adicionalmente, uma tarefa de background é, normalmente, um conjunto de lógicas independentes que devem ser manipuladas separadamente, com seus próprios recursos (e.g. sua própria conexão com banco de dados). |
|||
|
|||
Então, dessa forma você provavelmente terá um código mais limpo. |
|||
|
|||
Se você costumava depender desse comportamento, agora você precisa criar os recursos para uma tarefa de background dentro dela mesma, e usar internamente apenas dados que não dependam de recursos de dependências com `yield`. |
|||
|
|||
Por exemplo, em vez de utilizar a mesma sessão do banco de dados, você criaria uma nova sessão dentro da tarefa de background, e você obteria os objetos do banco de dados utilizando essa nova sessão. E então, em vez de passar o objeto obtido do banco de dados como um parâmetro para a função da tarefa de background, você passaria o ID desse objeto e buscaria ele novamente dentro da função da tarefa de background. |
|||
|
|||
## Gerenciadores de contexto |
|||
|
|||
### O que são gerenciadores de contexto |
|||
|
|||
"Gerenciadores de Contexto" são qualquer um dos objetos Python que podem ser utilizados com a declaração `with`. |
|||
|
|||
Por exemplo, <a href="https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files" class="external-link" target="_blank">você pode utilizar `with` para ler um arquivo</a>: |
|||
|
|||
```Python |
|||
with open("./somefile.txt") as f: |
|||
contents = f.read() |
|||
print(contents) |
|||
``` |
|||
|
|||
Por baixo dos panos, o código `open("./somefile.txt")` cria um objeto que é chamado de "Gerenciador de Contexto". |
|||
|
|||
Quando o bloco `with` finaliza, ele se certifica de fechar o arquivo, mesmo que tenha ocorrido alguma exceção. |
|||
|
|||
Quando você cria uma dependência com `yield`, o **FastAPI** irá criar um gerenciador de contexto internamente para ela, e combiná-lo com algumas outras ferramentas relacionadas. |
|||
|
|||
### Utilizando gerenciadores de contexto em dependências com `yield` |
|||
|
|||
!!! warning "Aviso" |
|||
Isso é uma ideia mais ou menos "avançada". |
|||
|
|||
Se você está apenas iniciando com o **FastAPI** você pode querer pular isso por enquanto. |
|||
|
|||
Em python, você pode criar Gerenciadores de Contexto ao <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank"> criar uma classe com dois métodos: `__enter__()` e `__exit__()`</a>. |
|||
|
|||
Você também pode usá-los dentro de dependências com `yield` do **FastAPI** ao utilizar `with` ou `async with` dentro da função da dependência: |
|||
|
|||
```Python hl_lines="1-9 13" |
|||
{!../../../docs_src/dependencies/tutorial010.py!} |
|||
``` |
|||
|
|||
!!! tip "Dica" |
|||
Outra forma de criar um gerenciador de contexto é utilizando: |
|||
|
|||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> ou |
|||
|
|||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a> |
|||
|
|||
Para decorar uma função com um único `yield`. |
|||
|
|||
Isso é o que o **FastAPI** usa internamente para dependências com `yield`. |
|||
|
|||
Mas você não precisa usar esses decoradores para as dependências do FastAPI (e você não deveria). |
|||
|
|||
O FastAPI irá fazer isso para você internamente. |
@ -0,0 +1,34 @@ |
|||
# Dependências Globais |
|||
|
|||
Para alguns tipos de aplicação específicos você pode querer adicionar dependências para toda a aplicação. |
|||
|
|||
De forma semelhante a [adicionar dependências (`dependencies`) em *decoradores de operação de rota*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, você pode adicioná-las à aplicação `FastAPI`. |
|||
|
|||
Nesse caso, elas serão aplicadas a todas as *operações de rota* da aplicação: |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="16" |
|||
{!> ../../../docs_src/dependencies/tutorial012_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="16" |
|||
{!> ../../../docs_src/dependencies/tutorial012_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="15" |
|||
{!> ../../../docs_src/dependencies/tutorial012.py!} |
|||
``` |
|||
|
|||
E todos os conceitos apresentados na sessão sobre [adicionar dependências em *decoradores de operação de rota*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} ainda se aplicam, mas nesse caso, para todas as *operações de rota* da aplicação. |
|||
|
|||
## Dependências para conjuntos de *operações de rota* |
|||
|
|||
Mais para a frente, quando você ler sobre como estruturar aplicações maiores ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possivelmente com múltiplos arquivos, você irá aprender a declarar um único parâmetro `dependencies` para um conjunto de *operações de rota*. |
@ -0,0 +1,194 @@ |
|||
# Subdependências |
|||
|
|||
Você pode criar dependências que possuem **subdependências**. |
|||
|
|||
Elas podem ter o nível de **profundidade** que você achar necessário. |
|||
|
|||
O **FastAPI** se encarrega de resolver essas dependências. |
|||
|
|||
## Primeira dependência "injetável" |
|||
|
|||
Você pode criar uma primeira dependência (injetável) dessa forma: |
|||
|
|||
=== "Python 3.10+" |
|||
|
|||
```Python hl_lines="8-9" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="8-9" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="9-10" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.10 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="6-7" |
|||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="8-9" |
|||
{!> ../../../docs_src/dependencies/tutorial005.py!} |
|||
``` |
|||
|
|||
Esse código declara um parâmetro de consulta opcional, `q`, com o tipo `str`, e então retorna esse parâmetro. |
|||
|
|||
Isso é bastante simples (e não muito útil), mas irá nos ajudar a focar em como as subdependências funcionam. |
|||
|
|||
## Segunda dependência, "injetável" e "dependente" |
|||
|
|||
Então, você pode criar uma outra função para uma dependência (um "injetável") que ao mesmo tempo declara sua própria dependência (o que faz dela um "dependente" também): |
|||
|
|||
=== "Python 3.10+" |
|||
|
|||
```Python hl_lines="13" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="13" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="14" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.10 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="11" |
|||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="13" |
|||
{!> ../../../docs_src/dependencies/tutorial005.py!} |
|||
``` |
|||
|
|||
Vamos focar nos parâmetros declarados: |
|||
|
|||
* Mesmo que essa função seja uma dependência ("injetável") por si mesma, ela também declara uma outra dependência (ela "depende" de outra coisa). |
|||
* Ela depende do `query_extractor`, e atribui o valor retornado pela função ao parâmetro `q`. |
|||
* Ela também declara um cookie opcional `last_query`, do tipo `str`. |
|||
* Se o usuário não passou nenhuma consulta `q`, a última consulta é utilizada, que foi salva em um cookie anteriormente. |
|||
|
|||
## Utilizando a dependência |
|||
|
|||
Então podemos utilizar a dependência com: |
|||
|
|||
=== "Python 3.10+" |
|||
|
|||
```Python hl_lines="23" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.9+" |
|||
|
|||
```Python hl_lines="23" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="24" |
|||
{!> ../../../docs_src/dependencies/tutorial005_an.py!} |
|||
``` |
|||
|
|||
=== "Python 3.10 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="19" |
|||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!} |
|||
``` |
|||
|
|||
=== "Python 3.8 non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="22" |
|||
{!> ../../../docs_src/dependencies/tutorial005.py!} |
|||
``` |
|||
|
|||
!!! info "Informação" |
|||
Perceba que nós estamos declarando apenas uma dependência na *função de operação de rota*, em `query_or_cookie_extractor`. |
|||
|
|||
Mas o **FastAPI** saberá que precisa solucionar `query_extractor` primeiro, para passar o resultado para `query_or_cookie_extractor` enquanto chama a função. |
|||
|
|||
```mermaid |
|||
graph TB |
|||
|
|||
query_extractor(["query_extractor"]) |
|||
query_or_cookie_extractor(["query_or_cookie_extractor"]) |
|||
|
|||
read_query["/items/"] |
|||
|
|||
query_extractor --> query_or_cookie_extractor --> read_query |
|||
``` |
|||
|
|||
## Utilizando a mesma dependência múltiplas vezes |
|||
|
|||
Se uma de suas dependências é declarada várias vezes para a mesma *operação de rota*, por exemplo, múltiplas dependências com uma mesma subdependência, o **FastAPI** irá chamar essa subdependência uma única vez para cada requisição. |
|||
|
|||
E o valor retornado é salvo em um <abbr title="Um utilitário/sistema para armazenar valores calculados/gerados para serem reutilizados em vez de computá-los novamente.">"cache"</abbr> e repassado para todos os "dependentes" que precisam dele em uma requisição específica, em vez de chamar a dependência múltiplas vezes para uma mesma requisição. |
|||
|
|||
Em um cenário avançado onde você precise que a dependência seja calculada em cada passo (possivelmente várias vezes) de uma requisição em vez de utilizar o valor em "cache", você pode definir o parâmetro `use_cache=False` em `Depends`: |
|||
|
|||
=== "Python 3.8+" |
|||
|
|||
```Python hl_lines="1" |
|||
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): |
|||
return {"fresh_value": fresh_value} |
|||
``` |
|||
|
|||
=== "Python 3.8+ non-Annotated" |
|||
|
|||
!!! tip "Dica" |
|||
Utilize a versão com `Annotated` se possível. |
|||
|
|||
```Python hl_lines="1" |
|||
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): |
|||
return {"fresh_value": fresh_value} |
|||
``` |
|||
|
|||
## Recapitulando |
|||
|
|||
Com exceção de todas as palavras complicadas usadas aqui, o sistema de **Injeção de Dependência** é bastante simples. |
|||
|
|||
Consiste apenas de funções que parecem idênticas a *funções de operação de rota*. |
|||
|
|||
Mas ainda assim, é bastante poderoso, e permite que você declare grafos (árvores) de dependências com uma profundidade arbitrária. |
|||
|
|||
!!! tip "Dica" |
|||
Tudo isso pode não parecer muito útil com esses exemplos. |
|||
|
|||
Mas você verá o quão útil isso é nos capítulos sobre **segurança**. |
|||
|
|||
E você também verá a quantidade de código que você não precisara escrever. |
@ -0,0 +1,328 @@ |
|||
# Перші кроки |
|||
|
|||
Найпростіший файл FastAPI може виглядати так: |
|||
|
|||
```Python |
|||
{!../../../docs_src/first_steps/tutorial001.py!} |
|||
``` |
|||
|
|||
Скопіюйте це до файлу `main.py`. |
|||
|
|||
Запустіть сервер: |
|||
|
|||
<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> |
|||
|
|||
У консолі буде рядок приблизно такого змісту: |
|||
|
|||
```hl_lines="4" |
|||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) |
|||
``` |
|||
|
|||
Цей рядок показує URL, за яким додаток запускається на вашій локальній машині. |
|||
|
|||
### Перевірте |
|||
|
|||
Відкрийте браузер та введіть адресу <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>. |
|||
|
|||
Ви побачите у відповідь таке повідомлення у форматі JSON: |
|||
|
|||
```JSON |
|||
{"message": "Hello World"} |
|||
``` |
|||
|
|||
### Інтерактивна API документація |
|||
|
|||
Перейдемо сюди <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. |
|||
|
|||
Ви побачите автоматичну інтерактивну API документацію (створену завдяки <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>): |
|||
|
|||
 |
|||
|
|||
### Альтернативна API документація |
|||
|
|||
Тепер перейдемо сюди <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>. |
|||
|
|||
Ви побачите альтернативну автоматичну документацію (створену завдяки <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>): |
|||
|
|||
 |
|||
|
|||
### OpenAPI |
|||
|
|||
**FastAPI** генерує "схему" з усім вашим API, використовуючи стандарт **OpenAPI** для визначення API. |
|||
|
|||
#### "Схема" |
|||
|
|||
"Схема" - це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис. |
|||
|
|||
#### API "схема" |
|||
|
|||
У цьому випадку, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> є специфікацією, яка визначає, як описати схему вашого API. |
|||
|
|||
Це визначення схеми включає шляхи (paths) вашого API, можливі параметри, які вони приймають тощо. |
|||
|
|||
#### "Схема" даних |
|||
|
|||
Термін "схема" також може відноситися до структури даних, наприклад, JSON. |
|||
|
|||
У цьому випадку це означає - атрибути JSON і типи даних, які вони мають тощо. |
|||
|
|||
#### OpenAPI і JSON Schema |
|||
|
|||
OpenAPI описує схему для вашого API. І ця схема включає визначення (або "схеми") даних, що надсилаються та отримуються вашим API за допомогою **JSON Schema**, стандарту для схем даних JSON. |
|||
|
|||
#### Розглянемо `openapi.json` |
|||
|
|||
Якщо вас цікавить, як виглядає вихідна схема OpenAPI, то FastAPI автоматично генерує JSON-схему з усіма описами API. |
|||
|
|||
Ознайомитися можна за посиланням: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>. |
|||
|
|||
Ви побачите приблизно такий JSON: |
|||
|
|||
```JSON |
|||
{ |
|||
"openapi": "3.1.0", |
|||
"info": { |
|||
"title": "FastAPI", |
|||
"version": "0.1.0" |
|||
}, |
|||
"paths": { |
|||
"/items/": { |
|||
"get": { |
|||
"responses": { |
|||
"200": { |
|||
"description": "Successful Response", |
|||
"content": { |
|||
"application/json": { |
|||
|
|||
|
|||
|
|||
... |
|||
``` |
|||
|
|||
#### Для чого потрібний OpenAPI |
|||
|
|||
Схема OpenAPI є основою для обох систем інтерактивної документації. |
|||
|
|||
Існують десятки альтернативних інструментів, заснованих на OpenAPI. Ви можете легко додати будь-який з них до **FastAPI** додатку. |
|||
|
|||
Ви також можете використовувати OpenAPI для автоматичної генерації коду для клієнтів, які взаємодіють з API. Наприклад, для фронтенд-, мобільних або IoT-додатків |
|||
|
|||
## А тепер крок за кроком |
|||
|
|||
### Крок 1: імпортуємо `FastAPI` |
|||
|
|||
```Python hl_lines="1" |
|||
{!../../../docs_src/first_steps/tutorial001.py!} |
|||
``` |
|||
|
|||
`FastAPI` це клас у Python, який надає всю функціональність для API. |
|||
|
|||
!!! note "Технічні деталі" |
|||
`FastAPI` це клас, який успадковується безпосередньо від `Starlette`. |
|||
|
|||
Ви також можете використовувати всю функціональність <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> у `FastAPI`. |
|||
|
|||
### Крок 2: створюємо екземпляр `FastAPI` |
|||
|
|||
```Python hl_lines="3" |
|||
{!../../../docs_src/first_steps/tutorial001.py!} |
|||
``` |
|||
Змінна `app` є екземпляром класу `FastAPI`. |
|||
|
|||
Це буде головна точка для створення і взаємодії з API. |
|||
|
|||
### Крок 3: визначте операцію шляху (path operation) |
|||
|
|||
#### Шлях (path) |
|||
|
|||
"Шлях" це частина URL, яка йде одразу після символу `/`. |
|||
|
|||
Отже, у такому URL, як: |
|||
|
|||
``` |
|||
https://example.com/items/foo |
|||
``` |
|||
|
|||
...шлях буде: |
|||
|
|||
``` |
|||
/items/foo |
|||
``` |
|||
|
|||
!!! info "Додаткова інформація" |
|||
"Шлях" (path) також зазвичай називають "ендпоінтом" (endpoint) або "маршрутом" (route). |
|||
|
|||
При створенні API, "шлях" є основним способом розділення "завдань" і "ресурсів". |
|||
#### Operation |
|||
|
|||
"Операція" (operation) тут означає один з "методів" HTTP. |
|||
|
|||
Один з: |
|||
|
|||
* `POST` |
|||
* `GET` |
|||
* `PUT` |
|||
* `DELETE` |
|||
|
|||
...та більш екзотичних: |
|||
|
|||
* `OPTIONS` |
|||
* `HEAD` |
|||
* `PATCH` |
|||
* `TRACE` |
|||
|
|||
У HTTP-протоколі можна спілкуватися з кожним шляхом, використовуючи один (або кілька) з цих "методів". |
|||
|
|||
--- |
|||
|
|||
При створенні API зазвичай використовуються конкретні методи HTTP для виконання певних дій. |
|||
|
|||
Як правило, використовують: |
|||
|
|||
* `POST`: для створення даних. |
|||
* `GET`: для читання даних. |
|||
* `PUT`: для оновлення даних. |
|||
* `DELETE`: для видалення даних. |
|||
|
|||
В OpenAPI кожен HTTP метод називається "операція". |
|||
|
|||
Ми також будемо дотримуватися цього терміна. |
|||
|
|||
#### Визначте декоратор операції шляху (path operation decorator) |
|||
|
|||
```Python hl_lines="6" |
|||
{!../../../docs_src/first_steps/tutorial001.py!} |
|||
``` |
|||
Декоратор `@app.get("/")` вказує **FastAPI**, що функція нижче, відповідає за обробку запитів, які надходять до неї: |
|||
|
|||
* шлях `/` |
|||
* використовуючи <abbr title="an HTTP GET method"><code>get</code> операцію</abbr> |
|||
|
|||
!!! info "`@decorator` Додаткова інформація" |
|||
Синтаксис `@something` у Python називається "декоратором". |
|||
|
|||
Ви розташовуєте його над функцією. Як гарний декоративний капелюх (мабуть, звідти походить термін). |
|||
|
|||
"Декоратор" приймає функцію нижче і виконує з нею якусь дію. |
|||
|
|||
У нашому випадку, цей декоратор повідомляє **FastAPI**, що функція нижче відповідає **шляху** `/` і **операції** `get`. |
|||
|
|||
Це і є "декоратор операції шляху (path operation decorator)". |
|||
|
|||
Можна також використовувати операції: |
|||
|
|||
* `@app.post()` |
|||
* `@app.put()` |
|||
* `@app.delete()` |
|||
|
|||
І більш екзотичні: |
|||
|
|||
* `@app.options()` |
|||
* `@app.head()` |
|||
* `@app.patch()` |
|||
* `@app.trace()` |
|||
|
|||
!!! tip "Порада" |
|||
Ви можете використовувати кожну операцію (HTTP-метод) на свій розсуд. |
|||
|
|||
**FastAPI** не нав'язує жодного певного значення для кожного методу. |
|||
|
|||
Наведена тут інформація є рекомендацією, а не обов'язковою вимогою. |
|||
|
|||
Наприклад, під час використання GraphQL зазвичай усі дії виконуються тільки за допомогою `POST` операцій. |
|||
|
|||
|
|||
### Крок 4: визначте **функцію операції шляху (path operation function)** |
|||
|
|||
Ось "**функція операції шляху**": |
|||
|
|||
* **шлях**: це `/`. |
|||
* **операція**: це `get`. |
|||
* **функція**: це функція, яка знаходиться нижче "декоратора" (нижче `@app.get("/")`). |
|||
|
|||
```Python hl_lines="7" |
|||
{!../../../docs_src/first_steps/tutorial001.py!} |
|||
``` |
|||
|
|||
Це звичайна функція Python. |
|||
|
|||
FastAPI викликатиме її щоразу, коли отримає запит до URL із шляхом "/", використовуючи операцію `GET`. |
|||
|
|||
У даному випадку це асинхронна функція. |
|||
|
|||
--- |
|||
|
|||
Ви також можете визначити її як звичайну функцію замість `async def`: |
|||
|
|||
```Python hl_lines="7" |
|||
{!../../../docs_src/first_steps/tutorial003.py!} |
|||
``` |
|||
|
|||
!!! note "Примітка" |
|||
Якщо не знаєте в чому різниця, подивіться [Конкурентність: *"Поспішаєш?"*](../async.md#in-a-hurry){.internal-link target=_blank}. |
|||
|
|||
### Крок 5: поверніть результат |
|||
|
|||
```Python hl_lines="8" |
|||
{!../../../docs_src/first_steps/tutorial001.py!} |
|||
``` |
|||
|
|||
Ви можете повернути `dict`, `list`, а також окремі значення `str`, `int`, ітд. |
|||
|
|||
Також можна повернути моделі Pydantic (про це ви дізнаєтесь пізніше). |
|||
|
|||
Існує багато інших об'єктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені, велика ймовірність, що вони вже підтримуються. |
|||
|
|||
## Підіб'ємо підсумки |
|||
|
|||
* Імпортуємо `FastAPI`. |
|||
* Створюємо екземпляр `app`. |
|||
* Пишемо **декоратор операції шляху** як `@app.get("/")`. |
|||
* Пишемо **функцію операції шляху**; наприклад, `def root(): ...`. |
|||
* Запускаємо сервер у режимі розробки `fastapi dev`. |
@ -0,0 +1,84 @@ |
|||
# FastAPI CLI |
|||
|
|||
**FastAPI CLI** 是一个命令行程序,你可以用它来部署和运行你的 FastAPI 应用程序,管理你的 FastAPI 项目,等等。 |
|||
|
|||
当你安装 FastAPI 时(例如使用 `pip install FastAPI` 命令),会包含一个名为 `fastapi-cli` 的软件包,该软件包在终端中提供 `fastapi` 命令。 |
|||
|
|||
要在开发环境中运行你的 FastAPI 应用,你可以使用 `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> |
|||
|
|||
该命令行程序 `fastapi` 就是 **FastAPI CLI**。 |
|||
|
|||
FastAPI CLI 接收你的 Python 程序路径,自动检测包含 FastAPI 的变量(通常命名为 `app`)及其导入方式,然后启动服务。 |
|||
|
|||
在生产环境中,你应该使用 `fastapi run` 命令。🚀 |
|||
|
|||
在内部,**FastAPI CLI** 使用了 <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>,这是一个高性能、适用于生产环境的 ASGI 服务器。😎 |
|||
|
|||
## `fastapi dev` |
|||
|
|||
当你运行 `fastapi dev` 时,它将以开发模式运行。 |
|||
|
|||
默认情况下,它会启用**自动重载**,因此当你更改代码时,它会自动重新加载服务器。该功能是资源密集型的,且相较不启用时更不稳定,因此你应该仅在开发环境下使用它。 |
|||
|
|||
默认情况下,它将监听 IP 地址 `127.0.0.1`,这是你的机器与自身通信的 IP 地址(`localhost`)。 |
|||
|
|||
## `fastapi run` |
|||
|
|||
当你运行 `fastapi run` 时,它默认以生产环境模式运行。 |
|||
|
|||
默认情况下,**自动重载是禁用的**。 |
|||
|
|||
它将监听 IP 地址 `0.0.0.0`,即所有可用的 IP 地址,这样任何能够与该机器通信的人都可以公开访问它。这通常是你在生产环境中运行它的方式,例如在容器中运行。 |
|||
|
|||
在大多数情况下,你会(且应该)有一个“终止代理”在上层为你处理 HTTPS,这取决于你如何部署应用程序,你的服务提供商可能会为你处理此事,或者你可能需要自己设置。 |
|||
|
|||
!!! tip "提示" |
|||
你可以在 [deployment documentation](deployment/index.md){.internal-link target=_blank} 获得更多信息。 |
Loading…
Reference in new issue