🌐 Update Portuguese translations with LLM prompt (#14228)

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* validated llm translation

* fix non-Annotated in llm-prompt

* rerun after a few changes in llm-prompt

* fix non-Annotated

* validated llm translation

* fix llm translation

* update outdated translations

* fix translation for operation IDs

* add header link

* add missing link

* fix line break

* fix diff

* fix llm translation

* fix 'Atualize' to 'Atualizar'

* update alternatives.md

* update async.md

* update fastapi-cli.md

* update features.md

* update help-fastapi.md

* update history-design-future.md

* update index.md

* update advanced/events.md

* update advanced/middleware.md

* update advanced/response-cookies.md

* update advanced/response-headers.md

* update advanced/templates.md

* update advanced/testing-websockets.md

* update advanced/using-request-directly.md

* update advanced/websockets.md

* update advanced/security/oauth2-scopes.md

* update deployment/cloud.md

* update deployment/manually.md

* update how-to/custom-request-and-route.md

* update how-to/migrate-from-pydantic-v1-to-pydantic-v2.md

* update tutorial/background-tasks.md

* update tutorial/first-steps.md

* update tutorial/handling-errors.md

* update tutorial/middleware.md

* update tutorial/request-files.md

* update tutorial/sql-databases.md

* update tutorial/static-files.md

* update tutorial/testing.md

* update tutorial/dependencies/dependencies-with-yield.md

* update advanced/advanced-dependencies.md

---------

Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
This commit is contained in:
Rafael de Oliveira Marques
2025-11-12 13:23:57 -03:00
committed by GitHub
parent 1a2e4152ed
commit 540a83da65
112 changed files with 3751 additions and 3376 deletions

View File

@@ -1,84 +1,85 @@
# Tarefas em segundo plano
# Tarefas em segundo plano { #background-tasks }
Você pode definir tarefas em segundo plano a serem executadas _ após _ retornar uma resposta.
Você pode definir tarefas em segundo plano para serem executadas *após* retornar uma resposta.
Isso é útil para operações que precisam acontecer após uma solicitação, mas que o cliente realmente não precisa esperar a operação ser concluída para receber a resposta.
Isso é útil para operações que precisam acontecer após uma request, mas que o cliente não precisa realmente esperar a operação terminar antes de receber a resposta.
Isso inclui, por exemplo:
- Envio de notificações por email após a realização de uma ação:
- Como conectar-se a um servidor de e-mail e enviar um e-mail tende a ser "lento" (vários segundos), você pode retornar a resposta imediatamente e enviar a notificação por e-mail em segundo plano.
- Processando dados:
- Por exemplo, digamos que você receba um arquivo que deve passar por um processo lento, você pode retornar uma resposta de "Aceito" (HTTP 202) e processá-lo em segundo plano.
* Notificações por e-mail enviadas após realizar uma ação:
* Como conectar-se a um servidor de e-mail e enviar um e-mail tende a ser lento (vários segundos), você pode retornar a resposta imediatamente e enviar a notificação por e-mail em segundo plano.
* Processamento de dados:
* Por exemplo, digamos que você receba um arquivo que precisa passar por um processo lento; você pode retornar uma resposta “Accepted” (HTTP 202) e processar o arquivo em segundo plano.
## Usando `BackgroundTasks`
## Usando `BackgroundTasks` { #using-backgroundtasks }
Primeiro, importe `BackgroundTasks` e defina um parâmetro em sua _função de operação de caminho_ com uma declaração de tipo de `BackgroundTasks`:
Primeiro, importe `BackgroundTasks` e defina um parâmetro na sua *função de operação de rota* com uma declaração de tipo `BackgroundTasks`:
{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
O **FastAPI** criará o objeto do tipo `BackgroundTasks` para você e o passará como esse parâmetro.
## Criar uma função de tarefa
## Crie uma função de tarefa { #create-a-task-function }
Crie uma função a ser executada como tarefa em segundo plano.
Crie uma função para ser executada como a tarefa em segundo plano.
É apenas uma função padrão que pode receber parâmetros.
Pode ser uma função `async def` ou `def` normal, o **FastAPI** saberá como lidar com isso corretamente.
Pode ser uma função `async def` ou um `def` normal, o **FastAPI** saberá como lidar com isso corretamente.
Nesse caso, a função de tarefa gravará em um arquivo (simulando o envio de um e-mail).
Neste caso, a função da tarefa escreverá em um arquivo (simulando o envio de um e-mail).
E como a operação de gravação não usa `async` e `await`, definimos a função com `def` normal:
E como a operação de escrita não usa `async` e `await`, definimos a função com um `def` normal:
{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
## Adicionar a tarefa em segundo plano
## Adicione a tarefa em segundo plano { #add-the-background-task }
Dentro de sua _função de operação de caminho_, passe sua função de tarefa para o objeto _tarefas em segundo plano_ com o método `.add_task()`:
Dentro da sua *função de operação de rota*, passe sua função de tarefa para o objeto de *tarefas em segundo plano* com o método `.add_task()`:
{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
`.add_task()` recebe como argumentos:
O `.add_task()` recebe como argumentos:
- Uma função de tarefa a ser executada em segundo plano (`write_notification`).
- Qualquer sequência de argumentos que deve ser passada para a função de tarefa na ordem (`email`).
- Quaisquer argumentos nomeados que devem ser passados para a função de tarefa (`mensagem = "alguma notificação"`).
* Uma função de tarefa a ser executada em segundo plano (`write_notification`).
* Qualquer sequência de argumentos que deve ser passada para a função de tarefa na ordem (`email`).
* Quaisquer argumentos nomeados que devem ser passados para a função de tarefa (`message="some notification"`).
## Injeção de dependência
## Injeção de dependências { #dependency-injection }
Usar `BackgroundTasks` também funciona com o sistema de injeção de dependência, você pode declarar um parâmetro do tipo `BackgroundTasks` em vários níveis: em uma _função de operação de caminho_, em uma dependência (confiável), em uma subdependência, etc.
Usar `BackgroundTasks` também funciona com o sistema de injeção de dependências; você pode declarar um parâmetro do tipo `BackgroundTasks` em vários níveis: em uma *função de operação de rota*, em uma dependência (dependable), em uma subdependência, etc.
O **FastAPI** sabe o que fazer em cada caso e como reutilizar o mesmo objeto, de forma que todas as tarefas em segundo plano sejam mescladas e executadas em segundo plano posteriormente:
O **FastAPI** sabe o que fazer em cada caso e como reutilizar o mesmo objeto, de forma que todas as tarefas em segundo plano sejam combinadas e executadas em segundo plano depois:
{* ../../docs_src/background_tasks/tutorial002.py hl[13,15,22,25] *}
Neste exemplo, as mensagens serão gravadas no arquivo `log.txt` _após_ o envio da resposta.
{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
Se houver uma consulta na solicitação, ela será gravada no log em uma tarefa em segundo plano.
Neste exemplo, as mensagens serão escritas no arquivo `log.txt` *após* o envio da resposta.
E então outra tarefa em segundo plano gerada na _função de operação de caminho_ escreverá uma mensagem usando o parâmetro de caminho `email`.
Se houver uma query na request, ela será registrada em uma tarefa em segundo plano.
## Detalhes técnicos
E então outra tarefa em segundo plano gerada na *função de operação de rota* escreverá uma mensagem usando o parâmetro de path `email`.
## Detalhes técnicos { #technical-details }
A classe `BackgroundTasks` vem diretamente de <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">`starlette.background`</a>.
Ela é importada/incluída diretamente no FastAPI para que você possa importá-la do `fastapi` e evitar a importação acidental da alternativa `BackgroundTask` (sem o `s` no final) de `starlette.background`.
Ela é importada/incluída diretamente no FastAPI para que você possa importá-la de `fastapi` e evitar importar acidentalmente a alternativa `BackgroundTask` (sem o `s` no final) de `starlette.background`.
Usando apenas `BackgroundTasks` (e não `BackgroundTask`), é então possível usá-la como um parâmetro de _função de operação de caminho_ e deixar o **FastAPI** cuidar do resto para você, assim como ao usar o objeto `Request` diretamente.
Usando apenas `BackgroundTasks` (e não `BackgroundTask`), é possível usá-la como um parâmetro de *função de operação de rota* e deixar o **FastAPI** cuidar do resto para você, assim como ao usar o objeto `Request` diretamente.
Ainda é possível usar `BackgroundTask` sozinho no FastAPI, mas você deve criar o objeto em seu código e retornar uma Starlette `Response` incluindo-o.
Ainda é possível usar `BackgroundTask` sozinho no FastAPI, mas você precisa criar o objeto no seu código e retornar uma `Response` da Starlette incluindo-o.
Você pode ver mais detalhes na <a href="https://www.starlette.dev/background/" class="external-link" target="_blank"> documentação oficiais da Starlette para tarefas em segundo plano </a>.
Você pode ver mais detalhes na <a href="https://www.starlette.dev/background/" class="external-link" target="_blank">documentação oficial da Starlette para tarefas em segundo plano</a>.
## Ressalva
## Ressalva { #caveat }
Se você precisa realizar cálculos pesados em segundo plano e não necessariamente precisa que seja executado pelo mesmo processo (por exemplo, você não precisa compartilhar memória, variáveis, etc), você pode se beneficiar do uso de outras ferramentas maiores, como <a href="http://www.celeryproject.org/" class="external-link" target="_blank"> Celery </a>.
Se você precisar realizar computação pesada em segundo plano e não necessariamente precisar que seja executada pelo mesmo processo (por exemplo, você não precisa compartilhar memória, variáveis, etc.), pode se beneficiar do uso de outras ferramentas maiores, como o <a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a>.
Eles tendem a exigir configurações mais complexas, um gerenciador de fila de mensagens/tarefas, como RabbitMQ ou Redis, mas permitem que você execute tarefas em segundo plano em vários processos e, especialmente, em vários servidores.
Elas tendem a exigir configurações mais complexas, um gerenciador de fila de mensagens/tarefas, como RabbitMQ ou Redis, mas permitem executar tarefas em segundo plano em vários processos e, especialmente, em vários servidores.
Mas se você precisa acessar variáveis e objetos do mesmo aplicativo **FastAPI**, ou precisa realizar pequenas tarefas em segundo plano (como enviar uma notificação por e-mail), você pode simplesmente usar `BackgroundTasks`.
Mas se você precisa acessar variáveis e objetos da mesma aplicação **FastAPI**, ou precisa realizar pequenas tarefas em segundo plano (como enviar uma notificação por e-mail), você pode simplesmente usar `BackgroundTasks`.
## Recapitulando
## Recapitulando { #recap }
Importe e use `BackgroundTasks` com parâmetros em _funções de operação de caminho_ e dependências para adicionar tarefas em segundo plano.
Importe e use `BackgroundTasks` com parâmetros em *funções de operação de rota* e dependências para adicionar tarefas em segundo plano.

View File

@@ -1,4 +1,4 @@
# Aplicações Maiores - Múltiplos Arquivos
# Aplicações Maiores - Múltiplos Arquivos { #bigger-applications-multiple-files }
Se você está construindo uma aplicação ou uma API web, é raro que você possa colocar tudo em um único arquivo.
@@ -10,7 +10,7 @@ Se você vem do Flask, isso seria o equivalente aos Blueprints do Flask.
///
## Um exemplo de estrutura de arquivos
## Um exemplo de estrutura de arquivos { #an-example-file-structure }
Digamos que você tenha uma estrutura de arquivos como esta:
@@ -71,7 +71,7 @@ A mesma estrutura de arquivos com comentários:
│   └── admin.py # "admin" submódulo, e.g. import app.internal.admin
```
## `APIRouter`
## `APIRouter` { #apirouter }
Vamos supor que o arquivo dedicado a lidar apenas com usuários seja o submódulo em `/app/routers/users.py`.
@@ -81,7 +81,7 @@ Mas ele ainda faz parte da mesma aplicação/web API **FastAPI** (faz parte do m
Você pode criar as *operações de rotas* para esse módulo usando o `APIRouter`.
### Importar `APIRouter`
### Importe `APIRouter` { #import-apirouter }
você o importa e cria uma "instância" da mesma maneira que faria com a classe `FastAPI`:
@@ -89,7 +89,7 @@ você o importa e cria uma "instância" da mesma maneira que faria com a classe
{!../../docs_src/bigger_applications/app/routers/users.py!}
```
### *Operações de Rota* com `APIRouter`
### *Operações de Rota* com `APIRouter` { #path-operations-with-apirouter }
E então você o utiliza para declarar suas *operações de rota*.
@@ -113,7 +113,7 @@ Neste exemplo, a variável é chamada de `router`, mas você pode nomeá-la como
Vamos incluir este `APIRouter` na aplicação principal `FastAPI`, mas primeiro, vamos verificar as dependências e outro `APIRouter`.
## Dependências
## Dependências { #dependencies }
Vemos que precisaremos de algumas dependências usadas em vários lugares da aplicação.
@@ -159,7 +159,7 @@ Mas em casos reais, você obterá melhores resultados usando os [Utilitários de
///
## Outro módulo com `APIRouter`
## Outro módulo com `APIRouter` { #another-module-with-apirouter }
Digamos que você também tenha os endpoints dedicados a manipular "itens" do seu aplicativo no módulo em `app/routers/items.py`.
@@ -177,7 +177,7 @@ Sabemos que todas as *operações de rota* neste módulo têm o mesmo:
* Path `prefix`: `/items`.
* `tags`: (apenas uma tag: `items`).
* Extra `responses`.
* `dependências`: todas elas precisam da dependência `X-Token` que criamos.
* `dependencies`: todas elas precisam da dependência `X-Token` que criamos.
Então, em vez de adicionar tudo isso a cada *operação de rota*, podemos adicioná-lo ao `APIRouter`.
@@ -224,17 +224,17 @@ O resultado final é que os caminhos dos itens agora são:
/// tip | Dica
Ter `dependências` no `APIRouter` pode ser usado, por exemplo, para exigir autenticação para um grupo inteiro de *operações de rota*. Mesmo que as dependências não sejam adicionadas individualmente a cada uma delas.
Ter `dependencies` no `APIRouter` pode ser usado, por exemplo, para exigir autenticação para um grupo inteiro de *operações de rota*. Mesmo que as dependências não sejam adicionadas individualmente a cada uma delas.
///
/// check
/// check | Verifique
Os parâmetros `prefix`, `tags`, `responses` e `dependencies` são (como em muitos outros casos) apenas um recurso do **FastAPI** para ajudar a evitar duplicação de código.
///
### Importar as dependências
### Importe as dependências { #import-the-dependencies }
Este código reside no módulo `app.routers.items`, o arquivo `app/routers/items.py`.
@@ -246,7 +246,7 @@ Então usamos uma importação relativa com `..` para as dependências:
{!../../docs_src/bigger_applications/app/routers/items.py!}
```
#### Como funcionam as importações relativas
#### Como funcionam as importações relativas { #how-relative-imports-work }
/// tip | Dica
@@ -309,11 +309,11 @@ Isso se referiria a algum pacote acima de `app/`, com seu próprio arquivo `__in
Mas agora você sabe como funciona, então você pode usar importações relativas em seus próprios aplicativos, não importa o quão complexos eles sejam. 🤓
### Adicione algumas `tags`, `respostas` e `dependências` personalizadas
### Adicione algumas `tags`, `responses` e `dependencies` personalizadas { #add-some-custom-tags-responses-and-dependencies }
Não estamos adicionando o prefixo `/items` nem `tags=["items"]` a cada *operação de rota* porque os adicionamos ao `APIRouter`.
Mas ainda podemos adicionar _mais_ `tags` que serão aplicadas a uma *operação de rota* específica, e também algumas `respostas` extras específicas para essa *operação de rota*:
Mas ainda podemos adicionar _mais_ `tags` que serão aplicadas a uma *operação de rota* específica, e também algumas `responses` extras específicas para essa *operação de rota*:
```Python hl_lines="30-31" title="app/routers/items.py"
{!../../docs_src/bigger_applications/app/routers/items.py!}
@@ -327,7 +327,7 @@ E também terá ambas as respostas na documentação, uma para `404` e uma para
///
## O principal `FastAPI`
## O principal `FastAPI` { #the-main-fastapi }
Agora, vamos ver o módulo em `app/main.py`.
@@ -337,7 +337,7 @@ Este será o arquivo principal em seu aplicativo que une tudo.
E como a maior parte de sua lógica agora viverá em seu próprio módulo específico, o arquivo principal será bem simples.
### Importar `FastAPI`
### Importe o `FastAPI` { #import-fastapi }
Você importa e cria uma classe `FastAPI` normalmente.
@@ -347,7 +347,7 @@ E podemos até declarar [dependências globais](dependencies/global-dependencies
{!../../docs_src/bigger_applications/app/main.py!}
```
### Importe o `APIRouter`
### Importe o `APIRouter` { #import-the-apirouter }
Agora importamos os outros submódulos que possuem `APIRouter`s:
@@ -357,7 +357,7 @@ Agora importamos os outros submódulos que possuem `APIRouter`s:
Como os arquivos `app/routers/users.py` e `app/routers/items.py` são submódulos que fazem parte do mesmo pacote Python `app`, podemos usar um único ponto `.` para importá-los usando "importações relativas".
### Como funciona a importação
### Como funciona a importação { #how-the-importing-works }
A seção:
@@ -399,7 +399,7 @@ Para saber mais sobre pacotes e módulos Python, leia <a href="https://docs.pyth
///
### Evite colisões de nomes
### Evite colisões de nomes { #avoid-name-collisions }
Estamos importando o submódulo `items` diretamente, em vez de importar apenas sua variável `router`.
@@ -420,9 +420,9 @@ Então, para poder usar ambos no mesmo arquivo, importamos os submódulos direta
{!../../docs_src/bigger_applications/app/main.py!}
```
### Incluir o `APIRouter`s para `usuários` e `itens`
### Inclua os `APIRouter`s para `usuários` e `itens` { #include-the-apirouters-for-users-and-items }
Agora, vamos incluir os `roteadores` dos submódulos `usuários` e `itens`:
Agora, vamos incluir os `router`s dos submódulos `users` e `items`:
```Python hl_lines="10-11" title="app/main.py"
{!../../docs_src/bigger_applications/app/main.py!}
@@ -440,7 +440,7 @@ Com `app.include_router()` podemos adicionar cada `APIRouter` ao aplicativo prin
Ele incluirá todas as rotas daquele roteador como parte dele.
/// note | Detalhe Técnico
/// note | Detalhes Técnicos
Na verdade, ele criará internamente uma *operação de rota* para cada *operação de rota* que foi declarada no `APIRouter`.
@@ -448,7 +448,7 @@ Então, nos bastidores, ele realmente funcionará como se tudo fosse o mesmo apl
///
/// check
/// check | Verifique
Você não precisa se preocupar com desempenho ao incluir roteadores.
@@ -458,7 +458,7 @@ Então não afetará o desempenho. ⚡
///
### Incluir um `APIRouter` com um `prefix` personalizado, `tags`, `responses` e `dependencies`
### Inclua um `APIRouter` com um `prefix`, `tags`, `responses` e `dependencies` personalizados { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies }
Agora, vamos imaginar que sua organização lhe deu o arquivo `app/internal/admin.py`.
@@ -470,7 +470,7 @@ Para este exemplo, será super simples. Mas digamos que, como ele é compartilha
{!../../docs_src/bigger_applications/app/internal/admin.py!}
```
Mas ainda queremos definir um `prefixo` personalizado ao incluir o `APIRouter` para que todas as suas *operações de rota* comecem com `/admin`, queremos protegê-lo com as `dependências` que já temos para este projeto e queremos incluir `tags` e `responses`.
Mas ainda queremos definir um `prefix` personalizado ao incluir o `APIRouter` para que todas as suas *operações de rota* comecem com `/admin`, queremos protegê-lo com as `dependencies` que já temos para este projeto e queremos incluir `tags` e `responses`.
Podemos declarar tudo isso sem precisar modificar o `APIRouter` original passando esses parâmetros para `app.include_router()`:
@@ -491,7 +491,7 @@ Mas isso afetará apenas o `APIRouter` em nosso aplicativo, e não em nenhum out
Assim, por exemplo, outros projetos poderiam usar o mesmo `APIRouter` com um método de autenticação diferente.
### Incluir uma *operação de rota*
### Inclua uma *operação de rota* { #include-a-path-operation }
Também podemos adicionar *operações de rota* diretamente ao aplicativo `FastAPI`.
@@ -503,7 +503,7 @@ Aqui fazemos isso... só para mostrar que podemos 🤷:
e funcionará corretamente, junto com todas as outras *operações de rota* adicionadas com `app.include_router()`.
/// info | Detalhes Técnicos
/// note | Detalhes Técnicos Avançados
**Observação**: este é um detalhe muito técnico que você provavelmente pode **simplesmente pular**.
@@ -517,14 +517,14 @@ Como não podemos simplesmente isolá-los e "montá-los" independentemente do re
///
## Verifique a documentação automática da API
## Verifique a documentação automática da API { #check-the-automatic-api-docs }
Agora, execute `uvicorn`, usando o módulo `app.main` e a variável `app`:
Agora, execute sua aplicação:
<div class="termy">
```console
$ uvicorn app.main:app --reload
$ fastapi dev app/main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
@@ -537,7 +537,7 @@ Você verá a documentação automática da API, incluindo os caminhos de todos
<img src="/img/tutorial/bigger-applications/image01.png">
## Incluir o mesmo roteador várias vezes com `prefixos` diferentes
## Inclua o mesmo roteador várias vezes com `prefix` diferentes { #include-the-same-router-multiple-times-with-different-prefix }
Você também pode usar `.include_router()` várias vezes com o *mesmo* roteador usando prefixos diferentes.
@@ -545,7 +545,7 @@ Isso pode ser útil, por exemplo, para expor a mesma API sob prefixos diferentes
Esse é um uso avançado que você pode não precisar, mas está lá caso precise.
## Incluir um `APIRouter` em outro
## Inclua um `APIRouter` em outro { #include-an-apirouter-in-another }
Da mesma forma que você pode incluir um `APIRouter` em um aplicativo `FastAPI`, você pode incluir um `APIRouter` em outro `APIRouter` usando:

View File

@@ -1,28 +1,28 @@
# Corpo - Campos
# Corpo - Campos { #body-fields }
Da mesma forma que você pode declarar validações adicionais e metadados nos parâmetros de *funções de operações de rota* com `Query`, `Path` e `Body`, você pode declarar validações e metadados dentro de modelos do Pydantic usando `Field` do Pydantic.
Da mesma forma que você pode declarar validações adicionais e metadados nos parâmetros de uma *função de operação de rota* com `Query`, `Path` e `Body`, você pode declarar validações e metadados dentro de modelos do Pydantic usando `Field` do Pydantic.
## Importe `Field`
## Importe `Field` { #import-field }
Primeiro, você tem que importá-lo:
{* ../../docs_src/body_fields/tutorial001.py hl[4] *}
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *}
/// warning | Aviso
/// warning | Atenção
Note que `Field` é importado diretamente do `pydantic`, não do `fastapi` como todo o resto (`Query`, `Path`, `Body`, etc).
///
## Declare atributos do modelo
## Declare atributos do modelo { #declare-model-attributes }
Você pode então utilizar `Field` com atributos do modelo:
{* ../../docs_src/body_fields/tutorial001.py hl[11:14] *}
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *}
`Field` funciona da mesma forma que `Query`, `Path` e `Body`, ele possui todos os mesmos parâmetros, etc.
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Na realidade, `Query`, `Path` e outros que você verá em seguida, criam objetos de subclasses de uma classe `Param` comum, que é ela mesma uma subclasse da classe `FieldInfo` do Pydantic.
@@ -40,13 +40,20 @@ Note como cada atributo do modelo com um tipo, valor padrão e `Field` possuem a
///
## Adicione informações extras
## Adicione informações extras { #add-extra-information }
Você pode declarar informação extra em `Field`, `Query`, `Body`, etc. E isso será incluído no JSON Schema gerado.
Você irá aprender mais sobre adicionar informações extras posteriormente nessa documentação, quando estiver aprendendo a declarar exemplos.
## Recapitulando
/// warning | Atenção
Chaves extras passadas para `Field` também estarão presentes no schema OpenAPI resultante da sua aplicação.
Como essas chaves podem não fazer necessariamente parte da especificação OpenAPI, algumas ferramentas de OpenAPI, por exemplo [o validador do OpenAPI](https://validator.swagger.io/), podem não funcionar com o schema gerado.
///
## Recapitulando { #recap }
Você pode usar `Field` do Pydantic para declarar validações extras e metadados para atributos do modelo.

View File

@@ -1,14 +1,14 @@
# Corpo - Múltiplos parâmetros
# Corpo - Múltiplos parâmetros { #body-multiple-parameters }
Agora que nós vimos como usar `Path` e `Query`, veremos usos mais avançados de declarações no corpo da requisição.
## Misture `Path`, `Query` e parâmetros de corpo
## Misture `Path`, `Query` e parâmetros de corpo { #mix-path-query-and-body-parameters }
Primeiro, é claro, você pode misturar `Path`, `Query` e declarações de parâmetro no corpo da requisição livremente e o **FastAPI** saberá o que fazer.
E você também pode declarar parâmetros de corpo como opcionais, definindo o valor padrão com `None`:
{* ../../docs_src/body_multiple_params/tutorial001_py310.py hl[17:19] *}
{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *}
/// note | Nota
@@ -16,7 +16,7 @@ Repare que, neste caso, o `item` que seria capturado a partir do corpo é opcion
///
## Múltiplos parâmetros de corpo
## Múltiplos parâmetros de corpo { #multiple-body-parameters }
No exemplo anterior, as *operações de rota* esperariam um JSON no corpo contendo os atributos de um `Item`, exemplo:
@@ -62,7 +62,7 @@ O **FastAPI** fará a conversão automática a partir da requisição, assim ess
Ele executará a validação dos dados compostos e irá documentá-los de maneira compatível com o esquema OpenAPI e documentação automática.
## Valores singulares no corpo
## Valores singulares no corpo { #singular-values-in-body }
Assim como existem uma `Query` e uma `Path` para definir dados adicionais para parâmetros de consulta e de rota, o **FastAPI** provê o equivalente para `Body`.
@@ -72,7 +72,7 @@ Se você declará-lo como é, porque é um valor singular, o **FastAPI** assumir
Mas você pode instruir o **FastAPI** para tratá-lo como outra chave do corpo usando `Body`:
{* ../../docs_src/body_multiple_params/tutorial003.py hl[22] *}
{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *}
Neste caso, o **FastAPI** esperará um corpo como:
@@ -94,7 +94,7 @@ Neste caso, o **FastAPI** esperará um corpo como:
Mais uma vez, ele converterá os tipos de dados, validar, documentar, etc.
## Múltiplos parâmetros de corpo e consulta
## Múltiplos parâmetros de corpo e consulta { #multiple-body-params-and-query }
Obviamente, você também pode declarar parâmetros de consulta assim que você precisar, de modo adicional a quaisquer parâmetros de corpo.
@@ -112,7 +112,7 @@ q: str | None = None
Por exemplo:
{* ../../docs_src/body_multiple_params/tutorial004_py310.py hl[26] *}
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
/// info | Informação
@@ -120,7 +120,7 @@ Por exemplo:
///
## Declare um único parâmetro de corpo indicando sua chave
## Declare um único parâmetro de corpo indicando sua chave { #embed-a-single-body-parameter }
Suponha que você tem um único parâmetro de corpo `item`, a partir de um modelo Pydantic `Item`.
@@ -134,7 +134,7 @@ item: Item = Body(embed=True)
como em:
{* ../../docs_src/body_multiple_params/tutorial005_py310.py hl[15] *}
{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *}
Neste caso o **FastAPI** esperará um corpo como:
@@ -160,7 +160,7 @@ ao invés de:
}
```
## Recapitulando
## Recapitulando { #recap }
Você pode adicionar múltiplos parâmetros de corpo para sua *função de operação de rota*, mesmo que a requisição possa ter somente um único corpo.

View File

@@ -1,32 +1,42 @@
# Corpo - Modelos aninhados
# Corpo - Modelos aninhados { #body-nested-models }
Com o **FastAPI**, você pode definir, validar, documentar e usar modelos profundamente aninhados de forma arbitrária (graças ao Pydantic).
Com o **FastAPI**, você pode definir, validar, documentar e usar modelos arbitrariamente e profundamente aninhados (graças ao Pydantic).
## Campos do tipo Lista
## Campos do tipo Lista { #list-fields }
Você pode definir um atributo como um subtipo. Por exemplo, uma `list` do Python:
{* ../../docs_src/body_nested_models/tutorial001.py hl[14] *}
{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *}
Isso fará com que tags seja uma lista de itens mesmo sem declarar o tipo dos elementos desta lista.
## Campos do tipo Lista com um parâmetro de tipo
## Campos do tipo Lista com um parâmetro de tipo { #list-fields-with-type-parameter }
Mas o Python tem uma maneira específica de declarar listas com tipos internos ou "parâmetros de tipo":
### Importe `List` do typing
### Importe `List` do typing { #import-typings-list }
Primeiramente, importe `List` do módulo `typing` que já vem por padrão no Python:
No Python 3.9 e superior você pode usar a `list` padrão para declarar essas anotações de tipo, como veremos abaixo. 💡
Mas nas versões do Python anteriores à 3.9 (3.6 e superiores), primeiro é necessário importar `List` do módulo padrão `typing` do Python:
{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
### Declare a `List` com um parâmetro de tipo
### Declare uma `list` com um parâmetro de tipo { #declare-a-list-with-a-type-parameter }
Para declarar tipos que têm parâmetros de tipo(tipos internos), como `list`, `dict`, `tuple`:
Para declarar tipos que têm parâmetros de tipo (tipos internos), como `list`, `dict`, `tuple`:
* Importe os do modulo `typing`
* Se você estiver em uma versão do Python inferior a 3.9, importe a versão equivalente do módulo `typing`
* Passe o(s) tipo(s) interno(s) como "parâmetros de tipo" usando colchetes: `[` e `]`
No Python 3.9, seria:
```Python
my_list: list[str]
```
Em versões do Python anteriores à 3.9, seria:
```Python
from typing import List
@@ -39,20 +49,17 @@ Use a mesma sintaxe padrão para atributos de modelo com tipos internos.
Portanto, em nosso exemplo, podemos fazer com que `tags` sejam especificamente uma "lista de strings":
{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *}
{* ../../docs_src/body_nested_models/tutorial002.py hl[14] *}
## Tipo "set"
## Tipos "set" { #set-types }
Mas então, quando nós pensamos mais, percebemos que as tags não devem se repetir, elas provavelmente devem ser strings únicas.
E que o Python tem um tipo de dados especial para conjuntos de itens únicos, o `set`.
Então podemos importar `Set` e declarar `tags` como um `set` de `str`s:
Então podemos declarar `tags` como um conjunto de strings:
{* ../../docs_src/body_nested_models/tutorial003.py hl[1,14] *}
{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *}
Com isso, mesmo que você receba uma requisição contendo dados duplicados, ela será convertida em um conjunto de itens exclusivos.
@@ -60,7 +67,7 @@ E sempre que você enviar esses dados como resposta, mesmo se a fonte tiver dupl
E também teremos anotações/documentação em conformidade.
## Modelos aninhados
## Modelos aninhados { #nested-models }
Cada atributo de um modelo Pydantic tem um tipo.
@@ -70,17 +77,17 @@ Portanto, você pode declarar "objects" JSON profundamente aninhados com nomes,
Tudo isso, aninhado arbitrariamente.
### Defina um sub-modelo
### Defina um sub-modelo { #define-a-submodel }
Por exemplo, nós podemos definir um modelo `Image`:
{* ../../docs_src/body_nested_models/tutorial004.py hl[9:11] *}
{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *}
### Use o sub-modelo como um tipo
### Use o sub-modelo como um tipo { #use-the-submodel-as-a-type }
E então podemos usa-lo como o tipo de um atributo:
{* ../../docs_src/body_nested_models/tutorial004.py hl[20] *}
{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *}
Isso significa que o **FastAPI** vai esperar um corpo similar à:
@@ -100,28 +107,28 @@ Isso significa que o **FastAPI** vai esperar um corpo similar à:
Novamente, apenas fazendo essa declaração, com o **FastAPI**, você ganha:
* Suporte do editor de texto (compleção, etc), inclusive para modelos aninhados
* Suporte do editor (preenchimento automático, etc.), inclusive para modelos aninhados
* Conversão de dados
* Validação de dados
* Documentação automatica
## Tipos especiais e validação
## Tipos especiais e validação { #special-types-and-validation }
Além dos tipos singulares normais como `str`, `int`, `float`, etc. Você também pode usar tipos singulares mais complexos que herdam de `str`.
Para ver todas as opções possíveis, cheque a documentação para os<a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">tipos exoticos do Pydantic</a>. Você verá alguns exemplos no próximo capitulo.
Para ver todas as opções possíveis, consulte a <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Visão geral dos tipos do Pydantic</a>. Você verá alguns exemplos no próximo capítulo.
Por exemplo, no modelo `Image` nós temos um campo `url`, nós podemos declara-lo como um `HttpUrl` do Pydantic invés de como uma `str`:
{* ../../docs_src/body_nested_models/tutorial005.py hl[4,10] *}
{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *}
A string será verificada para se tornar uma URL válida e documentada no esquema JSON/1OpenAPI como tal.
A string será verificada para se tornar uma URL válida e documentada no JSON Schema / OpenAPI como tal.
## Atributos como listas de submodelos
## Atributos como listas de submodelos { #attributes-with-lists-of-submodels }
Você também pode usar modelos Pydantic como subtipos de `list`, `set`, etc:
{* ../../docs_src/body_nested_models/tutorial006.py hl[20] *}
{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *}
Isso vai esperar(converter, validar, documentar, etc) um corpo JSON tal qual:
@@ -149,38 +156,43 @@ Isso vai esperar(converter, validar, documentar, etc) um corpo JSON tal qual:
}
```
/// info | informação
/// info | Informação
Note como o campo `images` agora tem uma lista de objetos de image.
Observe como a chave `images` agora tem uma lista de objetos de imagem.
///
## Modelos profundamente aninhados
## Modelos profundamente aninhados { #deeply-nested-models }
Você pode definir modelos profundamente aninhados de forma arbitrária:
{* ../../docs_src/body_nested_models/tutorial007.py hl[9,14,20,23,27] *}
{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *}
/// info | informação
/// info | Informação
Note como `Offer` tem uma lista de `Item`s, que por sua vez possui opcionalmente uma lista `Image`s
Observe como `Offer` tem uma lista de `Item`s, que por sua vez têm uma lista opcional de `Image`s
///
## Corpos de listas puras
## Corpos de listas puras { #bodies-of-pure-lists }
Se o valor de primeiro nível do corpo JSON que você espera for um `array` do JSON (uma` lista` do Python), você pode declarar o tipo no parâmetro da função, da mesma forma que nos modelos do Pydantic:
```Python
images: List[Image]
```
ou no Python 3.9 e superior:
```Python
images: list[Image]
```
como em:
{* ../../docs_src/body_nested_models/tutorial008.py hl[15] *}
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
## Suporte de editor em todo canto
## Suporte de editor em todo canto { #editor-support-everywhere }
E você obtém suporte do editor em todos os lugares.
@@ -192,7 +204,7 @@ Você não conseguiria este tipo de suporte de editor se estivesse trabalhando d
Mas você também não precisa se preocupar com eles, os dicts de entrada são convertidos automaticamente e sua saída é convertida automaticamente para JSON também.
## Corpos de `dict`s arbitrários
## Corpos de `dict`s arbitrários { #bodies-of-arbitrary-dicts }
Você também pode declarar um corpo como um `dict` com chaves de algum tipo e valores de outro tipo.
@@ -208,7 +220,7 @@ Outro caso útil é quando você deseja ter chaves de outro tipo, por exemplo, `
Neste caso, você aceitaria qualquer `dict`, desde que tenha chaves` int` com valores `float`:
{* ../../docs_src/body_nested_models/tutorial009.py hl[9] *}
{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
/// tip | Dica
@@ -222,14 +234,14 @@ E o `dict` que você recebe como `weights` terá, na verdade, chaves `int` e val
///
## Recapitulação
## Recapitulação { #recap }
Com **FastAPI** você tem a flexibilidade máxima fornecida pelos modelos Pydantic, enquanto seu código é mantido simples, curto e elegante.
Mas com todos os benefícios:
* Suporte do editor (compleção em todo canto!)
* Conversão de dados (leia-se parsing/serialização)
* Suporte do editor (preenchimento automático em todo canto!)
* Conversão de dados (parsing/serialização)
* Validação de dados
* Documentação dos esquemas
* Documentação automática

View File

@@ -1,6 +1,6 @@
# Corpo - Atualizações
# Corpo - Atualizações { #body-updates }
## Atualização de dados existentes com `PUT`
## Atualização de dados existentes com `PUT` { #update-replacing-with-put }
Para atualizar um item, você pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a>.
@@ -10,7 +10,7 @@ Você pode usar `jsonable_encoder` para converter os dados de entrada em dados q
`PUT` é usado para receber dados que devem substituir os dados existentes.
### Aviso sobre a substituição
### Aviso sobre a substituição { #warning-about-replacing }
Isso significa que, se você quiser atualizar o item `bar` usando `PUT` com um corpo contendo:
@@ -26,9 +26,9 @@ Como ele não inclui o atributo já armazenado `"tax": 20.2`, o modelo de entrad
E os dados seriam salvos com esse "novo" `tax` de `10.5`.
## Atualizações parciais com `PATCH`
## Atualizações parciais com `PATCH` { #partial-updates-with-patch }
Você também pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> para *atualizar* parcialmente os dados.
Você também pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> para atualizar parcialmente os dados.
Isso significa que você pode enviar apenas os dados que deseja atualizar, deixando o restante intacto.
@@ -44,7 +44,7 @@ Mas este guia te dá uma ideia de como eles são destinados a serem usados.
///
### Usando o parâmetro `exclude_unset` do Pydantic
### Usando o parâmetro `exclude_unset` do Pydantic { #using-pydantics-exclude-unset-parameter }
Se você quiser receber atualizações parciais, é muito útil usar o parâmetro `exclude_unset` no método `.model_dump()` do modelo do Pydantic.
@@ -52,7 +52,7 @@ Como `item.model_dump(exclude_unset=True)`.
/// info | Informação
No Pydantic v1, o método que era chamado `.dict()` e foi depreciado (mas ainda suportado) no Pydantic v2. Agora, deve-se usar o método `.model_dump()`.
No Pydantic v1, o método que era chamado `.dict()` e foi descontinuado (mas ainda suportado) no Pydantic v2. Agora, deve-se usar o método `.model_dump()`.
Os exemplos aqui usam `.dict()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` a partir do Pydantic v2.
@@ -64,13 +64,13 @@ Então, você pode usar isso para gerar um `dict` com apenas os dados definidos
{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
### Usando o parâmetro `update` do Pydantic
### Usando o parâmetro `update` do Pydantic { #using-pydantics-update-parameter }
Agora, você pode criar uma cópia do modelo existente usando `.model_copy()`, e passar o parâmetro `update` com um `dict` contendo os dados para atualizar.
/// info | Informação
No Pydantic v1, o método era chamado `.copy()`, ele foi depreciado (mas ainda suportado) no Pydantic v2, e renomeado para `.model_copy()`.
No Pydantic v1, o método era chamado `.copy()`, ele foi descontinuado (mas ainda suportado) no Pydantic v2, e renomeado para `.model_copy()`.
Os exemplos aqui usam `.copy()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_copy()` com o Pydantic v2.
@@ -80,7 +80,7 @@ Como `stored_item_model.model_copy(update=update_data)`:
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
### Recapitulando as atualizações parciais
### Recapitulando as atualizações parciais { #partial-updates-recap }
Resumindo, para aplicar atualizações parciais você pode:

View File

@@ -1,16 +1,16 @@
# Corpo da Requisição
# Corpo da requisição { #request-body }
Quando você precisa enviar dados de um cliente (como de um navegador web) para sua API, você o envia como um **corpo da requisição**.
Quando você precisa enviar dados de um cliente (como de um navegador) para sua API, você os envia como um **corpo da requisição**.
O corpo da **requisição** é a informação enviada pelo cliente para sua API. O corpo da **resposta** é a informação que sua API envia para o cliente.
Sua API quase sempre irá enviar um corpo na **resposta**. Mas os clientes não necessariamente precisam enviar um corpo em toda **requisição**.
Sua API quase sempre precisa enviar um corpo na **resposta**. Mas os clientes não necessariamente precisam enviar **corpos de requisição** o tempo todo, às vezes eles apenas requisitam um path, talvez com alguns parâmetros de consulta, mas não enviam um corpo.
Para declarar um corpo da **requisição**, você utiliza os modelos do <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> com todos os seus poderes e benefícios.
/// info | Informação
Para enviar dados, você deve usar utilizar um dos métodos: `POST` (Mais comum), `PUT`, `DELETE` ou `PATCH`.
Para enviar dados, você deve usar um dos: `POST` (o mais comum), `PUT`, `DELETE` ou `PATCH`.
Enviar um corpo em uma requisição `GET` não tem um comportamento definido nas especificações, porém é suportado pelo FastAPI, apenas para casos de uso bem complexos/extremos.
@@ -18,19 +18,19 @@ Como é desencorajado, a documentação interativa com Swagger UI não irá most
///
## Importe o `BaseModel` do Pydantic
## Importe o `BaseModel` do Pydantic { #import-pydantics-basemodel }
Primeiro, você precisa importar `BaseModel` do `pydantic`:
{* ../../docs_src/body/tutorial001.py hl[4] *}
{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
## Crie seu modelo de dados
## Crie seu modelo de dados { #create-your-data-model }
Então você declara seu modelo de dados como uma classe que herda `BaseModel`.
Utilize os tipos Python padrão para todos os atributos:
{* ../../docs_src/body/tutorial001.py hl[7:11] *}
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
Assim como quando declaramos parâmetros de consulta, quando um atributo do modelo possui um valor padrão, ele se torna opcional. Caso contrário, se torna obrigatório. Use `None` para torná-lo opcional.
@@ -39,13 +39,13 @@ Por exemplo, o modelo acima declara um JSON "`object`" (ou `dict` no Python) com
```JSON
{
"name": "Foo",
"description": "Uma descrição opcional",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
```
...como `description` e `tax` são opcionais (Com um valor padrão de `None`), esse JSON "`object`" também é válido:
...como `description` e `tax` são opcionais (com um valor padrão de `None`), esse JSON "`object`" também é válido:
```JSON
{
@@ -54,40 +54,40 @@ Por exemplo, o modelo acima declara um JSON "`object`" (ou `dict` no Python) com
}
```
## Declare como um parâmetro
## Declare como um parâmetro { #declare-it-as-a-parameter }
Para adicionar o corpo na *função de operação de rota*, declare-o da mesma maneira que você declarou parâmetros de rota e consulta:
Para adicioná-lo à sua *operação de rota*, declare-o da mesma maneira que você declarou parâmetros de rota e de consulta:
{* ../../docs_src/body/tutorial001.py hl[18] *}
{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
...E declare o tipo como o modelo que você criou, `Item`.
...e declare o seu tipo como o modelo que você criou, `Item`.
## Resultados
## Resultados { #results }
Apenas com esse declaração de tipos do Python, o **FastAPI** irá:
Apenas com essa declaração de tipos do Python, o **FastAPI** irá:
* Ler o corpo da requisição como um JSON.
* Converter os tipos correspondentes (se necessário).
* Validar os dados.
* Se algum dados for inválido, irá retornar um erro bem claro, indicando exatamente onde e o que está incorreto.
* Se algum dado for inválido, irá retornar um erro bem claro, indicando exatamente onde e o que estava incorreto.
* Entregar a você a informação recebida no parâmetro `item`.
* Como você o declarou na função como do tipo `Item`, você também terá o suporte do editor (completação, etc) para todos os atributos e seus tipos.
* Gerar um <a href="https://json-schema.org" class="external-link" target="_blank">Esquema JSON</a> com as definições do seu modelo, você também pode utilizá-lo em qualquer lugar que quiser, se fizer sentido para seu projeto.
* Esses esquemas farão parte do esquema OpenAPI, e utilizados nas <abbr title="User Interfaces">UIs</abbr> de documentação automática.
* Gerar definições de <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> para o seu modelo; você também pode usá-las em qualquer outro lugar se fizer sentido para o seu projeto.
* Esses schemas farão parte do esquema OpenAPI gerado, e serão usados pelas <abbr title="User Interfaces Interfaces de usuário">UIs</abbr> de documentação automática.
## Documentação automática
## Documentação automática { #automatic-docs }
Os esquemas JSON dos seus modelos farão parte do esquema OpenAPI gerado para sua aplicação, e aparecerão na documentação interativa da API:
Os JSON Schemas dos seus modelos farão parte do esquema OpenAPI gerado para sua aplicação, e aparecerão na documentação interativa da API:
<img src="/img/tutorial/body/image01.png">
E também serão utilizados em cada *função de operação de rota* que utilizá-los:
E também serão utilizados na documentação da API dentro de cada *operação de rota* que precisar deles:
<img src="/img/tutorial/body/image02.png">
## Suporte do editor de texto:
## Suporte do editor { #editor-support }
No seu editor de texto, dentro da função você receberá dicas de tipos e completação em todo lugar (isso não aconteceria se você recebesse um `dict` em vez de um modelo Pydantic):
No seu editor, dentro da função você receberá dicas de tipos e completação em todo lugar (isso não aconteceria se você recebesse um `dict` em vez de um modelo Pydantic):
<img src="/img/tutorial/body/image03.png">
@@ -111,9 +111,9 @@ Mas você terá o mesmo suporte do editor no <a href="https://www.jetbrains.com/
Se você utiliza o <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> como editor, você pode utilizar o <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Plugin do Pydantic para o PyCharm </a>.
Melhora o suporte do editor para seus modelos Pydantic com::
Melhora o suporte do editor para seus modelos Pydantic com:
* completação automática
* preenchimento automático
* verificação de tipos
* refatoração
* buscas
@@ -121,42 +121,52 @@ Melhora o suporte do editor para seus modelos Pydantic com::
///
## Use o modelo
## Use o modelo { #use-the-model }
Dentro da função, você pode acessar todos os atributos do objeto do modelo diretamente:
{* ../../docs_src/body/tutorial002.py hl[21] *}
{* ../../docs_src/body/tutorial002_py310.py *}
## Corpo da requisição + parâmetros de rota
/// info | Informação
No Pydantic v1 o método se chamava `.dict()`, ele foi descontinuado (mas ainda é suportado) no Pydantic v2, e renomeado para `.model_dump()`.
Os exemplos aqui usam `.dict()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` se puder usar o Pydantic v2.
///
## Corpo da requisição + parâmetros de rota { #request-body-path-parameters }
Você pode declarar parâmetros de rota e corpo da requisição ao mesmo tempo.
O **FastAPI** irá reconhecer que os parâmetros da função que combinam com parâmetros de rota devem ser **retirados da rota**, e parâmetros da função que são declarados como modelos Pydantic sejam **retirados do corpo da requisição**.
O **FastAPI** irá reconhecer que os parâmetros da função que combinam com parâmetros de rota devem ser **retirados da rota**, e que parâmetros da função que são declarados como modelos Pydantic sejam **retirados do corpo da requisição**.
{* ../../docs_src/body/tutorial003.py hl[17:18] *}
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
## Corpo da requisição + parâmetros de rota + parâmetros de consulta
## Corpo da requisição + parâmetros de rota + parâmetros de consulta { #request-body-path-query-parameters }
Você também pode declarar parâmetros de **corpo**, **rota** e **consulta**, ao mesmo tempo.
O **FastAPI** irá reconhecer cada um deles e retirar a informação do local correto.
{* ../../docs_src/body/tutorial004.py hl[18] *}
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
Os parâmetros da função serão reconhecidos conforme abaixo:
* Se o parâmetro também é declarado na **rota**, será utilizado como um parâmetro de rota.
* Se o parâmetro também é declarado no **path**, será utilizado como um parâmetro de rota.
* Se o parâmetro é de um **tipo único** (como `int`, `float`, `str`, `bool`, etc) será interpretado como um parâmetro de **consulta**.
* Se o parâmetro é declarado como um **modelo Pydantic**, será interpretado como o **corpo** da requisição.
/// note | Observação
/// note | Nota
O FastAPI saberá que o valor de `q` não é obrigatório por causa do valor padrão `= None`.
O `Union` em `Union[str, None]` não é utilizado pelo FastAPI, mas permite ao seu editor de texto lhe dar um suporte melhor e detectar erros.
O `str | None` (Python 3.10+) ou o `Union` em `Union[str, None]` (Python 3.8+) não é utilizado pelo FastAPI para determinar que o valor não é obrigatório, ele saberá que não é obrigatório porque tem um valor padrão `= None`.
Mas adicionar as anotações de tipo permitirá ao seu editor oferecer um suporte melhor e detectar erros.
///
## Sem o Pydantic
## Sem o Pydantic { #without-pydantic }
Se você não quer utilizar os modelos Pydantic, você também pode utilizar o parâmetro **Body**. Veja a documentação para [Body - Parâmetros múltiplos: Valores singulares no body](body-multiple-params.md#valores-singulares-no-corpo){.internal-link target=_blank}.
Se você não quer utilizar os modelos Pydantic, você também pode utilizar o parâmetro **Body**. Veja a documentação para [Body - Parâmetros múltiplos: Valores singulares no body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.

View File

@@ -1,4 +1,4 @@
# Modelos de Parâmetros de Cookie
# Modelos de Parâmetros de Cookie { #cookie-parameter-models }
Se você possui um grupo de **cookies** que estão relacionados, você pode criar um **modelo Pydantic** para declará-los. 🍪
@@ -16,7 +16,7 @@ Essa mesma técnica se aplica para `Query`, `Cookie`, e `Header`. 😎
///
## Cookies com Modelos Pydantic
## Cookies com Modelos Pydantic { #cookies-with-a-pydantic-model }
Declare o parâmetro de **cookie** que você precisa em um **modelo Pydantic**, e depois declare o parâmetro como um `Cookie`:
@@ -24,9 +24,9 @@ Declare o parâmetro de **cookie** que você precisa em um **modelo Pydantic**,
O **FastAPI** irá **extrair** os dados para **cada campo** dos **cookies** recebidos na requisição e lhe fornecer o modelo Pydantic que você definiu.
## Verifique os Documentos
## Verifique a Documentação { #check-the-docs }
Você pode ver os cookies definidos na IU dos documentos em `/docs`:
Você pode ver os cookies definidos na IU da documentação em `/docs`:
<div class="screenshot">
<img src="/img/tutorial/cookie-param-models/image01.png">
@@ -36,17 +36,17 @@ Você pode ver os cookies definidos na IU dos documentos em `/docs`:
Tenha em mente que, como os **navegadores lidam com cookies** de maneira especial e por baixo dos panos, eles **não** permitem facilmente que o **JavaScript** lidem com eles.
Se você for na **IU de documentos da API** em `/docs` você poderá ver a **documentação** para cookies das suas *operações de rotas*.
Se você for na **IU da documentação da API** em `/docs` você poderá ver a **documentação** para cookies das suas *operações de rotas*.
Mas mesmo que você **adicionar os dados** e clicar em "Executar", pelo motivo da IU dos documentos trabalharem com **JavaScript**, os cookies não serão enviados, e você verá uma mensagem de **erro** como se você não tivesse escrito nenhum dado.
Mas mesmo que você **adicionar os dados** e clicar em "Executar", pelo motivo da IU da documentação trabalhar com **JavaScript**, os cookies não serão enviados, e você verá uma mensagem de **erro** como se você não tivesse escrito nenhum dado.
///
## Proibir Cookies Adicionais
## Proibir Cookies Adicionais { #forbid-extra-cookies }
Em alguns casos especiais (provavelmente não muito comuns), você pode querer **restringir** os cookies que você deseja receber.
Agora a sua API possui o poder de contrar o seu próprio <abbr title="Isso é uma brincadeira, só por precaução. Isso não tem nada a ver com consentimentos de cookies, mas é engraçado que até a API consegue rejeitar os coitados dos cookies. Coma um biscoito. 🍪">consentimento de cookie</abbr>. 🤪🍪
Agora a sua API possui o poder de controlar o seu próprio <abbr title="Isso é uma brincadeira, só por precaução. Isso não tem nada a ver com consentimentos de cookies, mas é engraçado que até a API consegue rejeitar os coitados dos cookies. Coma um biscoito. 🍪">consentimento de cookie</abbr>. 🤪🍪
Você pode utilizar a configuração do modelo Pydantic para `proibir` qualquer campo `extra`.
@@ -58,7 +58,7 @@ Se o cliente tentar enviar alguns **cookies extras**, eles receberão um retorno
Coitados dos banners de cookies com todo o seu esforço para obter o seu consentimento para a <abbr title="Isso é uma outra piada. Não preste atenção em mim. Beba um café com o seu cookie. ☕">API rejeitá-lo</abbr>. 🍪
Por exemplo, se o cliente tentar enviar um cookie `santa_tracker` com o valor de `good-list-please`, o cliente receberá uma resposta de **erro** informando que o <abbr title="O papai noel desaprova a falta de biscoitos. 🎅 Ok, chega de piadas com os cookies.">cookie `santa_tracker` is not allowed</abbr>:
Por exemplo, se o cliente tentar enviar um cookie `santa_tracker` com o valor de `good-list-please`, o cliente receberá uma resposta de **erro** informando que o `santa_tracker` <abbr title="O papai noel desaprova a falta de biscoitos. 🎅 Ok, chega de piadas com os cookies.">cookie não é permitido</abbr>:
```json
{
@@ -73,6 +73,6 @@ Por exemplo, se o cliente tentar enviar um cookie `santa_tracker` com o valor de
}
```
## Resumo
## Resumo { #summary }
Você consegue utilizar **modelos Pydantic** para declarar <abbr title="Coma um último biscoito antes de você ir embora. 🍪">**cookies**</abbr> no **FastAPI**. 😎

View File

@@ -1,20 +1,19 @@
# Parâmetros de Cookie
# Parâmetros de Cookie { #cookie-parameters }
Você pode definir parâmetros de Cookie da mesma maneira que define paramêtros com `Query` e `Path`.
Você pode definir parâmetros de Cookie da mesma maneira que define parâmetros com `Query` e `Path`.
## Importe `Cookie`
## Importe `Cookie` { #import-cookie }
Primeiro importe `Cookie`:
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *}
## Declare parâmetros de `Cookie`
## Declare parâmetros de `Cookie` { #declare-cookie-parameters }
Então declare os paramêtros de cookie usando a mesma estrutura que em `Path` e `Query`.
Então declare os parâmetros de cookie usando a mesma estrutura que em `Path` e `Query`.
Você pode definir o valor padrão, assim como todas as validações extras ou parâmetros de anotação:
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *}
/// note | Detalhes Técnicos
@@ -31,6 +30,16 @@ Para declarar cookies, você precisa usar `Cookie`, pois caso contrário, os par
///
## Recapitulando
/// info | Informação
Tenha em mente que, como os **navegadores lidam com cookies** de maneiras especiais e nos bastidores, eles **não** permitem facilmente que o **JavaScript** os acesse.
Se você for à **interface de documentação da API** em `/docs`, poderá ver a **documentação** de cookies para suas *operações de rota*.
Mas mesmo que você **preencha os dados** e clique em "Execute", como a interface de documentação funciona com **JavaScript**, os cookies não serão enviados e você verá uma mensagem de **erro** como se você não tivesse escrito nenhum valor.
///
## Recapitulando { #recap }
Declare cookies com `Cookie`, usando o mesmo padrão comum que utiliza-se em `Query` e `Path`.

View File

@@ -1,8 +1,8 @@
# CORS (Cross-Origin Resource Sharing)
# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing }
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORS ou "Cross-Origin Resource Sharing"</a> refere-se às situações em que um frontend rodando em um navegador possui um código JavaScript que se comunica com um backend, e o backend está em uma "origem" diferente do frontend.
## Origem
## Origem { #origin }
Uma origem é a combinação de protocolo (`http`, `https`), domínio (`myapp.com`, `localhost`, `localhost.tiangolo.com`), e porta (`80`, `443`, `8080`).
@@ -12,27 +12,27 @@ Então, todos estes são origens diferentes:
* `https://localhost`
* `http://localhost:8080`
Mesmo se todos estiverem em `localhost`, eles usam diferentes protocolos e portas, portanto, são "origens" diferentes.
Mesmo se todos estiverem em `localhost`, eles usam diferentes protocolos ou portas, portanto, são "origens" diferentes.
## Passos
## Passos { #steps }
Então, digamos que você tenha um frontend rodando no seu navegador em `http://localhost:8080`, e seu JavaScript esteja tentando se comunicar com um backend rodando em http://localhost (como não especificamos uma porta, o navegador assumirá a porta padrão `80`).
Então, digamos que você tenha um frontend rodando no seu navegador em `http://localhost:8080`, e seu JavaScript esteja tentando se comunicar com um backend rodando em `http://localhost` (como não especificamos uma porta, o navegador assumirá a porta padrão `80`).
Portanto, o navegador irá enviar uma requisição HTTP `OPTIONS` ao backend, e se o backend enviar os cabeçalhos apropriados autorizando a comunicação a partir de uma origem diferente (`http://localhost:8080`) então o navegador deixará o JavaScript no frontend enviar sua requisição para o backend.
Portanto, o navegador enviará uma requisição HTTP `OPTIONS` ao backend `:80`, e se o backend enviar os cabeçalhos apropriados autorizando a comunicação a partir dessa origem diferente (`http://localhost:8080`), então o navegador `:8080` permitirá que o JavaScript no frontend envie sua requisição para o backend `:80`.
Para conseguir isso, o backend deve ter uma lista de "origens permitidas".
Para conseguir isso, o backend `:80` deve ter uma lista de "origens permitidas".
Neste caso, ele terá que incluir `http://localhost:8080` para o frontend funcionar corretamente.
Neste caso, a lista terá que incluir `http://localhost:8080` para o frontend `:8080` funcionar corretamente.
## Curingas
## Curingas { #wildcards }
É possível declarar uma lista com `"*"` (um "curinga") para dizer que tudo está permitido.
É possível declarar a lista como `"*"` (um "curinga") para dizer que tudo está permitido.
Mas isso só permitirá certos tipos de comunicação, excluindo tudo que envolva credenciais: cookies, cabeçalhos de autorização como aqueles usados com Bearer Tokens, etc.
Então, para que tudo funcione corretamente, é melhor especificar explicitamente as origens permitidas.
## Usar `CORSMiddleware`
## Usar `CORSMiddleware` { #use-corsmiddleware }
Você pode configurá-lo em sua aplicação **FastAPI** usando o `CORSMiddleware`.
@@ -48,7 +48,7 @@ Você também pode especificar se o seu backend permite:
{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
Os parâmetros padrão usados pela implementação `CORSMiddleware` são restritivos por padrão, então você precisará habilitar explicitamente as origens, métodos ou cabeçalhos específicos para que os navegadores tenham permissão para usá-los em um contexto de domínios diferentes.
Os parâmetros padrão usados pela implementação `CORSMiddleware` são restritivos por padrão, então você precisará habilitar explicitamente as origens, métodos ou cabeçalhos específicos para que os navegadores tenham permissão para usá-los em um contexto cross domain.
Os seguintes argumentos são suportados:
@@ -56,27 +56,30 @@ Os seguintes argumentos são suportados:
* `allow_origin_regex` - Uma string regex para corresponder às origens que devem ter permissão para fazer requisições de origem cruzada. Por exemplo, `'https://.*\.example\.org'`.
* `allow_methods` - Uma lista de métodos HTTP que devem ser permitidos para requisições de origem cruzada. O padrão é `['GET']`. Você pode usar `['*']` para permitir todos os métodos padrão.
* `allow_headers` - Uma lista de cabeçalhos de solicitação HTTP que devem ter suporte para requisições de origem cruzada. O padrão é `[]`. Você pode usar `['*']` para permitir todos os cabeçalhos. Os cabeçalhos `Accept`, `Accept-Language`, `Content-Language` e `Content-Type` são sempre permitidos para <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests" class="external-link" rel="noopener" target="_blank">requisições CORS simples</a>.
* `allow_credentials` - Indica que os cookies devem ser suportados para requisições de origem cruzada. O padrão é `False`. Além disso, `allow_origins` não pode ser definido como `['*']` para que as credenciais sejam permitidas, as origens devem ser especificadas.
* `allow_credentials` - Indica que os cookies devem ser suportados para requisições de origem cruzada. O padrão é `False`.
Nenhum de `allow_origins`, `allow_methods` e `allow_headers` pode ser definido como `['*']` se `allow_credentials` estiver definido como `True`. Todos eles devem ser <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards" class="external-link" rel="noopener" target="_blank">especificados explicitamente</a>.
* `expose_headers` - Indica quaisquer cabeçalhos de resposta que devem ser disponibilizados ao navegador. O padrão é `[]`.
* `max_age` - Define um tempo máximo em segundos para os navegadores armazenarem em cache as respostas CORS. O padrão é `600`.
O middleware responde a dois tipos específicos de solicitação HTTP...
### Requisições CORS pré-voo (preflight)
### Requisições CORS pré-voo (preflight) { #cors-preflight-requests }
Estas são quaisquer solicitações `OPTIONS` com cabeçalhos `Origin` e `Access-Control-Request-Method`.
Nesse caso, o middleware interceptará a solicitação recebida e responderá com cabeçalhos CORS apropriados e uma resposta `200` ou `400` para fins informativos.
### Requisições Simples
### Requisições Simples { #simple-requests }
Qualquer solicitação com um cabeçalho `Origin`. Neste caso, o middleware passará a solicitação normalmente, mas incluirá cabeçalhos CORS apropriados na resposta.
## Mais informações
## Mais informações { #more-info }
Para mais informações <abbr title="Cross-Origin Resource Sharing">CORS</abbr>, acesse <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS documentation</a>.
Para mais informações sobre <abbr title="Cross-Origin Resource Sharing">CORS</abbr>, consulte a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">documentação do CORS da Mozilla</a>.
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Você também pode usar `from starlette.middleware.cors import CORSMiddleware`.

View File

@@ -1,14 +1,14 @@
# Depuração
# Depuração { #debugging }
Você pode conectar o depurador no seu editor, por exemplo, com o Visual Studio Code ou PyCharm.
## Chamar `uvicorn`
## Chamar `uvicorn` { #call-uvicorn }
Em seu aplicativo FastAPI, importe e execute `uvicorn` diretamente:
Em sua aplicação FastAPI, importe e execute `uvicorn` diretamente:
{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
### Sobre `__name__ == "__main__"`
### Sobre `__name__ == "__main__"` { #about-name-main }
O objetivo principal de `__name__ == "__main__"` é ter algum código que seja executado quando seu arquivo for chamado com:
@@ -26,7 +26,7 @@ mas não é chamado quando outro arquivo o importa, como em:
from myapp import app
```
#### Mais detalhes
#### Mais detalhes { #more-details }
Digamos que seu arquivo se chama `myapp.py`.
@@ -78,9 +78,9 @@ Para mais informações, consulte <a href="https://docs.python.org/3/library/__m
///
## Execute seu código com seu depurador
## Execute seu código com seu depurador { #run-your-code-with-your-debugger }
Como você está executando o servidor Uvicorn diretamente do seu código, você pode chamar seu programa Python (seu aplicativo FastAPI) diretamente do depurador.
Como você está executando o servidor Uvicorn diretamente do seu código, você pode chamar seu programa Python (sua aplicação FastAPI) diretamente do depurador.
---

View File

@@ -1,8 +1,8 @@
# Classes como Dependências
# Classes como Dependências { #classes-as-dependencies }
Antes de nos aprofundarmos no sistema de **Injeção de Dependência**, vamos melhorar o exemplo anterior.
## `dict` do exemplo anterior
## `dict` do exemplo anterior { #a-dict-from-the-previous-example }
No exemplo anterior, nós retornávamos um `dict` da nossa dependência ("injetável"):
@@ -14,7 +14,7 @@ E sabemos que editores de texto não têm como oferecer muitas funcionalidades (
Podemos fazer melhor...
## O que caracteriza uma dependência
## O que caracteriza uma dependência { #what-makes-a-dependency }
Até agora você apenas viu dependências declaradas como funções.
@@ -38,7 +38,7 @@ something(some_argument, some_keyword_argument="foo")
Então esse objeto é um "chamável".
## Classes como dependências
## Classes como dependências { #classes-as-dependencies_1 }
Você deve ter percebido que para criar um instância de uma classe em Python, a mesma sintaxe é utilizada.
@@ -89,7 +89,7 @@ Em ambos os casos teremos:
Os dados serão convertidos, validados, documentados no esquema da OpenAPI e etc nos dois casos.
## Utilizando
## Utilizando { #use-it }
Agora você pode declarar sua dependência utilizando essa classe.
@@ -97,7 +97,7 @@ Agora você pode declarar sua dependência utilizando essa classe.
O **FastAPI** chama a classe `CommonQueryParams`. Isso cria uma "instância" dessa classe e é a instância que será passada para o parâmetro `commons` na sua função.
## Anotações de Tipo vs `Depends`
## Anotações de Tipo vs `Depends` { #type-annotation-vs-depends }
Perceba como escrevemos `CommonQueryParams` duas vezes no código abaixo:
@@ -189,11 +189,11 @@ commons = Depends(CommonQueryParams)
{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *}
Mas declarar o tipo é encorajado por que é a forma que o seu editor de texto sabe o que será passado como valor do parâmetro `commons`.
Mas declarar o tipo é encorajado por que é a forma que o seu editor de texto sabe o que será passado como valor do parâmetro `commons`, e assim ele pode ajudar com preenchimento automático, verificações de tipo, etc:
<img src="/img/tutorial/dependencies/image02.png">
## Pegando um Atalho
## Pegando um Atalho { #shortcut }
Mas você pode ver que temos uma repetição do código neste exemplo, escrevendo `CommonQueryParams` duas vezes:

View File

@@ -1,4 +1,4 @@
# Dependências em decoradores de operações de rota
# Dependências em decoradores de operações de rota { #dependencies-in-path-operation-decorators }
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*.
@@ -8,7 +8,7 @@ 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
## Adicione `dependencies` ao decorador da operação de rota { #add-dependencies-to-the-path-operation-decorator }
O *decorador da operação de rota* recebe um argumento opcional `dependencies`.
@@ -22,7 +22,7 @@ Essas dependências serão executadas/resolvidas da mesma forma que dependência
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.
Utilizando `dependencies` no *decorador da operação de rota* você pode garantir que elas serão executadas enquanto evita erros 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.
@@ -30,29 +30,29 @@ Isso também pode ser útil para evitar confundir novos desenvolvedores que ao v
/// info | Informação
Neste exemplo utilizamos cabeçalhos personalizados inventados `X-Keys` e `X-Token`.
Neste exemplo utilizamos cabeçalhos personalizados inventados `X-Key` 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
## Erros das dependências e valores de retorno { #dependencies-errors-and-return-values }
Você pode utilizar as mesmas *funções* de dependências que você usaria normalmente.
### Requisitos de Dependências
### Requisitos de Dependências { #dependency-requirements }
Dependências podem declarar requisitos de requisições (como cabeçalhos) ou outras subdependências:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
### Levantando exceções
### Levantar exceções { #raise-exceptions }
Essas dependências podem levantar exceções, da mesma forma que dependências comuns:
Essas dependências podem `raise` exceções, da mesma forma que dependências comuns:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
### Valores de retorno
### Valores de retorno { #return-values }
E elas também podem ou não retornar valores, eles não serão utilizados.
@@ -60,10 +60,10 @@ Então, você pode reutilizar uma dependência comum (que retorna um valor) que
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
## Dependências para um grupo de *operações de rota*
## Dependências para um grupo de *operações de rota* { #dependencies-for-a-group-of-path-operations }
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*.
Mais a frente, quando você ler sobre como estruturar aplicações maiores ([Aplicações maiores - Múltiplos arquivos](../../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
## Dependências globais { #global-dependencies }
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*.
No próximo passo veremos como adicionar dependências para uma aplicação `FastAPI` inteira, para que elas sejam aplicadas em toda *operação de rota*.

View File

@@ -1,12 +1,12 @@
# Dependências com yield
# Dependências com yield { #dependencies-with-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>.
O **FastAPI** possui suporte para dependências que realizam <abbr title='às vezes também chamado de "código de saída", "código de limpeza", "código de teardown", "código de fechamento", "código de saída do gerenciador de contexto", 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.
Garanta utilizar `yield` apenas uma vez por dependência.
///
@@ -23,19 +23,19 @@ Na realidade, o FastAPI utiliza esses dois decoradores internamente.
///
## Uma dependência de banco de dados com `yield`
## Uma dependência de banco de dados com `yield` { #a-database-dependency-with-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.
Por exemplo, você poderia utilizar isso para criar uma sessão do banco de dados, e fechá-la após terminar.
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.
Apenas o código anterior à declaração com `yield` e o código contendo essa declaração são executados antes de criar uma resposta:
{* ../../docs_src/dependencies/tutorial007.py hl[2:4] *}
O valor gerado (yielded) é o que é injetado nas *operações de rota* e outras dependências.
O valor gerado (yielded) é o que é injetado nas *operações de rota* e outras dependências:
{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
O código após o `yield` é executado após a resposta ser entregue:
O código após o `yield` é executado após a resposta:
{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *}
@@ -47,21 +47,19 @@ O **FastAPI** saberá o que fazer com cada uma, da mesma forma que as dependênc
///
## Uma dependência com `yield` e `try`
## Uma dependência com `yield` e `try` { #a-dependency-with-yield-and-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.
Por exemplo, se algum código em um certo momento no meio, 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 outra exceção, 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!}
```
{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *}
## Subdependências com `yield`
## Subdependências com `yield` { #sub-dependencies-with-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`.
@@ -69,73 +67,17 @@ O **FastAPI** garantirá que o "código de saída" em cada dependência com `yie
Por exemplo, `dependency_c` pode depender de `dependency_b`, e `dependency_b` depender de `dependency_a`:
//// tab | python 3.9+
```python hl_lines="6 14 22"
{!> ../../docs_src/dependencies/tutorial008_an_py39.py!}
```
////
//// tab | python 3.8+
```python hl_lines="5 13 21"
{!> ../../docs_src/dependencies/tutorial008_an.py!}
```
////
//// tab | 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!}
```
////
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}
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.
Neste caso, `dependency_c`, para executar seu código de saída, precisa que o valor de `dependency_b` (nomeado de `dep_b` aqui) continue disponível.
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.
E, por outro lado, `dependency_b` precisa que o valor de `dependency_a` (nomeado de `dep_a`) esteja disponível para executar seu código de saída.
//// tab | python 3.9+
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}
```python hl_lines="18-19 26-27"
{!> ../../docs_src/dependencies/tutorial008_an_py39.py!}
```
////
//// tab | python 3.8+
```python hl_lines="17-18 25-26"
{!> ../../docs_src/dependencies/tutorial008_an.py!}
```
////
//// tab | 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.
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 das duas.
E você poderia ter uma única dependência que precisa de diversas outras dependências com `yield`, etc.
@@ -151,83 +93,45 @@ O **FastAPI** utiliza eles internamente para alcançar isso.
///
## Dependências com `yield` e `httpexception`
## Dependências com `yield` e `HTTPException` { #dependencies-with-yield-and-httpexception }
Você viu que dependências podem ser utilizadas com `yield` e podem incluir blocos `try` para capturar exceções.
Você viu que pode usar dependências com `yield` e ter blocos `try` que tentam executar algum código e depois executar algum código de saída com `finally`.
Da mesma forma, você pode lançar uma `httpexception` ou algo parecido no código de saída, após o `yield`
Você também pode usar `except` para capturar a exceção que foi levantada e fazer algo com ela.
Por exemplo, você pode levantar uma exceção diferente, como `HTTPException`.
/// 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*.
Essa é uma técnica relativamente avançada, e na maioria dos casos você não vai precisar dela, já que você pode levantar exceções (incluindo `HTTPException`) dentro do resto do código da sua aplicação, por exemplo, na *função de operação de rota*.
Mas ela existe para ser utilizada caso você precise. 🤓
///
//// tab | python 3.9+
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
```python hl_lines="18-22 31"
{!> ../../docs_src/dependencies/tutorial008b_an_py39.py!}
```
Se você quiser capturar exceções e criar uma resposta personalizada com base nisso, crie um [Manipulador de Exceções Customizado](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
////
## Dependências com `yield` e `except` { #dependencies-with-yield-and-except }
//// tab | python 3.8+
```python hl_lines="17-21 30"
{!> ../../docs_src/dependencies/tutorial008b_an.py!}
```
////
//// tab | 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:
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 identificar que houve uma exceção, da mesma forma que aconteceria com Python puro:
{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}
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`
### Sempre levante (`raise`) em Dependências com `yield` e `except` { #always-raise-in-dependencies-with-yield-and-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.
Se você capturar uma exceção em uma dependência com `yield`, a menos que você esteja levantando outra `HTTPException` ou coisa parecida, **você deve relançar a exceção original**.
Você pode relançar a mesma exceção utilizando `raise`:
{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
//// tab | python 3.8+ non-annotated
/// tip | Dica
Utilize a versão com `Annotated` se possível.
///
{* ../../docs_src/dependencies/tutorial008d.py hl[15] *}
////
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`
## Execução de dependências com `yield` { #execution-of-dependencies-with-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.
@@ -270,57 +174,69 @@ participant tasks as Tarefas de Background
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
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.
Se você levantar qualquer exceção no código da *função de operação de rota*, ela será passada para as dependências com `yield`, incluindo `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
## Saída antecipada e `scope` { #early-exit-and-scope }
/// warning | Aviso
Normalmente, o código de saída das dependências com `yield` é executado **após a resposta** ser enviada ao cliente.
Você provavelmente não precisa desses detalhes técnicos, você pode pular essa seção e continuar na próxima seção abaixo.
Mas se você sabe que não precisará usar a dependência depois de retornar da *função de operação de rota*, você pode usar `Depends(scope="function")` para dizer ao FastAPI que deve fechar a dependência depois que a *função de operação de rota* retornar, mas **antes** de a **resposta ser enviada**.
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.
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
///
`Depends()` recebe um parâmetro `scope` que pode ser:
### Dependências com `yield` e `except`, Detalhes Técnicos
* `"function"`: iniciar a dependência antes da *função de operação de rota* que trata a requisição, encerrar a dependência depois que a *função de operação de rota* termina, mas **antes** de a resposta ser enviada de volta ao cliente. Assim, a função da dependência será executada **em torno** da *função de operação de rota*.
* `"request"`: iniciar a dependência antes da *função de operação de rota* que trata a requisição (semelhante a quando se usa `"function"`), mas encerrar **depois** que a resposta é enviada de volta ao cliente. Assim, a função da dependência será executada **em torno** do ciclo de **requisição** e resposta.
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.
Se não for especificado e a dependência tiver `yield`, ela terá `scope` igual a `"request"` por padrão.
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.
### `scope` para subdependências { #scope-for-sub-dependencies }
### Tarefas de Background e Dependências com `yield`, Detalhes Técnicos
Quando você declara uma dependência com `scope="request"` (o padrão), qualquer subdependência também precisa ter `scope` igual a `"request"`.
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.
Mas uma dependência com `scope` igual a `"function"` pode ter dependências com `scope` igual a `"function"` e com `scope` igual a `"request"`.
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.
Isso porque qualquer dependência precisa conseguir executar seu código de saída antes das subdependências, pois pode ainda precisar usá-las durante seu código de saída.
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.
```mermaid
sequenceDiagram
/// tip | Dica
participant client as Cliente
participant dep_req as Dep scope="request"
participant dep_func as Dep scope="function"
participant operation as Operação de Rota
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).
client ->> dep_req: Iniciar requisição
Note over dep_req: Executar código até o yield
dep_req ->> dep_func: Passar dependência
Note over dep_func: Executar código até o yield
dep_func ->> operation: Executar operação de rota com dependência
operation ->> dep_func: Retornar da operação de rota
Note over dep_func: Executar código após o yield
Note over dep_func: ✅ Dependência fechada
dep_func ->> client: Enviar resposta ao cliente
Note over client: Resposta enviada
Note over dep_req: Executar código após o yield
Note over dep_req: ✅ Dependência fechada
```
Então, dessa forma você provavelmente terá um código mais limpo.
## Dependências com `yield`, `HTTPException`, `except` e Tarefas de Background { #dependencies-with-yield-httpexception-except-and-background-tasks }
///
Dependências com `yield` evoluíram ao longo do tempo para cobrir diferentes casos de uso e corrigir alguns problemas.
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`.
Se você quiser ver o que mudou em diferentes versões do FastAPI, você pode ler mais sobre isso no guia avançado, em [Dependências Avançadas - Dependências com `yield`, `HTTPException`, `except` e Tarefas de Background](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}.
## Gerenciadores de contexto { #context-managers }
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
### O que são "Gerenciadores de Contexto" { #what-are-context-managers }
"Gerenciadores de Contexto" são qualquer um dos objetos Python que podem ser utilizados com a declaração `with`.
@@ -338,9 +254,9 @@ Quando o bloco `with` finaliza, ele se certifica de fechar o arquivo, mesmo que
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`
### Utilizando gerenciadores de contexto em dependências com `yield` { #using-context-managers-in-dependencies-with-yield }
/// warning | Aviso
/// warning | Atenção
Isso é uma ideia mais ou menos "avançada".
@@ -348,9 +264,10 @@ Se você está apenas iniciando com o **FastAPI** você pode querer pular isso p
///
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>.
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:
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:
{* ../../docs_src/dependencies/tutorial010.py hl[1:9,13] *}
@@ -359,7 +276,6 @@ Você também pode usá-los dentro de dependências com `yield` do **FastAPI** a
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`.

View File

@@ -1,15 +1,16 @@
# Dependências Globais
# Dependências Globais { #global-dependencies }
Para alguns tipos de aplicação específicos você pode querer adicionar dependências para toda a aplicação.
Para alguns tipos de aplicação 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`.
De forma semelhante a [adicionar `dependencies` aos *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:
{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[16] *}
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*
E todos os conceitos apresentados na seção sobre [adicionar `dependencies` aos *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.
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*.
## Dependências para conjuntos de *operações de rota* { #dependencies-for-groups-of-path-operations }
Mais para a frente, quando você ler sobre como estruturar aplicações maiores ([Aplicações Maiores - Múltiplos Arquivos](../../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*.

View File

@@ -1,10 +1,10 @@
# Dependências
# Dependências { #dependencies }
O **FastAPI** possui um poderoso, mas intuitivo sistema de **<abbr title="também conhecidos como, recursos, provedores, serviços, injetáveis">Injeção de Dependência</abbr>**.
O **FastAPI** possui um poderoso, mas intuitivo sistema de **<abbr title="também conhecidos como: componentes, recursos, provedores, serviços, injetáveis">Injeção de Dependência</abbr>**.
Esse sistema foi pensado para ser fácil de usar, e permitir que qualquer desenvolvedor possa integrar facilmente outros componentes ao **FastAPI**.
## O que é "Injeção de Dependência"
## O que é "Injeção de Dependência" { #what-is-dependency-injection }
**"Injeção de Dependência"** no mundo da programação significa, que existe uma maneira de declarar no seu código (nesse caso, suas *funções de operação de rota*) para declarar as coisas que ele precisa para funcionar e que serão utilizadas: "dependências".
@@ -19,13 +19,13 @@ Isso é bastante útil quando você precisa:
Tudo isso, enquanto minimizamos a repetição de código.
## Primeiros passos
## Primeiros passos { #first-steps }
Vamos ver um exemplo simples. Tão simples que não será muito útil, por enquanto.
Mas dessa forma podemos focar em como o sistema de **Injeção de Dependência** funciona.
### Criando uma dependência, ou "injetável"
### Criando uma dependência, ou "injetável" { #create-a-dependency-or-dependable }
Primeiro vamos focar na dependência.
@@ -57,15 +57,15 @@ FastAPI passou a suportar a notação `Annotated` (e começou a recomendá-la) n
Se você utiliza uma versão anterior, ocorrerão erros ao tentar utilizar `Annotated`.
Certifique-se de [Atualizar a versão do FastAPI](../../deployment/versions.md#atualizando-as-versoes-do-fastapi){.internal-link target=_blank} para pelo menos 0.95.1 antes de usar `Annotated`.
Certifique-se de [Atualizar a versão do FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} para pelo menos 0.95.1 antes de usar `Annotated`.
///
### Importando `Depends`
### Importando `Depends` { #import-depends }
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *}
### Declarando a dependência, no "dependente"
### Declarando a dependência, no "dependente" { #declare-the-dependency-in-the-dependant }
Da mesma forma que você utiliza `Body`, `Query`, etc. Como parâmetros de sua *função de operação de rota*, utilize `Depends` com um novo parâmetro:
@@ -106,7 +106,7 @@ common_parameters --> read_users
Assim, você escreve um código compartilhado apenas uma vez e o **FastAPI** se encarrega de chamá-lo em suas *operações de rota*.
/// check | Checando
/// check | Verifique
Perceba que você não precisa criar uma classe especial e enviar a dependência para algum outro lugar em que o **FastAPI** a "registre" ou realize qualquer operação similar.
@@ -114,7 +114,7 @@ Você apenas envia para `Depends` e o **FastAPI** sabe como fazer o resto.
///
## Compartilhando dependências `Annotated`
## Compartilhando dependências `Annotated` { #share-annotated-dependencies }
Nos exemplos acima, você pode ver que existe uma pequena **duplicação de código**.
@@ -140,7 +140,7 @@ As dependências continuarão funcionando como esperado, e a **melhor parte** é
Isso é especialmente útil para uma **base de código grande** onde **as mesmas dependências** são utilizadas repetidamente em **muitas *operações de rota***.
## `Async` ou não, eis a questão
## `Async` ou não, eis a questão { #to-async-or-not-to-async }
Como as dependências também serão chamadas pelo **FastAPI** (da mesma forma que *funções de operação de rota*), as mesmas regras se aplicam ao definir suas funções.
@@ -152,11 +152,11 @@ Não faz diferença. O **FastAPI** sabe o que fazer.
/// note | Nota
Caso você não conheça, veja em [Async: *"Com Pressa?"*](../../async.md#com-pressa){.internal-link target=_blank} a sessão acerca de `async` e `await` na documentação.
Caso você não conheça, veja em [Async: *"Com Pressa?"*](../../async.md#in-a-hurry){.internal-link target=_blank} a sessão acerca de `async` e `await` na documentação.
///
## Integrando com OpenAPI
## Integrando com OpenAPI { #integrated-with-openapi }
Todas as declarações de requisições, validações e requisitos para suas dependências (e sub-dependências) serão integradas em um mesmo esquema OpenAPI.
@@ -164,7 +164,7 @@ Então, a documentação interativa também terá toda a informação sobre essa
<img src="/img/tutorial/dependencies/image01.png">
## Caso de Uso Simples
## Caso de Uso Simples { #simple-usage }
Se você parar para ver, *funções de operação de rota* são declaradas para serem usadas sempre que uma *rota* e uma *operação* se encaixam, e então o **FastAPI** se encarrega de chamar a função correspondente com os argumentos corretos, extraindo os dados da requisição.
@@ -182,7 +182,7 @@ Outros termos comuns para essa mesma ideia de "injeção de dependência" são:
* injetáveis
* componentes
## Plug-ins em **FastAPI**
## Plug-ins em **FastAPI** { #fastapi-plug-ins }
Integrações e "plug-ins" podem ser construídos com o sistema de **Injeção de Dependência**. Mas na verdade, **não há necessidade de criar "plug-ins"**, já que utilizando dependências é possível declarar um número infinito de integrações e interações que se tornam disponíveis para as suas *funções de operação de rota*.
@@ -190,7 +190,7 @@ E as dependências pode ser criadas de uma forma bastante simples e intuitiva qu
Você verá exemplos disso nos próximos capítulos, acerca de bancos de dados relacionais e NoSQL, segurança, etc.
## Compatibilidade do **FastAPI**
## Compatibilidade do **FastAPI** { #fastapi-compatibility }
A simplicidade do sistema de injeção de dependência do **FastAPI** faz ele compatível com:
@@ -203,7 +203,7 @@ A simplicidade do sistema de injeção de dependência do **FastAPI** faz ele co
* sistemas de injeção de dados de resposta
* etc.
## Simples e Poderoso
## Simples e Poderoso { #simple-and-powerful }
Mesmo que o sistema hierárquico de injeção de dependência seja simples de definir e utilizar, ele ainda é bastante poderoso.
@@ -243,7 +243,7 @@ admin_user --> activate_user
paying_user --> pro_items
```
## Integração com **OpenAPI**
## Integração com **OpenAPI** { #integrated-with-openapi_1 }
Todas essas dependências, ao declarar os requisitos para suas *operações de rota*, também adicionam parâmetros, validações, etc.

View File

@@ -1,4 +1,4 @@
# Subdependências
# Subdependências { #sub-dependencies }
Você pode criar dependências que possuem **subdependências**.
@@ -6,9 +6,9 @@ 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"
## Primeira dependência "dependable" { #first-dependency-dependable }
Você pode criar uma primeira dependência (injetável) dessa forma:
Você pode criar uma primeira dependência ("dependable") dessa forma:
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *}
@@ -16,20 +16,20 @@ Esse código declara um parâmetro de consulta opcional, `q`, com o tipo `str`,
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"
## Segunda dependência, "dependable" e "dependente" { #second-dependency-dependable-and-dependant }
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):
Então, você pode criar uma outra função para uma dependência (um "dependable") que ao mesmo tempo declara sua própria dependência (o que faz dela um "dependente" também):
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *}
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).
* Mesmo que essa função seja uma dependência ("dependable") 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
## Utilizando a dependência { #use-the-dependency }
Então podemos utilizar a dependência com:
@@ -54,7 +54,7 @@ read_query["/items/"]
query_extractor --> query_or_cookie_extractor --> read_query
```
## Utilizando a mesma dependência múltiplas vezes
## Utilizando a mesma dependência múltiplas vezes { #using-the-same-dependency-multiple-times }
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.
@@ -86,7 +86,7 @@ async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False
////
## Recapitulando
## Recapitulando { #recap }
Com exceção de todas as palavras complicadas usadas aqui, o sistema de **Injeção de Dependência** é bastante simples.

View File

@@ -1,4 +1,4 @@
# Codificador Compatível com JSON
# Codificador Compatível com JSON { #json-compatible-encoder }
Existem alguns casos em que você pode precisar converter um tipo de dados (como um modelo Pydantic) para algo compatível com JSON (como um `dict`, `list`, etc).
@@ -6,13 +6,13 @@ Por exemplo, se você precisar armazená-lo em um banco de dados.
Para isso, **FastAPI** fornece uma função `jsonable_encoder()`.
## Usando a função `jsonable_encoder`
## Usando a função `jsonable_encoder` { #using-the-jsonable-encoder }
Vamos imaginar que você tenha um banco de dados `fake_db` que recebe apenas dados compatíveis com JSON.
Por exemplo, ele não recebe objetos `datetime`, pois estes objetos não são compatíveis com JSON.
Então, um objeto `datetime` teria que ser convertido em um `str` contendo os dados no formato <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO</a>.
Então, um objeto `datetime` teria que ser convertido em um `str` contendo os dados no <a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">formato ISO</a>.
Da mesma forma, este banco de dados não receberia um modelo Pydantic (um objeto com atributos), apenas um `dict`.

View File

@@ -1,4 +1,4 @@
# Tipos de dados extras
# Tipos de dados extras { #extra-data-types }
Até agora, você tem usado tipos de dados comuns, tais como:
@@ -17,7 +17,7 @@ E você ainda terá os mesmos recursos que viu até agora:
* Validação de dados.
* Anotação e documentação automáticas.
## Outros tipos de dados
## Outros tipos de dados { #other-data-types }
Aqui estão alguns dos tipos de dados adicionais que você pode usar:
@@ -36,7 +36,7 @@ Aqui estão alguns dos tipos de dados adicionais que você pode usar:
* `datetime.timedelta`:
* O `datetime.timedelta` do Python.
* Em requisições e respostas será representado como um `float` de segundos totais.
* O Pydantic também permite representá-lo como uma "codificação ISO 8601 diferença de tempo", <a href="https://docs.pydantic.dev/latest/concepts/serialization/" class="external-link" target="_blank">cheque a documentação para mais informações</a>.
* O Pydantic também permite representá-lo como uma "codificação ISO 8601 diferença de tempo", <a href="https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers" class="external-link" target="_blank">cheque a documentação para mais informações</a>.
* `frozenset`:
* Em requisições e respostas, será tratado da mesma forma que um `set`:
* Nas requisições, uma lista será lida, eliminando duplicadas e convertendo-a em um `set`.
@@ -49,14 +49,14 @@ Aqui estão alguns dos tipos de dados adicionais que você pode usar:
* `Decimal`:
* O `Decimal` padrão do Python.
* Em requisições e respostas será representado como um `float`.
* Você pode checar todos os tipos de dados válidos do Pydantic aqui: <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Tipos de dados do Pydantic</a>.
* Você pode checar todos os tipos de dados válidos do Pydantic aqui: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Tipos de dados do Pydantic</a>.
## Exemplo
## Exemplo { #example }
Aqui está um exemplo de *operação de rota* com parâmetros utilizando-se de alguns dos tipos acima.
{* ../../docs_src/extra_data_types/tutorial001.py hl[1,3,12:16] *}
{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *}
Note que os parâmetros dentro da função tem seu tipo de dados natural, e você pode, por exemplo, realizar manipulações normais de data, como:
{* ../../docs_src/extra_data_types/tutorial001.py hl[18:19] *}
{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *}

View File

@@ -1,4 +1,4 @@
# Modelos Adicionais
# Modelos Adicionais { #extra-models }
Continuando com o exemplo anterior, será comum ter mais de um modelo relacionado.
@@ -6,9 +6,9 @@ Isso é especialmente o caso para modelos de usuários, porque:
* O **modelo de entrada** precisa ser capaz de ter uma senha.
* O **modelo de saída** não deve ter uma senha.
* O **modelo de banco de dados** provavelmente precisaria ter uma senha criptografada.
* O **modelo de banco de dados** provavelmente precisaria ter uma senha com hash.
/// danger
/// danger | Cuidado
Nunca armazene senhas em texto simples dos usuários. Sempre armazene uma "hash segura" que você pode verificar depois.
@@ -16,15 +16,23 @@ Se não souber, você aprenderá o que é uma "senha hash" nos [capítulos de se
///
## Múltiplos modelos
## Múltiplos modelos { #multiple-models }
Aqui está uma ideia geral de como os modelos poderiam parecer com seus campos de senha e os lugares onde são usados:
{* ../../docs_src/extra_models/tutorial001.py hl[9,11,16,22,24,29:30,33:35,40:41] *}
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
### Sobre `**user_in.dict()`
/// info | Informação
#### O `.dict()` do Pydantic
No Pydantic v1 o método se chamava `.dict()`, ele foi descontinuado (mas ainda é suportado) no Pydantic v2 e renomeado para `.model_dump()`.
Os exemplos aqui usam `.dict()` por compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` se puder usar o Pydantic v2.
///
### Sobre `**user_in.dict()` { #about-user-in-dict }
#### O `.dict()` do Pydantic { #pydantics-dict }
`user_in` é um modelo Pydantic da classe `UserIn`.
@@ -61,7 +69,7 @@ teríamos um `dict` Python com:
}
```
#### Desembrulhando um `dict`
#### Desembrulhando um `dict` { #unpacking-a-dict }
Se tomarmos um `dict` como `user_dict` e passarmos para uma função (ou classe) com `**user_dict`, o Python irá "desembrulhá-lo". Ele passará as chaves e valores do `user_dict` diretamente como argumentos chave-valor.
@@ -93,7 +101,7 @@ UserInDB(
)
```
#### Um modelo Pydantic a partir do conteúdo de outro
#### Um modelo Pydantic a partir do conteúdo de outro { #a-pydantic-model-from-the-contents-of-another }
Como no exemplo acima, obtivemos o `user_dict` a partir do `user_in.dict()`, este código:
@@ -108,11 +116,11 @@ seria equivalente a:
UserInDB(**user_in.dict())
```
...porque `user_in.dict()` é um `dict`, e depois fazemos o Python "desembrulhá-lo" passando-o para UserInDB precedido por `**`.
...porque `user_in.dict()` é um `dict`, e depois fazemos o Python "desembrulhá-lo" passando-o para `UserInDB` precedido por `**`.
Então, obtemos um modelo Pydantic a partir dos dados em outro modelo Pydantic.
#### Desembrulhando um `dict` e palavras-chave extras
#### Desembrulhando um `dict` e palavras-chave extras { #unpacking-a-dict-and-extra-keywords }
E, então, adicionando o argumento de palavra-chave extra `hashed_password=hashed_password`, como em:
@@ -132,13 +140,13 @@ UserInDB(
)
```
/// warning
/// warning | Atenção
As funções adicionais de suporte são apenas para demonstração de um fluxo possível dos dados, mas é claro que elas não fornecem segurança real.
As funções adicionais de suporte `fake_password_hasher` e `fake_save_user` servem apenas para demonstrar um fluxo possível dos dados, mas é claro que elas não fornecem segurança real.
///
## Reduzir duplicação
## Reduzir duplicação { #reduce-duplication }
Reduzir a duplicação de código é uma das ideias principais no **FastAPI**.
@@ -154,25 +162,25 @@ Toda conversão de dados, validação, documentação, etc. ainda funcionará no
Dessa forma, podemos declarar apenas as diferenças entre os modelos (com `password` em texto claro, com `hashed_password` e sem senha):
{* ../../docs_src/extra_models/tutorial002.py hl[9,15:16,19:20,23:24] *}
{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *}
## `Union` ou `anyOf`
## `Union` ou `anyOf` { #union-or-anyof }
Você pode declarar uma resposta como o `Union` de dois tipos, o que significa que a resposta seria qualquer um dos dois.
Você pode declarar uma resposta como o `Union` de dois ou mais tipos, o que significa que a resposta seria qualquer um deles.
Isso será definido no OpenAPI com `anyOf`.
Para fazer isso, use a dica de tipo padrão do Python <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>:
Para fazer isso, use a anotação de tipo padrão do Python <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>:
/// note
/// note | Nota
Ao definir um <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a>, inclua o tipo mais específico primeiro, seguido pelo tipo menos específico. No exemplo abaixo, o tipo mais específico `PlaneItem` vem antes de `CarItem` em `Union[PlaneItem, CarItem]`.
///
{* ../../docs_src/extra_models/tutorial003.py hl[1,14:15,18:20,33] *}
{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *}
### `Union` no Python 3.10
### `Union` no Python 3.10 { #union-in-python-3-10 }
Neste exemplo, passamos `Union[PlaneItem, CarItem]` como o valor do argumento `response_model`.
@@ -184,27 +192,27 @@ Se estivesse em uma anotação de tipo, poderíamos ter usado a barra vertical,
some_variable: PlaneItem | CarItem
```
Mas se colocarmos isso em `response_model=PlaneItem | CarItem` teríamos um erro, pois o Python tentaria executar uma **operação inválida** entre `PlaneItem` e `CarItem` em vez de interpretar isso como uma anotação de tipo.
Mas se colocarmos isso na atribuição `response_model=PlaneItem | CarItem`, teríamos um erro, pois o Python tentaria executar uma **operação inválida** entre `PlaneItem` e `CarItem` em vez de interpretar isso como uma anotação de tipo.
## Lista de modelos
## Lista de modelos { #list-of-models }
Da mesma forma, você pode declarar respostas de listas de objetos.
Para isso, use o padrão Python `typing.List` (ou simplesmente `list` no Python 3.9 e superior):
{* ../../docs_src/extra_models/tutorial004.py hl[1,20] *}
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
## Resposta com `dict` arbitrário
## Resposta com `dict` arbitrário { #response-with-arbitrary-dict }
Você também pode declarar uma resposta usando um simples `dict` arbitrário, declarando apenas o tipo das chaves e valores, sem usar um modelo Pydantic.
Isso é útil se você não souber os nomes de campo / atributo válidos (que seriam necessários para um modelo Pydantic) antecipadamente.
Neste caso, você pode usar `typing.Dict` (ou simplesmente dict no Python 3.9 e superior):
Neste caso, você pode usar `typing.Dict` (ou simplesmente `dict` no Python 3.9 e superior):
{* ../../docs_src/extra_models/tutorial005.py hl[1,8] *}
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
## Em resumo
## Recapitulação { #recap }
Use vários modelos Pydantic e herde livremente para cada caso.

View File

@@ -1,4 +1,4 @@
# Primeiros Passos
# Primeiros Passos { #first-steps }
O arquivo FastAPI mais simples pode se parecer com:
@@ -48,15 +48,15 @@ $ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid
</div>
Na saída, temos:
Na saída, há uma linha com algo como:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Essa linha mostra a URL onde a sua aplicação está sendo servida, que nesse caso é a sua máquina local.
Essa linha mostra a URL onde a sua aplicação está sendo servida, na sua máquina local.
### Confira
### Confira { #check-it }
Abra o seu navegador em <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
@@ -66,7 +66,7 @@ Você verá essa resposta em JSON:
{"message": "Hello World"}
```
### Documentação Interativa de APIs
### Documentação Interativa de APIs { #interactive-api-docs }
Agora vá para <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
@@ -74,7 +74,7 @@ Você verá a documentação interativa automática da API (fornecida por <a hre
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Documentação Alternativa de APIs
### Documentação Alternativa de APIs { #alternative-api-docs }
E agora, vá para <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
@@ -82,31 +82,31 @@ Você verá a documentação alternativa automática (fornecida por <a href="htt
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
### OpenAPI { #openapi }
O **FastAPI** gera um "*schema*" com toda a sua API usando o padrão **OpenAPI** para definir APIs.
#### "*Schema*"
#### "*Schema*" { #schema }
Um "*schema*" é uma definição ou descrição de algo. Não o código que o implementa, mas apenas uma descrição abstrata.
#### API "*schema*"
#### API "*schema*" { #api-schema }
Nesse caso, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> é uma especificação que determina como definir um *schema* da sua API.
Esta definição de *schema* inclui as rotas da sua API, os parâmetros possíveis que elas usam, etc.
Esta definição de *schema* inclui os paths da sua API, os parâmetros possíveis que eles usam, etc.
#### "*Schema*" de dados
#### "*Schema*" de dados { #data-schema }
O termo "*schema*" também pode se referir à forma de alguns dados, como um conteúdo JSON.
Nesse caso, significaria os atributos JSON e os tipos de dados que eles possuem, etc.
#### OpenAPI e JSON *Schema*
#### OpenAPI e JSON Schema { #openapi-and-json-schema }
OpenAPI define um *schema* de API para sua API. E esse *schema* inclui definições (ou "*schemas*") dos dados enviados e recebidos por sua API usando **JSON *Schema***, o padrão para *schemas* de dados JSON.
OpenAPI define um *schema* de API para sua API. E esse *schema* inclui definições (ou "*schemas*") dos dados enviados e recebidos por sua API usando **JSON Schema**, o padrão para *schemas* de dados JSON.
#### Verifique o `openapi.json`
#### Verifique o `openapi.json` { #check-the-openapi-json }
Se você está curioso(a) sobre a aparência do *schema* bruto OpenAPI, o FastAPI gera automaticamente um JSON (*schema*) com as descrições de toda a sua API.
@@ -116,7 +116,7 @@ Ele mostrará um JSON começando com algo como:
```JSON
{
"openapi": "3.0.2",
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
@@ -135,7 +135,7 @@ Ele mostrará um JSON começando com algo como:
...
```
#### Para que serve o OpenAPI
#### Para que serve o OpenAPI { #what-is-openapi-for }
O *schema* OpenAPI é o que possibilita os dois sistemas de documentação interativos mostrados.
@@ -143,15 +143,15 @@ E existem dezenas de alternativas, todas baseadas em OpenAPI. Você pode facilme
Você também pode usá-lo para gerar código automaticamente para clientes que se comunicam com sua API. Por exemplo, aplicativos front-end, móveis ou IoT.
## Recapitulando, passo a passo
## Recapitulando, passo a passo { #recap-step-by-step }
### Passo 1: importe `FastAPI`
### Passo 1: importe `FastAPI` { #step-1-import-fastapi }
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
`FastAPI` é uma classe Python que fornece todas as funcionalidades para sua API.
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
`FastAPI` é uma classe que herda diretamente de `Starlette`.
@@ -159,7 +159,7 @@ Você pode usar todas as funcionalidades do <a href="https://www.starlette.dev/"
///
### Passo 2: crie uma "instância" de `FastAPI`
### Passo 2: crie uma "instância" de `FastAPI` { #step-2-create-a-fastapi-instance }
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
@@ -167,11 +167,11 @@ Aqui, a variável `app` será uma "instância" da classe `FastAPI`.
Este será o principal ponto de interação para criar toda a sua API.
### Passo 3: crie uma *rota*
### Passo 3: crie uma operação de rota { #step-3-create-a-path-operation }
#### Rota
#### Path { #path }
"Rota" aqui se refere à última parte da URL, começando do primeiro `/`.
"Path" aqui se refere à última parte da URL, começando do primeiro `/`.
Então, em uma URL como:
@@ -179,7 +179,7 @@ Então, em uma URL como:
https://example.com/items/foo
```
...a rota seria:
...o path seria:
```
/items/foo
@@ -187,13 +187,13 @@ https://example.com/items/foo
/// info | Informação
Uma "rota" também é comumente chamada de "endpoint".
Um "path" também é comumente chamado de "endpoint" ou de "rota".
///
Ao construir uma API, a "rota" é a principal forma de separar "preocupações" e "recursos".
Ao construir uma API, o "path" é a principal forma de separar "preocupações" e "recursos".
#### Operação
#### Operação { #operation }
"Operação" aqui se refere a um dos "métodos" HTTP.
@@ -211,7 +211,7 @@ Um dos:
* `PATCH`
* `TRACE`
No protocolo HTTP, você pode se comunicar com cada rota usando um (ou mais) desses "métodos".
No protocolo HTTP, você pode se comunicar com cada path usando um (ou mais) desses "métodos".
---
@@ -228,16 +228,16 @@ Portanto, no OpenAPI, cada um dos métodos HTTP é chamado de "operação".
Vamos chamá-los de "**operações**" também.
#### Defina um *decorador de rota*
#### Defina um decorador de operação de rota { #define-a-path-operation-decorator }
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
O `@app.get("/")` diz ao **FastAPI** que a função logo abaixo é responsável por tratar as requisições que vão para:
* a rota `/`
* usando o <abbr title="o método HTTP GET">operador <code>get</code></abbr>
* o path `/`
* usando uma <abbr title="um método HTTP GET">operação <code>get</code></abbr>
/// info | `@decorador`
/// info | Informações sobre `@decorator`
Essa sintaxe `@alguma_coisa` em Python é chamada de "decorador".
@@ -245,9 +245,9 @@ Você o coloca em cima de uma função. Como um chapéu decorativo (acho que é
Um "decorador" pega a função abaixo e faz algo com ela.
Em nosso caso, este decorador informa ao **FastAPI** que a função abaixo corresponde a **rota** `/` com uma **operação** `get`.
Em nosso caso, este decorador informa ao **FastAPI** que a função abaixo corresponde ao **path** `/` com uma **operação** `get`.
É o "**decorador de rota**".
É o "**decorador de operação de rota**".
///
@@ -276,11 +276,11 @@ Por exemplo, ao usar GraphQL, você normalmente executa todas as ações usando
///
### Passo 4: defina uma **função de rota**
### Passo 4: defina a função de operação de rota { #step-4-define-the-path-operation-function }
Esta é a nossa "**função de rota**":
Esta é a nossa "**função de operação de rota**":
* **rota**: é `/`.
* **path**: é `/`.
* **operação**: é `get`.
* **função**: é a função abaixo do "decorador" (abaixo do `@app.get("/")`).
@@ -288,9 +288,9 @@ Esta é a nossa "**função de rota**":
Esta é uma função Python.
Ela será chamada pelo **FastAPI** sempre que receber uma requisição para a URL "`/ `" usando uma operação `GET`.
Ela será chamada pelo **FastAPI** sempre que receber uma requisição para a URL "`/`" usando uma operação `GET`.
Neste caso, é uma função `assíncrona`.
Neste caso, é uma função `async`.
---
@@ -300,11 +300,11 @@ Você também pode defini-la como uma função normal em vez de `async def`:
/// note | Nota
Se você não sabe a diferença, verifique o [Async: *"Com pressa?"*](../async.md#com-pressa){.internal-link target=_blank}.
Se você não sabe a diferença, verifique o [Async: *"Com pressa?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
///
### Passo 5: retorne o conteúdo
### Passo 5: retorne o conteúdo { #step-5-return-the-content }
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
@@ -314,10 +314,10 @@ Você também pode devolver modelos Pydantic (você verá mais sobre isso mais t
Existem muitos outros objetos e modelos que serão convertidos automaticamente para JSON (incluindo ORMs, etc). Tente usar seus favoritos, é altamente provável que já sejam compatíveis.
## Recapitulando
## Recapitulando { #recap }
* Importe `FastAPI`.
* Crie uma instância do `app`.
* Coloque o **decorador que define a operação** (como `@app.get("/")`).
* Escreva uma **função para a operação da rota** (como `def root(): ...`) abaixo.
* Execute o servidor de desenvolvimento (como `uvicorn main:app --reload`).
* Escreva um **decorador de operação de rota** usando decoradores como `@app.get("/")`.
* Defina uma **função de operação de rota**; por exemplo, `def root(): ...`.
* Execute o servidor de desenvolvimento usando o comando `fastapi dev`.

View File

@@ -1,4 +1,4 @@
# Manipulação de erros
# Manipulação de erros { #handling-errors }
Há diversas situações em que você precisa notificar um erro a um cliente que está utilizando a sua API.
@@ -20,15 +20,15 @@ Os status codes na faixa dos 400 significam que houve um erro por parte do clien
Você se lembra de todos aqueles erros (e piadas) a respeito do "**404 Not Found**"?
## Use o `HTTPException`
## Use o `HTTPException` { #use-httpexception }
Para retornar ao cliente *responses* HTTP com erros, use o `HTTPException`.
### Import `HTTPException`
### Import `HTTPException` { #import-httpexception }
{* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
### Lance o `HTTPException` no seu código.
### Lance o `HTTPException` no seu código. { #raise-an-httpexception-in-your-code }
`HTTPException`, ao fundo, nada mais é do que a conjunção entre uma exceção comum do Python e informações adicionais relevantes para APIs.
@@ -42,13 +42,12 @@ Neste exemplo, quando o cliente pede, na requisição, por um item cujo ID não
{* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
### A response resultante
### A response resultante { #the-resulting-response }
Se o cliente faz uma requisição para `http://example.com/items/foo` (um `item_id` `"foo"`), esse cliente receberá um HTTP status code 200, e uma resposta JSON:
```
```JSON
{
"item": "The Foo Wrestlers"
}
@@ -71,7 +70,7 @@ Esses tipos de dados são manipulados automaticamente pelo **FastAPI** e convert
///
## Adicione headers customizados
## Adicione headers customizados { #add-custom-headers }
Há certas situações em que é bastante útil poder adicionar headers customizados no HTTP error. Exemplo disso seria adicionar headers customizados para tipos de segurança.
@@ -81,7 +80,7 @@ Mas caso você precise, para um cenário mais complexo, você pode adicionar hea
{* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
## Instalando manipuladores de exceções customizados
## Instale manipuladores de exceções customizados { #install-custom-exception-handlers }
Você pode adicionar manipuladores de exceção customizados com <a href="https://www.starlette.dev/exceptions/" class="external-link" target="_blank">a mesma seção de utilidade de exceções presentes no Starlette</a>
@@ -109,7 +108,7 @@ Você também pode usar `from starlette.requests import Request` and `from starl
///
## Sobrescreva o manipulador padrão de exceções
## Sobrescreva os manipuladores de exceções padrão { #override-the-default-exception-handlers }
**FastAPI** tem alguns manipuladores padrão de exceções.
@@ -117,12 +116,16 @@ Esses manipuladores são os responsáveis por retornar o JSON padrão de respost
Você pode sobrescrever esses manipuladores de exceção com os seus próprios manipuladores.
## Sobrescreva exceções de validação da requisição
### Sobrescreva exceções de validação da requisição { #override-request-validation-exceptions }
Quando a requisição contém dados inválidos, **FastAPI** internamente lança para o `RequestValidationError`.
E também inclui um manipulador de exceções padrão para ele.
Para sobrescrevê-lo, importe o `RequestValidationError` e use-o com o `@app.exception_handler(RequestValidationError)` para decorar o manipulador de exceções.
O manipulador de exceções receberá um `Request` e a exceção.
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *}
Se você for ao `/items/foo`, em vez de receber o JSON padrão com o erro:
@@ -150,15 +153,15 @@ path -> item_id
value is not a valid integer (type=type_error.integer)
```
### `RequestValidationError` vs `ValidationError`
#### `RequestValidationError` vs `ValidationError` { #requestvalidationerror-vs-validationerror }
/// warning | Aviso
/// warning | Atenção
Você pode pular estes detalhes técnicos caso eles não sejam importantes para você neste momento.
///
`RequestValidationError` é uma subclasse do <a href="https://docs.pydantic.dev/latest/#error-handling" class="external-link" target="_blank">`ValidationError`</a> existente no Pydantic.
`RequestValidationError` é uma subclasse do <a href="https://docs.pydantic.dev/latest/concepts/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a> existente no Pydantic.
**FastAPI** faz uso dele para que você veja o erro no seu log, caso você utilize um modelo de Pydantic em `response_model`, e seus dados tenham erro.
@@ -168,6 +171,8 @@ E assim deve ser porque seria um bug no seu código ter o `ValidationError` do P
E enquanto você conserta o bug, os clientes / usuários não deveriam ter acesso às informações internas do erro, porque, desse modo, haveria exposição de uma vulnerabilidade de segurança.
### Sobrescreva o manipulador de erro `HTTPException` { #override-the-httpexception-error-handler }
Do mesmo modo, você pode sobreescrever o `HTTPException`.
Por exemplo, você pode querer retornar uma *response* em *plain text* ao invés de um JSON para os seguintes erros:
@@ -182,12 +187,14 @@ Você pode usar `from starlette.responses import PlainTextResponse`.
///
### Use o body do `RequestValidationError`.
### Use o body do `RequestValidationError`. { #use-the-requestvalidationerror-body }
O `RequestValidationError` contém o `body` que ele recebeu de dados inválidos.
Você pode utilizá-lo enquanto desenvolve seu app para conectar o *body* e debugá-lo, e assim retorná-lo ao usuário, etc.
{* ../../docs_src/handling_errors/tutorial005.py hl[14] *}
Tente enviar um item inválido como este:
```JSON
@@ -197,7 +204,7 @@ Tente enviar um item inválido como este:
}
```
Você receberá uma *response* informando-o de que a data é inválida, e contendo o *body* recebido:
Você receberá uma *response* informando-o de que os dados são inválidos, e contendo o *body* recebido:
```JSON hl_lines="12-15"
{
@@ -218,27 +225,27 @@ Você receberá uma *response* informando-o de que a data é inválida, e conten
}
```
#### O `HTTPException` do FastAPI vs o `HTTPException` do Starlette.
#### O `HTTPException` do FastAPI vs o `HTTPException` do Starlette { #fastapis-httpexception-vs-starlettes-httpexception }
O **FastAPI** tem o seu próprio `HTTPException`.
E a classe de erro `HTTPException` do **FastAPI** herda da classe de erro do `HTTPException` do Starlette.
A diferença entre os dois é a de que o `HTTPException` do **FastAPI** permite que você adicione *headers* que serão incluídos nas *responses*.
Esses *headers* são necessários/utilizados internamente pelo OAuth 2.0 e também por outras utilidades de segurança.
A única diferença é que o `HTTPException` do **FastAPI** aceita qualquer dado que possa ser convertido em JSON para o campo `detail`, enquanto o `HTTPException` do Starlette aceita apenas strings para esse campo.
Portanto, você pode continuar lançando o `HTTPException` do **FastAPI** normalmente no seu código.
Porém, quando você registrar um manipulador de exceção, você deve registrá-lo através do `HTTPException` do Starlette.
Dessa forma, se qualquer parte do código interno, extensão ou plug-in do Starlette lançar o `HTTPException`, o seu manipulador de exceção poderá capturar esse lançamento e tratá-lo.
Dessa forma, se qualquer parte do código interno, extensão ou plug-in do Starlette lançar um `HTTPException` do Starlette, o seu manipulador poderá capturar e tratá-lo.
Neste exemplo, para poder ter ambos os `HTTPException` no mesmo código, a exceção do Starlette é renomeada para `StarletteHTTPException`:
```Python
from starlette.exceptions import HTTPException as StarletteHTTPException
```
### Re-use os manipulares de exceção do **FastAPI**
### Reutilize os manipuladores de exceção do **FastAPI** { #reuse-fastapis-exception-handlers }
Se você quer usar a exceção em conjunto com o mesmo manipulador de exceção *default* do **FastAPI**, você pode importar e re-usar esses manipuladores de exceção do `fastapi.exception_handlers`:

View File

@@ -1,8 +1,8 @@
# Modelos de Parâmetros do Cabeçalho
# Modelos de Parâmetros do Cabeçalho { #header-parameter-models }
Se você possui um grupo de **parâmetros de cabeçalho** relacionados, você pode criar um **modelo do Pydantic** para declará-los.
Isso vai lhe permitir **reusar o modelo** em **múltiplos lugares** e também declarar validações e metadadados para todos os parâmetros de uma vez. 😎
Isso vai lhe permitir **reusar o modelo** em **múltiplos lugares** e também declarar validações e metadados para todos os parâmetros de uma vez. 😎
/// note | Nota
@@ -10,7 +10,7 @@ Isso é possível desde a versão `0.115.0` do FastAPI. 🤓
///
## Parâmetros do Cabeçalho com um Modelo Pydantic
## Parâmetros do Cabeçalho com um Modelo Pydantic { #header-parameters-with-a-pydantic-model }
Declare os **parâmetros de cabeçalho** que você precisa em um **modelo do Pydantic**, e então declare o parâmetro como `Header`:
@@ -18,7 +18,7 @@ Declare os **parâmetros de cabeçalho** que você precisa em um **modelo do Pyd
O **FastAPI** irá **extrair** os dados de **cada campo** a partir dos **cabeçalhos** da requisição e te retornará o modelo do Pydantic que você definiu.
### Checando a documentação
## Checando a documentação { #check-the-docs }
Você pode ver os headers necessários na interface gráfica da documentação em `/docs`:
@@ -26,7 +26,7 @@ Você pode ver os headers necessários na interface gráfica da documentação e
<img src="/img/tutorial/header-param-models/image01.png">
</div>
### Proibindo Cabeçalhos adicionais
## Proibindo Cabeçalhos adicionais { #forbid-extra-headers }
Em alguns casos de uso especiais (provavelmente não muito comuns), você pode querer **restringir** os cabeçalhos que você quer receber.
@@ -51,6 +51,22 @@ Por exemplo, se o cliente tentar enviar um cabeçalho `tool` com o valor `plumbu
}
```
## Resumo
## Desativar conversão de underscores { #disable-convert-underscores }
Da mesma forma que com parâmetros de cabeçalho normais, quando você tem caracteres de sublinhado nos nomes dos parâmetros, eles são **automaticamente convertidos em hifens**.
Por exemplo, se você tem um parâmetro de cabeçalho `save_data` no código, o cabeçalho HTTP esperado será `save-data`, e ele aparecerá assim na documentação.
Se por algum motivo você precisar desativar essa conversão automática, também poderá fazê-lo para modelos do Pydantic para parâmetros de cabeçalho.
{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *}
/// warning | Atenção
Antes de definir `convert_underscores` como `False`, tenha em mente que alguns proxies e servidores HTTP não permitem o uso de cabeçalhos com sublinhados.
///
## Resumo { #summary }
Você pode utilizar **modelos do Pydantic** para declarar **cabeçalhos** no **FastAPI**. 😎

View File

@@ -1,20 +1,20 @@
# Parâmetros de Cabeçalho
# Parâmetros de Cabeçalho { #header-parameters }
Você pode definir parâmetros de Cabeçalho da mesma maneira que define paramêtros com `Query`, `Path` e `Cookie`.
## importe `Header`
## Importe `Header` { #import-header }
Primeiro importe `Header`:
{* ../../docs_src/header_params/tutorial001_py310.py hl[1] *}
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *}
## Declare parâmetros de `Header`
## Declare parâmetros de `Header` { #declare-header-parameters }
Então declare os paramêtros de cabeçalho usando a mesma estrutura que em `Path`, `Query` e `Cookie`.
O primeiro valor é o valor padrão, você pode passar todas as validações adicionais ou parâmetros de anotação:
{* ../../docs_src/header_params/tutorial001_py310.py hl[7] *}
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *}
/// note | Detalhes Técnicos
@@ -24,13 +24,13 @@ Mas lembre-se que quando você importa `Query`, `Path`, `Header`, e outras de `f
///
/// info
/// info | Informação
Para declarar headers, você precisa usar `Header`, caso contrário, os parâmetros seriam interpretados como parâmetros de consulta.
///
## Conversão automática
## Conversão automática { #automatic-conversion }
`Header` tem algumas funcionalidades a mais em relação a `Path`, `Query` e `Cookie`.
@@ -46,15 +46,15 @@ Portanto, você pode usar `user_agent` como faria normalmente no código Python,
Se por algum motivo você precisar desabilitar a conversão automática de sublinhados para hífens, defina o parâmetro `convert_underscores` de `Header` para `False`:
{* ../../docs_src/header_params/tutorial002_py310.py hl[8] *}
{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *}
/// warning | Aviso
/// warning | Atenção
Antes de definir `convert_underscores` como `False`, lembre-se de que alguns proxies e servidores HTTP não permitem o uso de cabeçalhos com sublinhados.
///
## Cabeçalhos duplicados
## Cabeçalhos duplicados { #duplicate-headers }
É possível receber cabeçalhos duplicados. Isso significa, o mesmo cabeçalho com vários valores.
@@ -64,9 +64,9 @@ Você receberá todos os valores do cabeçalho duplicado como uma `list` Python.
Por exemplo, para declarar um cabeçalho de `X-Token` que pode aparecer mais de uma vez, você pode escrever:
{* ../../docs_src/header_params/tutorial003_py310.py hl[7] *}
{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *}
Se você se comunicar com essa *operação de caminho* enviando dois cabeçalhos HTTP como:
Se você se comunicar com essa *operação de rota* enviando dois cabeçalhos HTTP como:
```
X-Token: foo
@@ -84,8 +84,8 @@ A resposta seria como:
}
```
## Recapitulando
## Recapitulando { #recap }
Declare cabeçalhos com `Header`, usando o mesmo padrão comum que utiliza-se em `Query`, `Path` e `Cookie`.
E não se preocupe com sublinhados em suas variáveis, FastAPI cuidará da conversão deles.
E não se preocupe com sublinhados em suas variáveis, **FastAPI** cuidará da conversão deles.

View File

@@ -1,4 +1,4 @@
# Tutorial - Guia de Usuário
# Tutorial - Guia de Usuário { #tutorial-user-guide }
Esse tutorial mostra como usar o **FastAPI** com a maior parte de seus recursos, passo a passo.
@@ -6,11 +6,11 @@ Cada seção constrói, gradualmente, sobre as anteriores, mas sua estrutura sã
Ele também foi construído para servir como uma referência futura, então você pode voltar e ver exatamente o que você precisa.
## Rode o código
## Rode o código { #run-the-code }
Todos os blocos de código podem ser copiados e utilizados diretamente (eles são, na verdade, arquivos Python testados).
Para rodar qualquer um dos exemplos, copie o codigo para um arquivo `main.py`, e inicie o `uvivorn` com:
Para rodar qualquer um dos exemplos, copie o código para um arquivo `main.py`, e inicie o `fastapi dev` com:
<div class="termy">
@@ -54,15 +54,15 @@ $ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid
É **ALTAMENTE recomendado** que você escreva ou copie o código, edite-o e rode-o localmente.
Usá-lo em seu editor é o que realmente te mostra os benefícios do FastAPI, ver quão pouco código você tem que escrever, todas as conferências de tipo, auto completações etc.
Usá-lo em seu editor é o que realmente te mostra os benefícios do FastAPI, ver quão pouco código você tem que escrever, todas as conferências de tipo, preenchimento automático, etc.
---
## Instale o FastAPI
## Instale o FastAPI { #install-fastapi }
O primeiro passo é instalar o FastAPI.
Para o tutorial, você deve querer instalá-lo com todas as dependências e recursos opicionais.
Certifique-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então **instalar o FastAPI**:
<div class="termy">
@@ -76,17 +76,19 @@ $ pip install "fastapi[standard]"
/// note | Nota
Quando você instala com pip install "fastapi[standard]", ele vem com algumas dependências opcionais padrão.
Quando você instala com `pip install "fastapi[standard]"`, ele vem com algumas dependências opcionais padrão, incluindo `fastapi-cloud-cli`, que permite fazer deploy na <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>.
Se você não quiser ter essas dependências opcionais, pode instalar pip install fastapi em vez disso.
Se você não quiser ter essas dependências opcionais, pode instalar `pip install fastapi` em vez disso.
Se você quiser instalar as dependências padrão, mas sem o `fastapi-cloud-cli`, você pode instalar com `pip install "fastapi[standard-no-fastapi-cloud-cli]"`.
///
## Guia Avançado de Usuário
## Guia Avançado de Usuário { #advanced-user-guide }
Há também um **Guia Avançado de Usuário** que você pode ler após esse **Tutorial - Guia de Usuário**.
O **Guia Avançado de Usuário** constrói sobre esse, usa os mesmos conceitos e te ensina alguns recursos extras.
O **Guia Avançado de Usuário** constrói sobre esse, usa os mesmos conceitos e te ensina algumas funcionalidades extras.
Mas você deveria ler primeiro o **Tutorial - Guia de Usuário** (que você está lendo agora).

View File

@@ -1,8 +1,8 @@
# Metadados e Urls de Documentos
# Metadados e Urls de Documentos { #metadata-and-docs-urls }
Você pode personalizar várias configurações de metadados na sua aplicação **FastAPI**.
## Metadados para API
## Metadados para API { #metadata-for-api }
Você pode definir os seguintes campos que são usados na especificação OpenAPI e nas interfaces automáticas de documentação da API:
@@ -30,7 +30,7 @@ Com essa configuração, a documentação automática da API se pareceria com:
<img src="/img/tutorial/metadata/image01.png">
## Identificador de Licença
## Identificador de Licença { #license-identifier }
Desde o OpenAPI 3.1.0 e FastAPI 0.99.0, você também pode definir o license_info com um identifier em vez de uma url.
@@ -38,7 +38,7 @@ Por exemplo:
{* ../../docs_src/metadata/tutorial001_1.py hl[31] *}
## Metadados para tags
## Metadados para tags { #metadata-for-tags }
Você também pode adicionar metadados adicionais para as diferentes tags usadas para agrupar suas operações de rota com o parâmetro `openapi_tags`.
@@ -52,7 +52,7 @@ Cada dicionário pode conter:
* `description`: uma `str` com uma breve descrição da documentação externa.
* `url` (**obrigatório**): uma `str` com a URL da documentação externa.
### Criar Metadados para tags
### Criar Metadados para tags { #create-metadata-for-tags }
Vamos tentar isso em um exemplo com tags para `users` e `items`.
@@ -68,31 +68,31 @@ Você não precisa adicionar metadados para todas as tags que você usa.
///
### Use suas tags
### Use suas tags { #use-your-tags }
Use o parâmetro `tags` com suas *operações de rota* (e `APIRouter`s) para atribuí-los a diferentes tags:
{* ../../docs_src/metadata/tutorial004.py hl[21,26] *}
/// info | Informação
/// info | Informação
Leia mais sobre tags em [Configuração de Operação de Caminho](path-operation-configuration.md#tags){.internal-link target=_blank}.
Leia mais sobre tags em [Configuração de operação de rota](path-operation-configuration.md#tags){.internal-link target=_blank}.
///
### Cheque os documentos
### Cheque os documentos { #check-the-docs }
Agora, se você verificar a documentação, ela exibirá todos os metadados adicionais:
<img src="/img/tutorial/metadata/image02.png">
### Ordem das tags
### Ordem das tags { #order-of-tags }
A ordem de cada dicionário de metadados de tag também define a ordem exibida na interface de documentação.
Por exemplo, embora `users` apareça após `items` em ordem alfabética, ele é exibido antes deles, porque adicionamos seus metadados como o primeiro dicionário na lista.
## URL da OpenAPI
## URL da OpenAPI { #openapi-url }
Por padrão, o esquema OpenAPI é servido em `/openapi.json`.
@@ -104,7 +104,7 @@ Por exemplo, para defini-lo para ser servido em `/api/v1/openapi.json`:
Se você quiser desativar completamente o esquema OpenAPI, pode definir `openapi_url=None`, o que também desativará as interfaces de documentação que o utilizam.
## URLs da Documentação
## URLs da Documentação { #docs-urls }
Você pode configurar as duas interfaces de documentação incluídas:

View File

@@ -1,4 +1,4 @@
# Middleware
# Middleware { #middleware }
Você pode adicionar middleware à suas aplicações **FastAPI**.
@@ -11,15 +11,15 @@ Um "middleware" é uma função que manipula cada **requisição** antes de ser
* Ele pode fazer algo com essa **resposta** ou executar qualquer código necessário.
* Então ele retorna a **resposta**.
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Se você tiver dependências com `yield`, o código de saída será executado *depois* do middleware.
Se houver alguma tarefa em segundo plano (documentada posteriormente), ela será executada *depois* de todo o middleware.
Se houver alguma tarefa em segundo plano (abordada na seção [Tarefas em segundo plano](background-tasks.md){.internal-link target=_blank}, que você verá mais adiante), ela será executada *depois* de todo o middleware.
///
## Criar um middleware
## Criar um middleware { #create-a-middleware }
Para criar um middleware, use o decorador `@app.middleware("http")` logo acima de uma função.
@@ -35,13 +35,13 @@ A função middleware recebe:
/// tip | Dica
Tenha em mente que cabeçalhos proprietários personalizados podem ser adicionados <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">usando o prefixo 'X-'</a>.
Tenha em mente que cabeçalhos proprietários personalizados podem ser adicionados <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">usando o prefixo `X-`</a>.
Mas se você tiver cabeçalhos personalizados desejando que um cliente em um navegador esteja apto a ver, você precisa adicioná-los às suas configurações CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) usando o parâmetro `expose_headers` documentado em <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">Documentos CORS da Starlette</a>.
///
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Você também pode usar `from starlette.requests import Request`.
@@ -49,7 +49,7 @@ Você também pode usar `from starlette.requests import Request`.
///
### Antes e depois da `response`
### Antes e depois da `response` { #before-and-after-the-response }
Você pode adicionar código para ser executado com a `request`, antes que qualquer *operação de rota* o receba.
@@ -59,7 +59,36 @@ Por exemplo, você pode adicionar um cabeçalho personalizado `X-Process-Time` c
{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *}
## Outros middlewares
/// tip | Dica
Aqui usamos <a href="https://docs.python.org/3/library/time.html#time.perf_counter" class="external-link" target="_blank">`time.perf_counter()`</a> em vez de `time.time()` porque ele pode ser mais preciso para esses casos de uso. 🤓
///
## Ordem de execução de múltiplos middlewares { #multiple-middleware-execution-order }
Quando você adiciona múltiplos middlewares usando o decorador `@app.middleware()` ou o método `app.add_middleware()`, cada novo middleware envolve a aplicação, formando uma pilha. O último middleware adicionado é o mais externo, e o primeiro é o mais interno.
No caminho da requisição, o middleware mais externo roda primeiro.
No caminho da resposta, ele roda por último.
Por exemplo:
```Python
app.add_middleware(MiddlewareA)
app.add_middleware(MiddlewareB)
```
Isso resulta na seguinte ordem de execução:
* **Requisição**: MiddlewareB → MiddlewareA → rota
* **Resposta**: rota → MiddlewareA → MiddlewareB
Esse comportamento de empilhamento garante que os middlewares sejam executados em uma ordem previsível e controlável.
## Outros middlewares { #other-middlewares }
Mais tarde, você pode ler mais sobre outros middlewares no [Guia do usuário avançado: Middleware avançado](../advanced/middleware.md){.internal-link target=_blank}.

View File

@@ -1,14 +1,14 @@
# Configuração da Operação de Rota
# Configuração da Operação de Rota { #path-operation-configuration }
Existem vários parâmetros que você pode passar para o seu *decorador de operação de rota* para configurá-lo.
/// warning | Aviso
/// warning | Atenção
Observe que esses parâmetros são passados diretamente para o *decorador de operação de rota*, não para a sua *função de operação de rota*.
///
## Código de Status da Resposta
## Código de Status da Resposta { #response-status-code }
Você pode definir o `status_code` (HTTP) para ser usado na resposta da sua *operação de rota*.
@@ -16,7 +16,7 @@ Você pode passar diretamente o código `int`, como `404`.
Mas se você não se lembrar o que cada código numérico significa, pode usar as constantes de atalho em `status`:
{* ../../docs_src/path_operation_configuration/tutorial001.py hl[3,17] *}
{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *}
Esse código de status será usado na resposta e será adicionado ao esquema OpenAPI.
@@ -28,17 +28,17 @@ Você também poderia usar `from starlette import status`.
///
## Tags
## Tags { #tags }
Você pode adicionar tags para sua *operação de rota*, passe o parâmetro `tags` com uma `list` de `str` (comumente apenas um `str`):
{* ../../docs_src/path_operation_configuration/tutorial002.py hl[17,22,27] *}
{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *}
Eles serão adicionados ao esquema OpenAPI e usados pelas interfaces de documentação automática:
<img src="/img/tutorial/path-operation-configuration/image01.png">
### Tags com Enums
### Tags com Enums { #tags-with-enums }
Se você tem uma grande aplicação, você pode acabar acumulando **várias tags**, e você gostaria de ter certeza de que você sempre usa a **mesma tag** para *operações de rota* relacionadas.
@@ -48,30 +48,29 @@ Nestes casos, pode fazer sentido armazenar as tags em um `Enum`.
{* ../../docs_src/path_operation_configuration/tutorial002b.py hl[1,8:10,13,18] *}
## Resumo e descrição
## Resumo e descrição { #summary-and-description }
Você pode adicionar um `summary` e uma `description`:
{* ../../docs_src/path_operation_configuration/tutorial003.py hl[20:21] *}
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *}
## Descrição do docstring
## Descrição do docstring { #description-from-docstring }
Como as descrições tendem a ser longas e cobrir várias linhas, você pode declarar a descrição da *operação de rota* na <abbr title="uma string de várias linhas como a primeira expressão dentro de uma função (não atribuída a nenhuma variável) usada para documentação">docstring</abbr> da função e o **FastAPI** irá lê-la de lá.
Você pode escrever <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> na docstring, ele será interpretado e exibido corretamente (levando em conta a indentação da docstring).
{* ../../docs_src/path_operation_configuration/tutorial004.py hl[19:27] *}
{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *}
Ela será usada nas documentações interativas:
<img src="/img/tutorial/path-operation-configuration/image02.png">
## Descrição da resposta
## Descrição da resposta { #response-description }
Você pode especificar a descrição da resposta com o parâmetro `response_description`:
{* ../../docs_src/path_operation_configuration/tutorial005.py hl[21] *}
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *}
/// info | Informação
@@ -79,7 +78,7 @@ Note que `response_description` se refere especificamente à resposta, a `descri
///
/// check
/// check | Verifique
OpenAPI especifica que cada *operação de rota* requer uma descrição de resposta.
@@ -89,7 +88,7 @@ Então, se você não fornecer uma, o **FastAPI** irá gerar automaticamente uma
<img src="/img/tutorial/path-operation-configuration/image03.png">
## Depreciar uma *operação de rota*
## Descontinuar uma *operação de rota* { #deprecate-a-path-operation }
Se você precisar marcar uma *operação de rota* como <abbr title="obsoleta, recomendada não usá-la">descontinuada</abbr>, mas sem removê-la, passe o parâmetro `deprecated`:
@@ -103,6 +102,6 @@ Verifique como *operações de rota* descontinuadas e não descontinuadas se par
<img src="/img/tutorial/path-operation-configuration/image05.png">
## Resumindo
## Resumindo { #recap }
Você pode configurar e adicionar metadados para suas *operações de rota* facilmente passando parâmetros para os *decoradores de operação de rota*.

View File

@@ -1,91 +1,128 @@
# Parâmetros da Rota e Validações Numéricas
# Parâmetros de path e validações numéricas { #path-parameters-and-numeric-validations }
Do mesmo modo que você pode declarar mais validações e metadados para parâmetros de consulta com `Query`, você pode declarar os mesmos tipos de validações e metadados para parâmetros de rota com `Path`.
Da mesma forma que você pode declarar mais validações e metadados para parâmetros de consulta com `Query`, você pode declarar o mesmo tipo de validações e metadados para parâmetros de path com `Path`.
## Importe `Path`
## Importe `Path` { #import-path }
Primeiro, importe `Path` de `fastapi`:
Primeiro, importe `Path` de `fastapi`, e importe `Annotated`:
{* ../../docs_src/path_params_numeric_validations/tutorial001_py310.py hl[1] *}
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *}
## Declare metadados
/// info | Informação
Você pode declarar todos os parâmetros da mesma maneira que na `Query`.
O FastAPI adicionou suporte a `Annotated` (e passou a recomendá-lo) na versão 0.95.0.
Por exemplo para declarar um valor de metadado `title` para o parâmetro de rota `item_id` você pode digitar:
Se você tiver uma versão mais antiga, verá erros ao tentar usar `Annotated`.
{* ../../docs_src/path_params_numeric_validations/tutorial001_py310.py hl[8] *}
/// note | Nota
Um parâmetro de rota é sempre obrigatório, como se fizesse parte da rota.
Então, você deve declará-lo com `...` para marcá-lo como obrigatório.
Mesmo que você declare-o como `None` ou defina um valor padrão, isso não teria efeito algum, o parâmetro ainda seria obrigatório.
Certifique-se de [Atualizar a versão do FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} para pelo menos 0.95.1 antes de usar `Annotated`.
///
## Ordene os parâmetros de acordo com sua necessidade
## Declare metadados { #declare-metadata }
Suponha que você queira declarar o parâmetro de consulta `q` como uma `str` obrigatória.
Você pode declarar todos os mesmos parâmetros que em `Query`.
E você não precisa declarar mais nada em relação a este parâmetro, então você não precisa necessariamente usar `Query`.
Por exemplo, para declarar um valor de metadado `title` para o parâmetro de path `item_id` você pode digitar:
Mas você ainda precisa usar `Path` para o parâmetro de rota `item_id`.
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *}
O Python irá acusar se você colocar um elemento com um valor padrão definido antes de outro que não tenha um valor padrão.
/// note | Nota
Mas você pode reordená-los, colocando primeiro o elemento sem o valor padrão (o parâmetro de consulta `q`).
Um parâmetro de path é sempre obrigatório, pois precisa fazer parte do path. Mesmo que você o declare como `None` ou defina um valor padrão, isso não afetaria nada, ele ainda seria sempre obrigatório.
Isso não faz diferença para o **FastAPI**. Ele vai detectar os parâmetros pelos seus nomes, tipos e definições padrão (`Query`, `Path`, etc), sem se importar com a ordem.
///
## Ordene os parâmetros de acordo com sua necessidade { #order-the-parameters-as-you-need }
/// tip | Dica
Isso provavelmente não é tão importante ou necessário se você usar `Annotated`.
///
Vamos supor que você queira declarar o parâmetro de consulta `q` como uma `str` obrigatória.
E você não precisa declarar mais nada para esse parâmetro, então você realmente não precisa usar `Query`.
Mas você ainda precisa usar `Path` para o parâmetro de path `item_id`. E você não quer usar `Annotated` por algum motivo.
O Python vai reclamar se você colocar um valor com “padrão” antes de um valor que não tem “padrão”.
Mas você pode reordená-los e colocar primeiro o valor sem padrão (o parâmetro de consulta `q`).
Isso não faz diferença para o **FastAPI**. Ele vai detectar os parâmetros pelos seus nomes, tipos e declarações de padrão (`Query`, `Path`, etc.), sem se importar com a ordem.
Então, você pode declarar sua função assim:
{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
## Ordene os parâmetros de a acordo com sua necessidade, truques
Mas tenha em mente que, se você usar `Annotated`, você não terá esse problema, não fará diferença, pois você não está usando valores padrão de parâmetros de função para `Query()` ou `Path()`.
Se você quiser declarar o parâmetro de consulta `q` sem um `Query` nem um valor padrão, e o parâmetro de rota `item_id` usando `Path`, e definí-los em uma ordem diferente, Python tem um pequeno truque na sintaxe para isso.
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
## Ordene os parâmetros de acordo com sua necessidade, truques { #order-the-parameters-as-you-need-tricks }
/// tip | Dica
Isso provavelmente não é tão importante ou necessário se você usar `Annotated`.
///
Aqui vai um pequeno truque que pode ser útil, mas você não vai precisar dele com frequência.
Se você quiser:
* declarar o parâmetro de consulta `q` sem um `Query` nem qualquer valor padrão
* declarar o parâmetro de path `item_id` usando `Path`
* tê-los em uma ordem diferente
* não usar `Annotated`
...o Python tem uma pequena sintaxe especial para isso.
Passe `*`, como o primeiro parâmetro da função.
O Python não vai fazer nada com esse `*`, mas ele vai saber que a partir dali os parâmetros seguintes deverão ser chamados argumentos nomeados (pares chave-valor), também conhecidos como <abbr title="Do inglês: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Mesmo que eles não possuam um valor padrão.
O Python não fará nada com esse `*`, mas saberá que todos os parâmetros seguintes devem ser chamados como argumentos nomeados (pares chave-valor), também conhecidos como <abbr title="Do inglês: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Mesmo que eles não tenham um valor padrão.
{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
## Validações numéricas: maior que ou igual
### Melhor com `Annotated` { #better-with-annotated }
Com `Query` e `Path` (e outras que você verá mais tarde) você pode declarar restrições numéricas.
Tenha em mente que, se você usar `Annotated`, como você não está usando valores padrão de parâmetros de função, você não terá esse problema e provavelmente não precisará usar `*`.
Aqui, com `ge=1`, `item_id` precisará ser um número inteiro maior que ("`g`reater than") ou igual ("`e`qual") a 1.
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial004.py hl[8] *}
## Validações numéricas: maior que ou igual { #number-validations-greater-than-or-equal }
## Validações numéricas: maior que e menor que ou igual
Com `Query` e `Path` (e outras que você verá depois) você pode declarar restrições numéricas.
O mesmo se aplica para:
Aqui, com `ge=1`, `item_id` precisará ser um número inteiro “`g`reater than or `e`qual” a `1`.
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
## Validações numéricas: maior que e menor que ou igual { #number-validations-greater-than-and-less-than-or-equal }
O mesmo se aplica a:
* `gt`: maior que (`g`reater `t`han)
* `le`: menor que ou igual (`l`ess than or `e`qual)
{* ../../docs_src/path_params_numeric_validations/tutorial005.py hl[9] *}
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
## Validações numéricas: valores do tipo float, maior que e menor que
## Validações numéricas: floats, maior que e menor que { #number-validations-floats-greater-than-and-less-than }
Validações numéricas também funcionam para valores do tipo `float`.
Validações numéricas também funcionam para valores `float`.
Aqui é onde se torna importante a possibilidade de declarar <abbr title="greater than"><code>gt</code></abbr> e não apenas <abbr title="greater than or equal"><code>ge</code></abbr>. Com isso você pode especificar, por exemplo, que um valor deve ser maior que `0`, ainda que seja menor que `1`.
Aqui é onde se torna importante poder declarar <abbr title="greater than maior que"><code>gt</code></abbr> e não apenas <abbr title="greater than or equal maior que ou igual"><code>ge</code></abbr>. Com isso você pode exigir, por exemplo, que um valor seja maior que `0`, mesmo que seja menor que `1`.
Assim, `0.5` seria um valor válido. Mas `0.0` ou `0` não seria.
Assim, `0.5` seria um valor válido. Mas `0.0` ou `0` não seriam.
E o mesmo para <abbr title="less than"><code>lt</code></abbr>.
E o mesmo para <abbr title="less than menor que"><code>lt</code></abbr>.
{* ../../docs_src/path_params_numeric_validations/tutorial006.py hl[11] *}
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
## Recapitulando
## Recapitulando { #recap }
Com `Query`, `Path` (e outras que você ainda não viu) você pode declarar metadados e validações de texto do mesmo modo que com [Parâmetros de consulta e validações de texto](query-params-str-validations.md){.internal-link target=_blank}.
Com `Query`, `Path` (e outras que você ainda não viu) você pode declarar metadados e validações de string do mesmo modo que em [Parâmetros de consulta e validações de string](query-params-str-validations.md){.internal-link target=_blank}.
E você também pode declarar validações numéricas:
@@ -96,7 +133,7 @@ E você também pode declarar validações numéricas:
/// info | Informação
`Query`, `Path` e outras classes que você verá a frente são subclasses de uma classe comum `Param`.
`Query`, `Path` e outras classes que você verá depois são subclasses de uma classe comum `Param`.
Todas elas compartilham os mesmos parâmetros para validação adicional e metadados que você viu.
@@ -106,12 +143,12 @@ Todas elas compartilham os mesmos parâmetros para validação adicional e metad
Quando você importa `Query`, `Path` e outras de `fastapi`, elas são na verdade funções.
Que quando chamadas, retornam instâncias de classes de mesmo nome.
Que, quando chamadas, retornam instâncias de classes de mesmo nome.
Então, você importa `Query`, que é uma função. E quando você a chama, ela retorna uma instância de uma classe também chamada `Query`.
Estas funções são assim (ao invés de apenas usar as classes diretamente) para que seu editor não acuse erros sobre seus tipos.
Essas funções existem (em vez de usar diretamente as classes) para que seu editor não marque erros sobre seus tipos.
Dessa maneira você pode user seu editor e ferramentas de desenvolvimento sem precisar adicionar configurações customizadas para ignorar estes erros.
Dessa forma, você pode usar seu editor e ferramentas de codificação normais sem precisar adicionar configurações personalizadas para desconsiderar esses erros.
///

View File

@@ -1,207 +1,188 @@
# Parâmetros da rota da URL
# Parâmetros de path { #path-parameters }
Você pode declarar os "parâmetros" ou "variáveis" com a mesma sintaxe utilizada pelo formato de strings do Python:
Você pode declarar "parâmetros" ou "variáveis" de path com a mesma sintaxe usada por strings de formatação do Python:
{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
O valor do parâmetro que foi passado à `item_id` será passado para a sua função como o argumento `item_id`.
O valor do parâmetro de path `item_id` será passado para a sua função como o argumento `item_id`.
Então, se você rodar este exemplo e for até <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, você verá a seguinte resposta:
Então, se você executar este exemplo e acessar <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, você verá uma resposta:
```JSON
{"item_id":"foo"}
```
## Parâmetros da rota com tipos
## Parâmetros de path com tipos { #path-parameters-with-types }
Você pode declarar o tipo de um parâmetro na função usando as anotações padrões do Python:
Você pode declarar o tipo de um parâmetro de path na função, usando as anotações de tipo padrão do Python:
{* ../../docs_src/path_params/tutorial002.py hl[7] *}
Nesse caso, `item_id` está sendo declarado como um `int`.
Neste caso, `item_id` é declarado como um `int`.
/// check | Verifique
Isso fornecerá suporte do editor dentro da sua função, com verificações de erros, preenchimento automático, etc.
///
Isso vai dar à você suporte do seu editor dentro das funções, com verificações de erros, autocompletar, etc.
## Dados <abbr title="também conhecido como: serialização, parsing, marshalling">conversão</abbr> { #data-conversion }
## Conversão de <abbr title="também conhecido como: serialização, parsing, marshalling">dados</abbr>
Se você rodar esse exemplo e abrir o seu navegador em <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, você verá a seguinte resposta:
Se você executar este exemplo e abrir seu navegador em <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, você verá uma resposta:
```JSON
{"item_id":3}
```
/// check | Verifique
Perceba que o valor que sua função recebeu (e retornou) é `3`, como um `int` do Python, não uma string `"3"`.
Então, com essa declaração de tipo, o **FastAPI** fornece <abbr title="convertendo a string que vem de um request HTTP em dados Python">"parsing"</abbr> automático do request.
///
Observe que o valor recebido pela função (e também retornado por ela) é `3`, como um Python `int`, não como uma string `"3"`.
## Validação de dados { #data-validation }
Então, com essa declaração de tipo, o **FastAPI** pra você um <abbr title="convertendo a string que veio do request HTTP em um dado Python">"parsing"</abbr> automático no request .
## Validação de dados
Mas se você abrir o seu navegador em <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, você verá um belo erro HTTP:
Mas se você for no navegador para <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, verá um bom erro HTTP:
```JSON
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
"detail": [
{
"type": "int_parsing",
"loc": [
"path",
"item_id"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "foo"
}
]
}
```
devido ao parâmetro da rota `item_id` ter um valor `"foo"`, que não é um `int`.
porque o parâmetro de path `item_id` tinha o valor `"foo"`, que não é um `int`.
O mesmo erro apareceria se você tivesse fornecido um `float` ao invés de um `int`, como em: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
O mesmo erro apareceria se você fornecesse um `float` em vez de um `int`, como em: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
/// check | Verifique
Então, com a mesma declaração de tipo do Python, o **FastAPI** fornece validação de dados.
Observe que o erro também declara claramente exatamente o ponto onde a validação não passou.
Isso é incrivelmente útil ao desenvolver e depurar código que interage com sua API.
///
Então, com a mesma declaração de tipo do Python, o **FastAPI** dá pra você validação de dados.
## Documentação { #documentation }
Observe que o erro também mostra claramente o ponto exato onde a validação não passou.
Isso é incrivelmente útil enquanto se desenvolve e debuga o código que interage com a sua API.
## Documentação
Quando você abrir o seu navegador em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, você verá de forma automática e interativa a documentação da API como:
E quando você abrir seu navegador em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, você verá documentação automática, interativa, da API como:
<img src="/img/tutorial/path-params/image01.png">
/// check | Verifique
Novamente, apenas com a mesma declaração de tipo do Python, o **FastAPI** fornece documentação automática e interativa (integrando o Swagger UI).
Observe que o parâmetro de path está declarado como um inteiro.
///
Novamente, apenas com a mesma declaração de tipo do Python, o **FastAPI** te dá de forma automática e interativa a documentação (integrada com o Swagger UI).
## Benefícios baseados em padrões, documentação alternativa { #standards-based-benefits-alternative-documentation }
Veja que o parâmetro de rota está declarado como sendo um inteiro (int).
E como o schema gerado é do padrão <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a>, existem muitas ferramentas compatíveis.
## Beneficios baseados em padrões, documentação alternativa
Devido ao schema gerado ser o padrão do <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a>, existem muitas ferramentas compatíveis.
Por esse motivo, o próprio **FastAPI** fornece uma API alternativa para documentação (utilizando ReDoc), que você pode acessar em <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
Por causa disso, o próprio **FastAPI** fornece uma documentação alternativa da API (usando ReDoc), que você pode acessar em <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
<img src="/img/tutorial/path-params/image02.png">
Da mesma forma, existem muitas ferramentas compatíveis. Incluindo ferramentas de geração de código para muitas linguagens.
## Pydantic
## Pydantic { #pydantic }
Toda a validação de dados é feita por baixo dos panos pelo <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, então você tem todos os benefícios disso. E assim você sabe que está em boas mãos.
Toda a validação de dados é realizada nos bastidores pelo <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, então você recebe todos os benefícios disso. E você sabe que está em boas mãos.
Você pode usar as mesmas declarações de tipo com `str`, `float`, `bool` e muitos outros tipos complexos de dados.
Você pode usar as mesmas declarações de tipo com `str`, `float`, `bool` e muitos outros tipos de dados complexos.
Vamos explorar muitos destes tipos nos próximos capítulos do tutorial.
Vários deles são explorados nos próximos capítulos do tutorial.
## A ordem importa
## A ordem importa { #order-matters }
Quando você cria operações de rota, você pode se deparar com situações onde você pode ter uma rota fixa.
Ao criar *operações de rota*, você pode encontrar situações em que tem um path fixo.
Algo como `/users/me` por exemplo, digamos que essa rota seja utilizada para pegar dados sobre o usuário atual.
Como `/users/me`, digamos que seja para obter dados sobre o usuário atual.
E então você pode ter também uma rota `/users/{user_id}` para pegar dados sobre um usuário específico associado a um ID de usuário.
E então você também pode ter um path `/users/{user_id}` para obter dados sobre um usuário específico por algum ID de usuário.
Porque as operações de rota são avaliadas em ordem, você precisa ter certeza que a rota para `/users/me` está sendo declarado antes da rota `/users/{user_id}`:
Como as *operações de rota* são avaliadas em ordem, você precisa garantir que o path para `/users/me` seja declarado antes do de `/users/{user_id}`:
{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
Caso contrário, a rota para `/users/{user_id}` coincidiria também para `/users/me`, "pensando" que estaria recebendo o parâmetro `user_id` com o valor de `"me"`.
Caso contrário, o path para `/users/{user_id}` também corresponderia a `/users/me`, "achando" que está recebendo um parâmetro `user_id` com o valor `"me"`.
## Valores predefinidos
Da mesma forma, você não pode redefinir uma operação de rota:
Se você tem uma operação de rota que recebe um parâmetro da rota, mas que você queira que esses valores possíveis do parâmetro da rota sejam predefinidos, você pode usar <abbr title="Enumeration">`Enum`</abbr> padrão do Python.
{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *}
### Criando uma classe `Enum`
A primeira sempre será usada, já que o path corresponde primeiro.
Importe `Enum` e crie uma sub-classe que herde de `str` e de `Enum`.
## Valores predefinidos { #predefined-values }
Por herdar de `str` a documentação da API vai ser capaz de saber que os valores devem ser do tipo `string` e assim ser capaz de mostrar eles corretamente.
Se você tem uma *operação de rota* que recebe um *parâmetro de path*, mas quer que os valores válidos possíveis do *parâmetro de path* sejam predefinidos, você pode usar um <abbr title="Enumeration">`Enum`</abbr> padrão do Python.
Assim, crie atributos de classe com valores fixos, que serão os valores válidos disponíveis.
### Crie uma classe `Enum` { #create-an-enum-class }
Importe `Enum` e crie uma subclasse que herde de `str` e de `Enum`.
Ao herdar de `str`, a documentação da API saberá que os valores devem ser do tipo `string` e poderá renderizá-los corretamente.
Em seguida, crie atributos de classe com valores fixos, que serão os valores válidos disponíveis:
{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
/// info | informação
/// info | Informação
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerations (ou enums) estão disponíveis no Python</a> desde a versão 3.4.
///
/// tip | Dica
Se você está se perguntando, "AlexNet", "ResNet" e "LeNet" são apenas nomes de <abbr title="Tecnicamente, arquiteturas de modelos de Deep Learning">modelos</abbr> de Aprendizado de Máquina.
///
Se você está se perguntando, "AlexNet", "ResNet", e "LeNet" são apenas nomes de <abbr title="técnicamente, modelos de arquitetura de Deep Learning">modelos</abbr> de Machine Learning (aprendizado de máquina).
### Declare um parâmetro de path { #declare-a-path-parameter }
### Declare um *parâmetro de rota*
Logo, crie um *parâmetro de rota* com anotações de tipo usando a classe enum que você criou (`ModelName`):
Em seguida, crie um *parâmetro de path* com anotação de tipo usando a classe enum que você criou (`ModelName`):
{* ../../docs_src/path_params/tutorial005.py hl[16] *}
### Revise a documentação
### Verifique a documentação { #check-the-docs }
Visto que os valores disponíveis para o parâmetro da rota estão predefinidos, a documentação interativa pode mostrar esses valores de uma forma bem legal:
Como os valores disponíveis para o *parâmetro de path* são predefinidos, a documentação interativa pode mostrá-los de forma agradável:
<img src="/img/tutorial/path-params/image03.png">
### Trabalhando com os *enumeration* do Python
### Trabalhando com *enumerações* do Python { #working-with-python-enumerations }
O valor do *parâmetro da rota* será um *membro de enumeration*.
O valor do *parâmetro de path* será um *membro de enumeração*.
#### Compare *membros de enumeration*
#### Compare membros de enumeração { #compare-enumeration-members }
Você pode comparar eles com o *membro de enumeration* no enum `ModelName` que você criou:
Você pode compará-lo com o *membro de enumeração* no seu enum `ModelName` criado:
{* ../../docs_src/path_params/tutorial005.py hl[17] *}
#### Obtenha o *valor de enumerate*
#### Obtenha o valor da enumeração { #get-the-enumeration-value }
Você pode ter o valor exato de enumerate (um `str` nesse caso) usando `model_name.value`, ou em geral, `your_enum_member.value`:
Você pode obter o valor real (um `str` neste caso) usando `model_name.value`, ou, em geral, `your_enum_member.value`:
{* ../../docs_src/path_params/tutorial005.py hl[20] *}
/// tip | Dica
Você também pode acessar o valor `"lenet"` com `ModelName.lenet.value`.
///
Você também poderia acessar o valor `"lenet"` com `ModelName.lenet.value`
#### Retorne membros de enumeração { #return-enumeration-members }
#### Retorne *membros de enumeration*
Você pode retornar *membros de enum* da sua *operação de rota*, até mesmo aninhados em um corpo JSON (por exemplo, um `dict`).
Você pode retornar *membros de enum* da sua *rota de operação*, em um corpo JSON aninhado (por exemplo um `dict`).
Eles serão convertidos para o seus valores correspondentes (strings nesse caso) antes de serem retornados ao cliente:
Eles serão convertidos para seus valores correspondentes (strings neste caso) antes de serem retornados ao cliente:
{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
No seu cliente você vai obter uma resposta JSON como:
No seu cliente, você receberá uma resposta JSON como:
```JSON
{
@@ -210,56 +191,51 @@ No seu cliente você vai obter uma resposta JSON como:
}
```
## Parâmetros de rota que contém caminhos
## Parâmetros de path que contêm paths { #path-parameters-containing-paths }
Digamos que você tenha uma *operação de rota* com uma rota `/files/{file_path}`.
Digamos que você tenha uma *operação de rota* com um path `/files/{file_path}`.
Mas você precisa que o próprio `file_path` contenha uma *rota*, como `home/johndoe/myfile.txt`.
Mas você precisa que o próprio `file_path` contenha um *path*, como `home/johndoe/myfile.txt`.
Então, a URL para este arquivo deveria ser algo como: `/files/home/johndoe/myfile.txt`.
Então, a URL para esse arquivo seria algo como: `/files/home/johndoe/myfile.txt`.
### Suporte do OpenAPI
### Suporte do OpenAPI { #openapi-support }
O OpenAPI não suporta uma maneira de declarar um *parâmetro de rota* que contenha uma *rota* dentro, dado que isso poderia levar a cenários que são difíceis de testar e definir.
O OpenAPI não oferece suporte a uma maneira de declarar um *parâmetro de path* que contenha um *path* dentro, pois isso poderia levar a cenários difíceis de testar e definir.
No entanto, você pode fazer isso no **FastAPI**, usando uma das ferramentas internas do Starlette.
Ainda assim, você pode fazer isso no **FastAPI**, usando uma das ferramentas internas do Starlette.
A documentação continuaria funcionando, ainda que não adicionaria nenhuma informação dizendo que o parâmetro deveria conter uma rota.
E a documentação continuará funcionando, embora não adicione nenhuma informação dizendo que o parâmetro deve conter um path.
### Conversor de rota
### Conversor de path { #path-convertor }
Usando uma opção direta do Starlette você pode declarar um *parâmetro de rota* contendo uma *rota* usando uma URL como:
Usando uma opção diretamente do Starlette você pode declarar um *parâmetro de path* contendo um *path* usando uma URL como:
```
/files/{file_path:path}
```
Nesse caso, o nome do parâmetro é `file_path`, e a última parte, `:path`, diz que o parâmetro deveria coincidir com qualquer *rota*.
Nesse caso, o nome do parâmetro é `file_path`, e a última parte, `:path`, diz que o parâmetro deve corresponder a qualquer *path*.
Então, você poderia usar ele com:
Então, você pode usá-lo com:
{* ../../docs_src/path_params/tutorial004.py hl[6] *}
/// tip | Dica
Você pode precisar que o parâmetro contenha `/home/johndoe/myfile.txt`, com uma barra inicial (`/`).
Nesse caso, a URL seria: `/files//home/johndoe/myfile.txt`, com uma barra dupla (`//`) entre `files` e `home`.
///
Você poderia precisar que o parâmetro contivesse `/home/johndoe/myfile.txt`, com uma barra no inicio (`/`).
## Recapitulação { #recap }
Neste caso, a URL deveria ser: `/files//home/johndoe/myfile.txt`, com barra dupla (`//`) entre `files` e `home`.
Com o **FastAPI**, ao usar declarações de tipo do Python curtas, intuitivas e padrão, você obtém:
- Suporte no editor: verificações de erro, autocompletar, etc.
- "<abbr title="convertendo a string que vem de um request HTTP em dados Python">Parsing</abbr>" de dados
- Validação de dados
- Anotação da API e documentação automática
## Recapitulando
E você só precisa declará-los uma vez.
Com o **FastAPI**, usando as declarações de tipo do Python, você obtém:
* Suporte no editor: verificação de erros, e opção de autocompletar, etc.
* "<abbr title="convertendo uma string que vem de um request HTTP em dado Python">Parsing</abbr>" de dados
* Validação de dados
* Anotação da API e documentação automática
Você apenas tem que declará-los uma vez.
Essa é provavelmente a vantagem mais visível do **FastAPI** se comparado com frameworks alternativos (além do desempenho puro).
Essa é provavelmente a principal vantagem visível do **FastAPI** em comparação com frameworks alternativos (além do desempenho bruto).

View File

@@ -1,4 +1,4 @@
# Modelos de Parâmetros de Consulta
# Modelos de Parâmetros de Consulta { #query-parameter-models }
Se você possui um grupo de **parâmetros de consultas** que são relacionados, você pode criar um **modelo Pydantic** para declará-los.
@@ -10,7 +10,7 @@ Isso é suportado desde o FastAPI versão `0.115.0`. 🤓
///
## Parâmetros de Consulta com um Modelo Pydantic
## Parâmetros de Consulta com um Modelo Pydantic { #query-parameters-with-a-pydantic-model }
Declare os **parâmetros de consulta** que você precisa em um **modelo Pydantic**, e então declare o parâmetro como `Query`:
@@ -19,7 +19,7 @@ Declare os **parâmetros de consulta** que você precisa em um **modelo Pydantic
O **FastAPI** **extrairá** os dados para **cada campo** dos **parâmetros de consulta** presentes na requisição, e fornecerá o modelo Pydantic que você definiu.
## Verifique os Documentos
## Verifique os Documentos { #check-the-docs }
Você pode ver os parâmetros de consulta nos documentos de IU em `/docs`:
@@ -27,7 +27,7 @@ Você pode ver os parâmetros de consulta nos documentos de IU em `/docs`:
<img src="/img/tutorial/query-param-models/image01.png">
</div>
## Restrinja Parâmetros de Consulta Extras
## Restrinja Parâmetros de Consulta Extras { #forbid-extra-query-parameters }
Em alguns casos especiais (provavelmente não muito comuns), você queira **restrinjir** os parâmetros de consulta que deseja receber.
@@ -58,7 +58,7 @@ Eles receberão um retorno de **erro** informando-os que o parâmentro de consul
}
```
## Resumo
## Resumo { #summary }
Você pode utilizar **modelos Pydantic** para declarar **parâmetros de consulta** no **FastAPI**. 😎

View File

@@ -1,164 +1,286 @@
# Parâmetros de consulta e validações de texto
# Parâmetros de consulta e validações de string { #query-parameters-and-string-validations }
O **FastAPI** permite que você declare informações adicionais e validações aos seus parâmetros.
O **FastAPI** permite declarar informações adicionais e validações para os seus parâmetros.
Vamos utilizar essa aplicação como exemplo:
Vamos usar esta aplicação como exemplo:
{* ../../docs_src/query_params_str_validations/tutorial001.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
O parâmetro de consulta `q` é do tipo `Union[str, None]`, o que significa que é do tipo `str` mas que também pode ser `None`, e de fato, o valor padrão é `None`, então o FastAPI saberá que não é obrigatório.
O parâmetro de consulta `q` é do tipo `str | None`, isso significa que é do tipo `str`, mas também pode ser `None`, e de fato, o valor padrão é `None`, então o FastAPI saberá que não é obrigatório.
/// note | Observação
/// note | Nota
O FastAPI saberá que o valor de `q` não é obrigatório por causa do valor padrão `= None`.
O `Union` em `Union[str, None]` não é usado pelo FastAPI, mas permitirá que seu editor lhe dê um melhor suporte e detecte erros.
Ter `str | None` permitirá que seu editor lhe ofereça melhor suporte e detecte erros.
///
## Validação adicional
## Validação adicional { #additional-validation }
Nós iremos forçar que mesmo o parâmetro `q` seja opcional, sempre que informado, **seu tamanho não exceda 50 caracteres**.
Vamos impor que, embora `q` seja opcional, sempre que for fornecido, **seu comprimento não exceda 50 caracteres**.
### Importe `Query`
### Importe `Query` e `Annotated` { #import-query-and-annotated }
Para isso, primeiro importe `Query` de `fastapi`:
Para isso, primeiro importe:
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[3] *}
* `Query` de `fastapi`
* `Annotated` de `typing`
## Use `Query` como o valor padrão
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
Agora utilize-o como valor padrão do seu parâmetro, definindo o parâmetro `max_length` para 50:
/// info | Informação
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *}
O FastAPI adicionou suporte a `Annotated` (e passou a recomendá-lo) na versão 0.95.0.
Note que substituímos o valor padrão de `None` para `Query(default=None)`, o primeiro parâmetro de `Query` serve para o mesmo propósito: definir o valor padrão do parâmetro.
Se você tiver uma versão mais antiga, terá erros ao tentar usar `Annotated`.
Então:
Certifique-se de [Atualizar a versão do FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} para pelo menos 0.95.1 antes de usar `Annotated`.
///
## Use `Annotated` no tipo do parâmetro `q` { #use-annotated-in-the-type-for-the-q-parameter }
Lembra que eu disse antes que `Annotated` pode ser usado para adicionar metadados aos seus parâmetros na [Introdução aos tipos do Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
Agora é a hora de usá-lo com FastAPI. 🚀
Tínhamos esta anotação de tipo:
//// tab | Python 3.10+
```Python
q: Union[str, None] = Query(default=None)
q: str | None = None
```
...Torna o parâmetro opcional, da mesma maneira que:
////
//// tab | Python 3.8+
```Python
q: Union[str, None] = None
```
Mas o declara explicitamente como um parâmetro de consulta.
////
/// info | Informação
O que faremos é envolver isso com `Annotated`, para que fique assim:
Tenha em mente que o FastAPI se preocupa com a parte:
//// tab | Python 3.10+
```Python
= None
q: Annotated[str | None] = None
```
Ou com:
////
//// tab | Python 3.8+
```Python
= Query(default=None)
q: Annotated[Union[str, None]] = None
```
E irá utilizar o `None` para detectar que o parâmetro de consulta não é obrigatório.
////
O `Union` é apenas para permitir que seu editor de texto lhe dê um melhor suporte.
Ambas as versões significam a mesma coisa, `q` é um parâmetro que pode ser `str` ou `None`, e por padrão é `None`.
Agora vamos pular para a parte divertida. 🎉
## Adicione `Query` ao `Annotated` no parâmetro `q` { #add-query-to-annotated-in-the-q-parameter }
Agora que temos esse `Annotated` onde podemos colocar mais informações (neste caso, uma validação adicional), adicione `Query` dentro de `Annotated` e defina o parâmetro `max_length` como `50`:
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}
Perceba que o valor padrão continua sendo `None`, então o parâmetro ainda é opcional.
Mas agora, com `Query(max_length=50)` dentro de `Annotated`, estamos dizendo ao FastAPI que queremos **validação adicional** para este valor, queremos que tenha no máximo 50 caracteres. 😎
/// tip | Dica
Aqui estamos usando `Query()` porque este é um **parâmetro de consulta**. Mais adiante veremos outros como `Path()`, `Body()`, `Header()` e `Cookie()`, que também aceitam os mesmos argumentos que `Query()`.
///
Então, podemos passar mais parâmetros para `Query`. Neste caso, o parâmetro `max_length` que se aplica a textos:
Agora o FastAPI vai:
```Python
q: str = Query(default=None, max_length=50)
```
* **Validar** os dados garantindo que o comprimento máximo seja de 50 caracteres
* Mostrar um **erro claro** para o cliente quando os dados não forem válidos
* **Documentar** o parâmetro na *operação de rota* do esquema OpenAPI (então ele aparecerá na **UI de docs automática**)
Isso irá validar os dados, mostrar um erro claro quando os dados forem inválidos, e documentar o parâmetro na *operação de rota* do esquema OpenAPI..
## Alternativa (antiga): `Query` como valor padrão { #alternative-old-query-as-the-default-value }
## Adicionando mais validações
Versões anteriores do FastAPI (antes de <abbr title="antes de 2023-03">0.95.0</abbr>) exigiam que você usasse `Query` como valor padrão do seu parâmetro, em vez de colocá-lo em `Annotated`. É muito provável que você veja código assim por aí, então vou te explicar.
Você também pode incluir um parâmetro `min_length`:
/// tip | Dica
{* ../../docs_src/query_params_str_validations/tutorial003.py hl[10] *}
## Adicionando expressões regulares
Você pode definir uma <abbr title="Uma expressão regular, regex ou regexp é uma sequência de caracteres que define um parâmetro de busca para textos.">expressão regular</abbr> que combine com um padrão esperado pelo parâmetro:
{* ../../docs_src/query_params_str_validations/tutorial004.py hl[11] *}
Essa expressão regular específica verifica se o valor recebido no parâmetro:
* `^`: Inicia com os seguintes caracteres, ou seja, não contém caracteres anteriores.
* `fixedquery`: contém o valor exato `fixedquery`.
* `$`: termina aqui, não contém nenhum caractere após `fixedquery`.
Se você se sente perdido com todo esse assunto de **"expressão regular"**, não se preocupe. Esse é um assunto complicado para a maioria das pessoas. Você ainda pode fazer muitas coisas sem utilizar expressões regulares.
Mas assim que você precisar e já tiver aprendido sobre, saiba que você poderá usá-las diretamente no **FastAPI**.
## Valores padrão
Da mesma maneira que você utiliza `None` como o primeiro argumento para ser utilizado como um valor padrão, você pode usar outros valores.
Vamos dizer que você queira que o parâmetro de consulta `q` tenha um `min_length` de `3`, e um valor padrão de `"fixedquery"`, então declararíamos assim:
{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *}
/// note | Observação
O parâmetro torna-se opcional quando possui um valor padrão.
Para código novo e sempre que possível, use `Annotated` como explicado acima. Há múltiplas vantagens (explicadas abaixo) e nenhuma desvantagem. 🍰
///
## Torne-o obrigatório
É assim que você usaria `Query()` como valor padrão do parâmetro da sua função, definindo o parâmetro `max_length` como 50:
Quando você não necessita de validações ou de metadados adicionais, podemos fazer com que o parâmetro de consulta `q` seja obrigatório por não declarar um valor padrão, dessa forma:
{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}
Como neste caso (sem usar `Annotated`) temos que substituir o valor padrão `None` na função por `Query()`, agora precisamos definir o valor padrão com o parâmetro `Query(default=None)`, ele serve ao mesmo propósito de definir esse valor padrão (pelo menos para o FastAPI).
Então:
```Python
q: str | None = Query(default=None)
```
...torna o parâmetro opcional, com um valor padrão de `None`, o mesmo que:
```Python
q: str | None = None
```
Mas a versão com `Query` o declara explicitamente como sendo um parâmetro de consulta.
Então, podemos passar mais parâmetros para `Query`. Neste caso, o parâmetro `max_length` que se aplica a strings:
```Python
q: str | None = Query(default=None, max_length=50)
```
Isso validará os dados, mostrará um erro claro quando os dados não forem válidos e documentará o parâmetro na *operação de rota* do esquema OpenAPI.
### `Query` como valor padrão ou em `Annotated` { #query-as-the-default-value-or-in-annotated }
Tenha em mente que, ao usar `Query` dentro de `Annotated`, você não pode usar o parâmetro `default` de `Query`.
Em vez disso, use o valor padrão real do parâmetro da função. Caso contrário, haveria inconsistência.
Por exemplo, isto não é permitido:
```Python
q: Annotated[str, Query(default="rick")] = "morty"
```
...porque não está claro se o valor padrão deveria ser `"rick"` ou `"morty"`.
Então, você usaria (preferencialmente):
```Python
q: Annotated[str, Query()] = "rick"
```
...ou em bases de código mais antigas você encontrará:
```Python
q: str = Query(default="rick")
```
### Vantagens de `Annotated` { #advantages-of-annotated }
**Usar `Annotated` é recomendado** em vez do valor padrão nos parâmetros da função, é **melhor** por vários motivos. 🤓
O valor **padrão** do **parâmetro da função** é o **valor padrão real**, isso é mais intuitivo com Python em geral. 😌
Você poderia **chamar** essa mesma função em **outros lugares** sem FastAPI, e ela **funcionaria como esperado**. Se houver um parâmetro **obrigatório** (sem valor padrão), seu **editor** vai avisar com um erro, e o **Python** também reclamará se você executá-la sem passar o parâmetro obrigatório.
Quando você não usa `Annotated` e em vez disso usa o estilo de **valor padrão (antigo)**, se você chamar essa função sem FastAPI em **outros lugares**, terá que **lembrar** de passar os argumentos para a função para que funcione corretamente, caso contrário os valores serão diferentes do esperado (por exemplo, `QueryInfo` ou algo parecido em vez de `str`). E seu editor não vai avisar, e o Python também não vai reclamar ao executar a função, apenas quando as operações internas falharem.
Como `Annotated` pode ter mais de uma anotação de metadados, você agora pode até usar a mesma função com outras ferramentas, como o <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. 🚀
## Adicione mais validações { #add-more-validations }
Você também pode adicionar um parâmetro `min_length`:
{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
## Adicione expressões regulares { #add-regular-expressions }
Você pode definir um `pattern` de <abbr title="Uma expressão regular, regex ou regexp é uma sequência de caracteres que define um padrão de busca para strings.">expressão regular</abbr> que o parâmetro deve corresponder:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
Esse padrão específico de expressão regular verifica se o valor recebido no parâmetro:
* `^`: começa com os caracteres seguintes, não tem caracteres antes.
* `fixedquery`: tem exatamente o valor `fixedquery`.
* `$`: termina ali, não tem mais caracteres depois de `fixedquery`.
Se você se sentir perdido com essas ideias de **"expressão regular"**, não se preocupe. Esse é um assunto difícil para muitas pessoas. Você ainda pode fazer muitas coisas sem precisar de expressões regulares por enquanto.
Agora você sabe que, sempre que precisar delas, pode usá-las no **FastAPI**.
### Pydantic v1 `regex` em vez de `pattern` { #pydantic-v1-regex-instead-of-pattern }
Antes da versão 2 do Pydantic e antes do FastAPI 0.100.0, o parâmetro se chamava `regex` em vez de `pattern`, mas agora está descontinuado.
Você ainda pode ver algum código usando isso:
//// tab | Pydantic v1
{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *}
////
Mas saiba que isso está descontinuado e deve ser atualizado para usar o novo parâmetro `pattern`. 🤓
## Valores padrão { #default-values }
Você pode, claro, usar valores padrão diferentes de `None`.
Digamos que você queira declarar o parâmetro de consulta `q` com `min_length` de `3` e ter um valor padrão de `"fixedquery"`:
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
/// note | Nota
Ter um valor padrão de qualquer tipo, incluindo `None`, torna o parâmetro opcional (não obrigatório).
///
## Parâmetros obrigatórios { #required-parameters }
Quando não precisamos declarar mais validações ou metadados, podemos tornar o parâmetro de consulta `q` obrigatório simplesmente não declarando um valor padrão, assim:
```Python
q: str
```
em vez desta:
em vez de:
```Python
q: Union[str, None] = None
q: str | None = None
```
Mas agora nós o estamos declarando como `Query`, conforme abaixo:
Mas agora estamos declarando com `Query`, por exemplo assim:
```Python
q: Union[str, None] = Query(default=None, min_length=3)
q: Annotated[str | None, Query(min_length=3)] = None
```
Então, quando você precisa declarar um parâmetro obrigatório utilizando o `Query`, você pode utilizar `...` como o primeiro argumento:
Então, quando você precisa declarar um valor como obrigatório usando `Query`, você pode simplesmente não declarar um valor padrão:
{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *}
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
/// info | Informação
### Obrigatório, pode ser `None` { #required-can-be-none }
Se você nunca viu os `...` antes: é um valor único especial, faz <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">parte do Python e é chamado "Ellipsis"</a>.
Você pode declarar que um parâmetro pode aceitar `None`, mas que ainda assim é obrigatório. Isso forçaria os clientes a enviarem um valor, mesmo que o valor seja `None`.
///
Para isso, você pode declarar que `None` é um tipo válido, mas simplesmente não declarar um valor padrão:
Dessa forma o **FastAPI** saberá que o parâmetro é obrigatório.
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
## Lista de parâmetros de consulta / múltiplos valores
## Lista de parâmetros de consulta / múltiplos valores { #query-parameter-list-multiple-values }
Quando você declara explicitamente um parâmetro com `Query` você pode declará-lo para receber uma lista de valores, ou podemos dizer, que irá receber mais de um valor.
Quando você define explicitamente um parâmetro de consulta com `Query`, você também pode declará-lo para receber uma lista de valores, ou seja, receber múltiplos valores.
Por exemplo, para declarar que o parâmetro `q` pode aparecer diversas vezes na URL, você escreveria:
Por exemplo, para declarar um parâmetro de consulta `q` que pode aparecer várias vezes na URL, você pode escrever:
{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}
Então, com uma URL assim:
Então, com uma URL como:
```
http://localhost:8000/items/?q=foo&q=bar
```
você receberá os múltiplos *parâmetros de consulta* `q` com os valores (`foo` e `bar`) em uma lista (`list`) Python dentro da *função de operação de rota*, no *parâmetro da função* `q`.
você receberá os múltiplos valores do *parâmetro de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *função de operação de rota*, no *parâmetro da função* `q`.
Assim, a resposta para essa URL seria:
@@ -173,19 +295,19 @@ Assim, a resposta para essa URL seria:
/// tip | Dica
Para declarar um parâmetro de consulta com o tipo `list`, como no exemplo acima, você precisa usar explicitamente o `Query`, caso contrário será interpretado como um corpo da requisição.
Para declarar um parâmetro de consulta com tipo `list`, como no exemplo acima, você precisa usar explicitamente `Query`, caso contrário seria interpretado como um corpo da requisição.
///
A documentação interativa da API irá atualizar de acordo, permitindo múltiplos valores:
A documentação interativa da API será atualizada de acordo, permitindo múltiplos valores:
<img src="/img/tutorial/query-params-str-validations/image02.png">
### Lista de parâmetros de consulta / múltiplos valores por padrão
### Lista de parâmetros de consulta / múltiplos valores com valores padrão { #query-parameter-list-multiple-values-with-defaults }
E você também pode definir uma lista (`list`) de valores padrão caso nenhum seja informado:
Você também pode definir uma `list` de valores padrão caso nenhum seja fornecido:
{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
Se você for até:
@@ -193,7 +315,7 @@ Se você for até:
http://localhost:8000/items/
```
O valor padrão de `q` será: `["foo", "bar"]` e sua resposta será:
o valor padrão de `q` será: `["foo", "bar"]` e sua resposta será:
```JSON
{
@@ -204,93 +326,163 @@ O valor padrão de `q` será: `["foo", "bar"]` e sua resposta será:
}
```
#### Usando `list`
#### Usando apenas `list` { #using-just-list }
Você também pode utilizar o tipo `list` diretamente em vez de `List[str]`:
Você também pode usar `list` diretamente em vez de `list[str]`:
{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *}
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
/// note | Observação
/// note | Nota
Tenha em mente que neste caso, o FastAPI não irá validar os conteúdos da lista.
Tenha em mente que, neste caso, o FastAPI não verificará o conteúdo da lista.
Por exemplo, um `List[int]` iria validar (e documentar) que os contéudos da lista são números inteiros. Mas apenas `list` não.
Por exemplo, `list[int]` verificaria (e documentaria) que os contdos da lista são inteiros. Mas `list` sozinho não.
///
## Declarando mais metadados
## Declare mais metadados { #declare-more-metadata }
Você pode adicionar mais informações sobre o parâmetro.
Essa informações serão inclusas no esquema do OpenAPI e utilizado pela documentação interativa e ferramentas externas.
Essas informações serão incluídas no OpenAPI gerado e usadas pelas interfaces de documentação e por ferramentas externas.
/// note | Observação
/// note | Nota
Tenha em mente que cada ferramenta oferece diferentes níveis de suporte ao OpenAPI.
Tenha em mente que ferramentas diferentes podem ter níveis diferentes de suporte ao OpenAPI.
Algumas delas não exibem todas as informações extras que declaramos, ainda que na maioria dos casos, esses recursos estão planejados para desenvolvimento.
Algumas delas podem ainda não mostrar todas as informações extras declaradas, embora na maioria dos casos o recurso ausente já esteja planejado para desenvolvimento.
///
Você pode adicionar um `title`:
{* ../../docs_src/query_params_str_validations/tutorial007.py hl[10] *}
{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}
E uma `description`:
{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *}
{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
## Apelidos (alias) de parâmetros
## Parâmetros com alias { #alias-parameters }
Imagine que você queira que um parâmetro tenha o nome `item-query`.
Imagine que você queira que o parâmetro seja `item-query`.
Desta maneira:
Assim:
```
http://127.0.0.1:8000/items/?item-query=foobaritems
```
Mas o nome `item-query` não é um nome de váriavel válido no Python.
Mas `item-query` não é um nome de variável Python válido.
O que mais se aproxima é `item_query`.
O mais próximo seria `item_query`.
Mas ainda você precisa que o nome seja exatamente `item-query`...
Mas você ainda precisa que seja exatamente `item-query`...
Então você pode declarar um `alias`, e esse apelido (alias) que será utilizado para encontrar o valor do parâmetro:
Então você pode declarar um `alias`, e esse alias será usado para encontrar o valor do parâmetro:
{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
## Parâmetros descontinuados
## Descontinuando parâmetros { #deprecating-parameters }
Agora vamos dizer que você não queria mais utilizar um parâmetro.
Agora digamos que você não gosta mais desse parâmetro.
Você tem que deixá-lo ativo por um tempo, já que existem clientes o utilizando. Mas você quer que a documentação deixe claro que este parâmetro será <abbr title="obsoleto, recomenda-se que não deve ser utilizado">descontinuado</abbr>.
Você tem que deixá-lo por um tempo, pois há clientes usando-o, mas quer que a documentação mostre claramente que ele está <abbr title="obsoleto, recomenda-se não usá-lo">descontinuado</abbr>.
Então você passa o parâmetro `deprecated=True` para `Query`:
Então passe o parâmetro `deprecated=True` para `Query`:
{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *}
{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}
Na documentação aparecerá assim:
A documentação vai mostrar assim:
<img src="/img/tutorial/query-params-str-validations/image01.png">
## Recapitulando
## Excluir parâmetros do OpenAPI { #exclude-parameters-from-openapi }
Você pode adicionar validações e metadados adicionais aos seus parâmetros.
Para excluir um parâmetro de consulta do OpenAPI gerado (e portanto, dos sistemas de documentação automáticos), defina o parâmetro `include_in_schema` de `Query` como `False`:
Validações genéricas e metadados:
{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
## Validação personalizada { #custom-validation }
Podem existir casos em que você precise fazer alguma **validação personalizada** que não pode ser feita com os parâmetros mostrados acima.
Nesses casos, você pode usar uma **função validadora personalizada** que é aplicada após a validação normal (por exemplo, depois de validar que o valor é uma `str`).
Você pode fazer isso usando o <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator" class="external-link" target="_blank">`AfterValidator` do Pydantic</a> dentro de `Annotated`.
/// tip | Dica
O Pydantic também tem <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator" class="external-link" target="_blank">`BeforeValidator`</a> e outros. 🤓
///
Por exemplo, este validador personalizado verifica se o ID do item começa com `isbn-` para um número de livro <abbr title="ISBN significa Número Padrão Internacional de Livro">ISBN</abbr> ou com `imdb-` para um ID de URL de filme <abbr title="IMDB (Internet Movie Database) é um site com informações sobre filmes">IMDB</abbr>:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
/// info | Informação
Isso está disponível com a versão 2 do Pydantic ou superior. 😎
///
/// tip | Dica
Se você precisar fazer qualquer tipo de validação que exija comunicação com algum **componente externo**, como um banco de dados ou outra API, você deve usar **Dependências do FastAPI** em vez disso; você aprenderá sobre elas mais adiante.
Esses validadores personalizados são para coisas que podem ser verificadas **apenas** com os **mesmos dados** fornecidos na requisição.
///
### Entenda esse código { #understand-that-code }
O ponto importante é apenas usar **`AfterValidator` com uma função dentro de `Annotated`**. Sinta-se à vontade para pular esta parte. 🤸
---
Mas se você está curioso sobre este exemplo específico e ainda entretido, aqui vão alguns detalhes extras.
#### String com `value.startswith()` { #string-with-value-startswith }
Percebeu? Uma string usando `value.startswith()` pode receber uma tupla, e verificará cada valor na tupla:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
#### Um item aleatório { #a-random-item }
Com `data.items()` obtemos um <abbr title="Algo que podemos iterar com um laço for, como uma list, set, etc.">objeto iterável</abbr> com tuplas contendo a chave e o valor de cada item do dicionário.
Convertimos esse objeto iterável em uma `list` adequada com `list(data.items())`.
Em seguida, com `random.choice()` podemos obter um **valor aleatório** da lista, então obtemos uma tupla com `(id, name)`. Será algo como `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`.
Depois **atribuímos esses dois valores** da tupla às variáveis `id` e `name`.
Assim, se o usuário não fornecer um ID de item, ele ainda receberá uma sugestão aleatória.
...fazemos tudo isso em **uma única linha simples**. 🤯 Você não ama Python? 🐍
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
## Recapitulando { #recap }
Você pode declarar validações adicionais e metadados para seus parâmetros.
Validações e metadados genéricos:
* `alias`
* `title`
* `description`
* `deprecated`
Validações específicas para textos:
Validações específicas para strings:
* `min_length`
* `max_length`
* `regex`
* `pattern`
Nesses exemplos você viu como declarar validações em valores do tipo `str`.
Validações personalizadas usando `AfterValidator`.
Leia os próximos capítulos para ver como declarar validação de outros tipos, como números.
Nestes exemplos você viu como declarar validações para valores `str`.
Veja os próximos capítulos para aprender a declarar validações para outros tipos, como números.

View File

@@ -1,4 +1,4 @@
# Parâmetros de Consulta
# Parâmetros de Consulta { #query-parameters }
Quando você declara outros parâmetros na função que não fazem parte dos parâmetros da rota, esses parâmetros são automaticamente interpretados como parâmetros de "consulta".
@@ -28,7 +28,7 @@ Todo o processo que era aplicado para parâmetros de rota também é aplicado pa
* Validação de dados
* Documentação automática
## Valores padrão
## Valores padrão { #defaults }
Como os parâmetros de consulta não são uma parte fixa da rota, eles podem ser opcionais e podem ter valores padrão.
@@ -57,7 +57,7 @@ Os valores dos parâmetros na sua função serão:
* `skip=20`: Por que você definiu isso na URL
* `limit=10`: Por que esse era o valor padrão
## Parâmetros opcionais
## Parâmetros opcionais { #optional-parameters }
Da mesma forma, você pode declarar parâmetros de consulta opcionais, definindo o valor padrão para `None`:
@@ -65,13 +65,13 @@ Da mesma forma, você pode declarar parâmetros de consulta opcionais, definindo
Nesse caso, o parâmetro da função `q` será opcional, e `None` será o padrão.
/// check | Verificar
/// check | Verifique
Você também pode notar que o **FastAPI** é esperto o suficiente para perceber que o parâmetro da rota `item_id` é um parâmetro da rota, e `q` não é, portanto, `q` é o parâmetro de consulta.
///
## Conversão dos tipos de parâmetros de consulta
## Conversão dos tipos de parâmetros de consulta { #query-parameter-type-conversion }
Você também pode declarar tipos `bool`, e eles serão convertidos:
@@ -109,7 +109,7 @@ http://127.0.0.1:8000/items/foo?short=yes
ou qualquer outra variação (tudo em maiúscula, primeira letra em maiúscula, etc), a sua função vai ver o parâmetro `short` com um valor `bool` de `True`. Caso contrário `False`.
## Múltiplos parâmetros de rota e consulta
## Múltiplos parâmetros de rota e consulta { #multiple-path-and-query-parameters }
Você pode declarar múltiplos parâmetros de rota e parâmetros de consulta ao mesmo tempo, o **FastAPI** vai saber o quê é o quê.
@@ -119,7 +119,7 @@ Eles serão detectados pelo nome:
{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
## Parâmetros de consulta obrigatórios
## Parâmetros de consulta obrigatórios { #required-query-parameters }
Quando você declara um valor padrão para parâmetros que não são de rota (até agora, nós vimos apenas parâmetros de consulta), então eles não são obrigatórios.
@@ -141,16 +141,17 @@ http://127.0.0.1:8000/items/foo-item
```JSON
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
"detail": [
{
"type": "missing",
"loc": [
"query",
"needy"
],
"msg": "Field required",
"input": null
}
]
}
```
@@ -181,6 +182,6 @@ Nesse caso, existem 3 parâmetros de consulta:
/// tip | Dica
Você também poderia usar `Enum` da mesma forma que com [Path Parameters](path-params.md#valores-predefinidos){.internal-link target=_blank}.
Você também poderia usar `Enum` da mesma forma que com [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
///

View File

@@ -1,4 +1,4 @@
# Arquivos de Requisição
# Arquivos de Requisição { #request-files }
Você pode definir arquivos para serem enviados pelo cliente usando `File`.
@@ -16,13 +16,13 @@ Isso é necessário, visto que os arquivos enviados são enviados como "dados de
///
## Importe `File`
## Importe `File` { #import-file }
Importe `File` e `UploadFile` de `fastapi`:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
## Definir Parâmetros `File`
## Definir Parâmetros `File` { #define-file-parameters }
Crie parâmetros de arquivo da mesma forma que você faria para `Body` ou `Form`:
@@ -50,7 +50,7 @@ Mantenha em mente que isso significa que todo o conteúdo será armazenado na me
Mas há muitos casos em que você pode se beneficiar do uso de `UploadFile`.
## Parâmetros de Arquivo com `UploadFile`
## Parâmetros de Arquivo com `UploadFile` { #file-parameters-with-uploadfile }
Defina um parâmetro de arquivo com um tipo de `UploadFile`:
@@ -66,12 +66,12 @@ Utilizar `UploadFile` tem várias vantagens sobre `bytes`:
* Ele tem uma <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> interface `assíncrona`.
* Ele expõe um objeto python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> que você pode passar diretamente para outras bibliotecas que esperam um objeto semelhante a um arquivo("file-like").
### `UploadFile`
### `UploadFile` { #uploadfile }
`UploadFile` tem os seguintes atributos:
* `filename`: Uma `str` com o nome do arquivo original que foi enviado (por exemplo, `myimage.jpg`).
* `content_type`: Uma `str` com o tipo de conteúdo (tipo MIME / tipo de mídia) (por exemplo, `image/jpeg`).
* `content_type`: Uma `str` com o tipo de conteúdo (MIME type / media type) (por exemplo, `image/jpeg`).
* `file`: Um <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (um <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> objeto). Este é o objeto de arquivo Python que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto semelhante a um arquivo("file-like").
`UploadFile` tem os seguintes métodos `assíncronos`. Todos eles chamam os métodos de arquivo correspondentes por baixo dos panos (usando o `SpooledTemporaryFile` interno).
@@ -105,11 +105,11 @@ Quando você usa os métodos `async`, o **FastAPI** executa os métodos de arqui
/// note | Detalhes Técnicos do Starlette
O `UploadFile` do ***FastAPI** herda diretamente do `UploadFile` do **Starlette** , mas adiciona algumas partes necessárias para torná-lo compatível com o **Pydantic** e as outras partes do FastAPI.
O `UploadFile` do **FastAPI** herda diretamente do `UploadFile` do **Starlette**, mas adiciona algumas partes necessárias para torná-lo compatível com o **Pydantic** e as outras partes do FastAPI.
///
## O que é "Form Data"
## O que é "Form Data" { #what-is-form-data }
O jeito que os formulários HTML (`<form></form>`) enviam os dados para o servidor normalmente usa uma codificação "especial" para esses dados, a qual é diferente do JSON.
@@ -117,15 +117,15 @@ O jeito que os formulários HTML (`<form></form>`) enviam os dados para o servid
/// note | Detalhes Técnicos
Dados de formulários normalmente são codificados usando o "media type" (tipo de mídia) `application/x-www-form-urlencoded` quando não incluem arquivos.
Dados de formulários normalmente são codificados usando o "media type" `application/x-www-form-urlencoded` quando não incluem arquivos.
Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Se você usar `File`, o **FastAPI** saberá que tem que pegar os arquivos da parte correta do corpo da requisição.
Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs para <code>POST</code></a>.
Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network Rede de Desenvolvedores da Mozilla">MDN</abbr> web docs para <code>POST</code></a>.
///
/// warning | Aviso
/// warning | Atenção
Você pode declarar múltiplos parâmetros `File` e `Form` em uma *operação de rota*, mas você não pode declarar campos `Body` que você espera receber como JSON, pois a requisição terá o corpo codificado usando `multipart/form-data` ao invés de `application/json`.
@@ -133,19 +133,19 @@ Isso não é uma limitação do **FastAPI**, é parte do protocolo HTTP.
///
## Upload de Arquivo Opcional
## Upload de Arquivo Opcional { #optional-file-upload }
Você pode tornar um arquivo opcional usando anotações de tipo padrão e definindo um valor padrão de `None`:
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
## `UploadFile` com Metadados Adicionais
## `UploadFile` com Metadados Adicionais { #uploadfile-with-additional-metadata }
Você também pode usar `File()` com `UploadFile`, por exemplo, para definir metadados adicionais:
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
## Uploads de Múltiplos Arquivos
## Uploads de Múltiplos Arquivos { #multiple-file-uploads }
É possível realizar o upload de vários arquivos ao mesmo tempo.
@@ -165,12 +165,12 @@ Você pode também pode usar `from starlette.responses import HTMLResponse`.
///
### Uploads de Múltiplos Arquivos com Metadados Adicionais
### Uploads de Múltiplos Arquivos com Metadados Adicionais { #multiple-file-uploads-with-additional-metadata }
Da mesma forma de antes, você pode usar `File()` para definir parâmetros adicionais, mesmo para `UploadFile`:
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
## Recapitulando
## Recapitulando { #recap }
Utilize `File`, `bytes` e `UploadFile` para declarar arquivos a serem enviados na requisição, enviados como dados de formulário.

View File

@@ -1,4 +1,4 @@
# Modelos de Formulários
# Modelos de Formulários { #form-models }
Você pode utilizar **Modelos Pydantic** para declarar **campos de formulários** no FastAPI.
@@ -20,7 +20,7 @@ Isto é suportado desde a versão `0.113.0` do FastAPI. 🤓
///
## Modelos Pydantic para Formulários
## Modelos Pydantic para Formulários { #pydantic-models-for-forms }
Você precisa apenas declarar um **modelo Pydantic** com os campos que deseja receber como **campos de formulários**, e então declarar o parâmetro como um `Form`:
@@ -28,7 +28,7 @@ Você precisa apenas declarar um **modelo Pydantic** com os campos que deseja re
O **FastAPI** irá **extrair** as informações para **cada campo** dos **dados do formulário** na requisição e dar para você o modelo Pydantic que você definiu.
## Confira os Documentos
## Confira os Documentos { #check-the-docs }
Você pode verificar na UI de documentação em `/docs`:
@@ -36,7 +36,7 @@ Você pode verificar na UI de documentação em `/docs`:
<img src="/img/tutorial/request-form-models/image01.png">
</div>
## Proibir Campos Extras de Formulários
## Proibir Campos Extras de Formulários { #forbid-extra-form-fields }
Em alguns casos de uso especiais (provavelmente não muito comum), você pode desejar **restringir** os campos do formulário para aceitar apenas os declarados no modelo Pydantic. E **proibir** qualquer campo **extra**.
@@ -73,6 +73,6 @@ Ele receberá um retorno de erro informando-o que o campo `extra` não é permit
}
```
## Resumo
## Resumo { #summary }
Você pode utilizar modelos Pydantic para declarar campos de formulários no FastAPI. 😎

View File

@@ -1,4 +1,4 @@
# Formulários e Arquivos da Requisição
# Formulários e Arquivos da Requisição { #request-forms-and-files }
Você pode definir arquivos e campos de formulário ao mesmo tempo usando `File` e `Form`.
@@ -6,32 +6,36 @@ Você pode definir arquivos e campos de formulário ao mesmo tempo usando `File`
Para receber arquivos carregados e/ou dados de formulário, primeiro instale <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Por exemplo: `pip install python-multipart`.
Certifique-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar, por exemplo:
```console
$ pip install python-multipart
```
///
## Importe `File` e `Form`
## Importe `File` e `Form` { #import-file-and-form }
{* ../../docs_src/request_forms_and_files/tutorial001.py hl[1] *}
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
## Defina parâmetros de `File` e `Form`
## Defina parâmetros de `File` e `Form` { #define-file-and-form-parameters }
Crie parâmetros de arquivo e formulário da mesma forma que você faria para `Body` ou `Query`:
{* ../../docs_src/request_forms_and_files/tutorial001.py hl[8] *}
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
Os arquivos e campos de formulário serão carregados como dados de formulário e você receberá os arquivos e campos de formulário.
E você pode declarar alguns dos arquivos como `bytes` e alguns como `UploadFile`.
/// warning | Aviso
/// warning | Atenção
Você pode declarar vários parâmetros `File` e `Form` em uma *operação de caminho*, mas não é possível declarar campos `Body` para receber como JSON, pois a requisição terá o corpo codificado usando `multipart/form-data` ao invés de `application/json`.
Isso não é uma limitação do **FastAPI** , é parte do protocolo HTTP.
Isso não é uma limitação do **FastAPI**, é parte do protocolo HTTP.
///
## Recapitulando
## Recapitulando { #recap }
Usar `File` e `Form` juntos quando precisar receber dados e arquivos na mesma requisição.

View File

@@ -1,12 +1,12 @@
# Dados do formulário
# Dados do formulário { #form-data }
Quando você precisar receber campos de formulário ao invés de JSON, você pode usar `Form`.
Quando você precisar receber campos de formulário em vez de JSON, você pode usar `Form`.
/// info | Informação
Para usar formulários, primeiro instale <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Lembre-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar a dependência, por exemplo:
Certifique-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalá-lo, por exemplo:
```console
$ pip install python-multipart
@@ -14,23 +14,23 @@ $ pip install python-multipart
///
## Importe `Form`
## Importe `Form` { #import-form }
Importe `Form` de `fastapi`:
{* ../../docs_src/request_forms/tutorial001.py hl[1] *}
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
## Declare parâmetros de `Form`
## Defina parâmetros de `Form` { #define-form-parameters }
Crie parâmetros de formulário da mesma forma que você faria para `Body` ou `Query`:
{* ../../docs_src/request_forms/tutorial001.py hl[7] *}
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
Por exemplo, em uma das maneiras que a especificação OAuth2 pode ser usada (chamada "fluxo de senha"), é necessário enviar um `username` e uma `password` como campos do formulário.
A <abbr title="especificação">spec</abbr> exige que os campos sejam exatamente nomeados como `username` e `password` e sejam enviados como campos de formulário, não JSON.
A <abbr title="specification especificação">spec</abbr> exige que os campos sejam exatamente nomeados como `username` e `password` e sejam enviados como campos de formulário, não JSON.
Com `Form` você pode declarar os mesmos metadados e validação que com `Body` (e `Query`, `Path`, `Cookie`).
Com `Form` você pode declarar as mesmas configurações que com `Body` (e `Query`, `Path`, `Cookie`), incluindo validação, exemplos, um alias (por exemplo, `user-name` em vez de `username`), etc.
/// info | Informação
@@ -44,30 +44,30 @@ Para declarar corpos de formulário, você precisa usar `Form` explicitamente, p
///
## Sobre "Campos de formulário"
## Sobre "Campos de formulário" { #about-form-fields }
A forma como os formulários HTML (`<form></form>`) enviam os dados para o servidor normalmente usa uma codificação "especial" para esses dados, é diferente do JSON.
O **FastAPI** fará a leitura desses dados no lugar certo em vez de JSON.
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Os dados dos formulários são normalmente codificados usando o "tipo de mídia" `application/x-www-form-urlencoded`.
Os dados dos formulários são normalmente codificados usando o "media type" `application/x-www-form-urlencoded`.
Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Você lerá sobre como lidar com arquivos no próximo capítulo.
Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Você lerá sobre como lidar com arquivos no próximo capítulo.
Se você quiser ler mais sobre essas codificações e campos de formulário, vá para o <a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs para <code>POST</code></a>.
Se você quiser ler mais sobre essas codificações e campos de formulário, vá para o <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network Rede de Desenvolvedores da Mozilla">MDN</abbr> web docs para <code>POST</code></a>.
///
/// warning | Aviso
/// warning | Atenção
Você pode declarar vários parâmetros `Form` em uma *operação de caminho*, mas não pode declarar campos `Body` que espera receber como JSON, pois a solicitação terá o corpo codificado usando `application/x-www- form-urlencoded` em vez de `application/json`.
Você pode declarar vários parâmetros `Form` em uma *operação de rota*, mas não pode declarar campos `Body` que espera receber como JSON, pois a requisição terá o corpo codificado usando `application/x-www-form-urlencoded` em vez de `application/json`.
Esta não é uma limitação do **FastAPI**, é parte do protocolo HTTP.
Isso não é uma limitação do **FastAPI**, é parte do protocolo HTTP.
///
## Recapitulando
## Recapitulando { #recap }
Use `Form` para declarar os parâmetros de entrada de dados de formulário.

View File

@@ -1,172 +0,0 @@
# Arquivos de Requisição
Você pode definir arquivos para serem enviados para o cliente utilizando `File`.
/// info
Para receber arquivos compartilhados, primeiro instale <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
E.g. `pip install python-multipart`.
Isso se deve por que arquivos enviados são enviados como "dados de formulário".
///
## Importe `File`
Importe `File` e `UploadFile` do `fastapi`:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
## Defina os parâmetros de `File`
Cria os parâmetros do arquivo da mesma forma que você faria para `Body` ou `Form`:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
/// info | Informação
`File` é uma classe que herda diretamente de `Form`.
Mas lembre-se que quando você importa `Query`,`Path`, `File`, entre outros, do `fastapi`, essas são na verdade funções que retornam classes especiais.
///
/// tip | Dica
Para declarar o corpo de arquivos, você precisa utilizar `File`, do contrário os parâmetros seriam interpretados como parâmetros de consulta ou corpo (JSON) da requisição.
///
Os arquivos serão enviados como "form data".
Se você declarar o tipo do seu parâmetro na sua *função de operação de rota* como `bytes`, o **FastAPI** irá ler o arquivo para você e você receberá o conteúdo como `bytes`.
Lembre-se que isso significa que o conteúdo inteiro será armazenado em memória. Isso funciona bem para arquivos pequenos.
Mas existem vários casos em que você pode se beneficiar ao usar `UploadFile`.
## Parâmetros de arquivo com `UploadFile`
Defina um parâmetro de arquivo com o tipo `UploadFile`
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
Utilizando `UploadFile` tem várias vantagens sobre `bytes`:
* Você não precisa utilizar `File()` como o valor padrão do parâmetro.
* A classe utiliza um arquivo em "spool":
* Um arquivo guardado em memória até um tamanho máximo, depois desse limite ele é guardado em disco.
* Isso significa que a classe funciona bem com arquivos grandes como imagens, vídeos, binários extensos, etc. Sem consumir toda a memória.
* Você pode obter metadados do arquivo enviado.
* Ela possui uma interface <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">semelhante a arquivos</a> `async`.
* Ela expõe um objeto python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> que você pode repassar para bibliotecas que esperam um objeto com comportamento de arquivo.
### `UploadFile`
`UploadFile` tem os seguintes atributos:
* `filename`: Uma string (`str`) com o nome original do arquivo enviado (e.g. `myimage.jpg`).
* `content-type`: Uma `str` com o tipo do conteúdo (tipo MIME / media) (e.g. `image/jpeg`).
* `file`: Um objeto do tipo <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (um objeto <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a>). O arquivo propriamente dito que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto "file-like".
`UploadFile` tem os seguintes métodos `async`. Todos eles chamam os métodos de arquivos por baixo dos panos (usando o objeto `SpooledTemporaryFile` interno).
* `write(data)`: escreve dados (`data`) em `str` ou `bytes` no arquivo.
* `read(size)`: Lê um número de bytes/caracteres de acordo com a quantidade `size` (`int`).
* `seek(offset)`: Navega para o byte na posição `offset` (`int`) do arquivo.
* E.g., `await myfile.seek(0)` navegaria para o ínicio do arquivo.
* Isso é especialmente útil se você executar `await myfile.read()` uma vez e depois precisar ler os conteúdos do arquivo de novo.
* `close()`: Fecha o arquivo.
Como todos esses métodos são assíncronos (`async`) você precisa esperar ("await") por eles.
Por exemplo, dentro de uma *função de operação de rota* assíncrona você pode obter os conteúdos com:
```Python
contents = await myfile.read()
```
Se você estiver dentro de uma *função de operação de rota* definida normalmente com `def`, você pode acessar `UploadFile.file` diretamente, por exemplo:
```Python
contents = myfile.file.read()
```
/// note | Detalhes técnicos do `async`
Quando você utiliza métodos assíncronos, o **FastAPI** executa os métodos do arquivo em uma threadpool e espera por eles.
///
/// note | Detalhes técnicos do Starlette
O `UploadFile` do **FastAPI** herda diretamente do `UploadFile` do **Starlette**, mas adiciona algumas funcionalidades necessárias para ser compatível com o **Pydantic**
///
## O que é "Form Data"
A forma como formulários HTML(`<form></form>`) enviam dados para o servidor normalmente utilizam uma codificação "especial" para esses dados, que é diferente do JSON.
O **FastAPI** garante que os dados serão lidos da forma correta, em vez do JSON.
/// note | Detalhes Técnicos
Dados vindos de formulários geralmente tem a codificação com o "media type" `application/x-www-form-urlencoded` quando estes não incluem arquivos.
Mas quando os dados incluem arquivos, eles são codificados como `multipart/form-data`. Se você utilizar `File`, **FastAPI** saberá que deve receber os arquivos da parte correta do corpo da requisição.
Se você quer ler mais sobre essas codificações e campos de formulário, veja a documentação online da <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> sobre <code> POST</code> </a>.
///
/// warning | Aviso
Você pode declarar múltiplos parâmetros `File` e `Form` em uma *operação de rota*, mas você não pode declarar campos `Body`que seriam recebidos como JSON junto desses parâmetros, por que a codificação do corpo da requisição será `multipart/form-data` em vez de `application/json`.
Isso não é uma limitação do **FastAPI**, é uma parte do protocolo HTTP.
///
## Arquivo de upload opcional
Você pode definir um arquivo como opcional utilizando as anotações de tipo padrão e definindo o valor padrão como `None`:
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
## `UploadFile` com Metadados Adicionais
Você também pode utilizar `File()` com `UploadFile`, por exemplo, para definir metadados adicionais:
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
## Envio de Múltiplos Arquivos
É possível enviar múltiplos arquivos ao mesmo tmepo.
Ele ficam associados ao mesmo "campo do formulário" enviado com "form data".
Para usar isso, declare uma lista de `bytes` ou `UploadFile`:
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
Você irá receber, como delcarado uma lista (`list`) de `bytes` ou `UploadFile`s,
/// note | Detalhes Técnicos
Você também poderia utilizar `from starlette.responses import HTMLResponse`.
O **FastAPI** fornece as mesmas `starlette.responses` como `fastapi.responses` apenas como um facilitador para você, desenvolvedor. Mas a maior parte das respostas vem diretamente do Starlette.
///
### Enviando Múltiplos Arquivos com Metadados Adicionais
E da mesma forma que antes, você pode utilizar `File()` para definir parâmetros adicionais, até mesmo para `UploadFile`:
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
## Recapitulando
Use `File`, `bytes` e `UploadFile` para declarar arquivos que serão enviados na requisição, enviados como dados do formulário.

View File

@@ -1,6 +1,6 @@
# Modelo de resposta - Tipo de retorno
# Modelo de resposta - Tipo de retorno { #response-model-return-type }
Você pode declarar o tipo usado para a resposta anotando o **tipo de retorno** *da função de operação de rota*.
Você pode declarar o tipo usado para a resposta anotando o **tipo de retorno** da *função de operação de rota*.
Você pode usar **anotações de tipo** da mesma forma que usaria para dados de entrada em **parâmetros** de função, você pode usar modelos Pydantic, listas, dicionários, valores escalares como inteiros, booleanos, etc.
@@ -10,7 +10,7 @@ O FastAPI usará este tipo de retorno para:
* **Validar** os dados retornados.
* Se os dados forem inválidos (por exemplo, se estiver faltando um campo), significa que o código do *seu* aplicativo está quebrado, não retornando o que deveria, e retornará um erro de servidor em vez de retornar dados incorretos. Dessa forma, você e seus clientes podem ter certeza de que receberão os dados e o formato de dados esperados.
* Adicionar um **Esquema JSON** para a resposta, na *operação de rota* do OpenAPI.
* Adicionar um **JSON Schema** para a resposta, na *operação de rota* do OpenAPI.
* Isso será usado pela **documentação automática**.
* Também será usado por ferramentas de geração automática de código do cliente.
@@ -19,7 +19,7 @@ Mas o mais importante:
* Ele **limitará e filtrará** os dados de saída para o que está definido no tipo de retorno.
* Isso é particularmente importante para a **segurança**, veremos mais sobre isso abaixo.
## Parâmetro `response_model`
## Parâmetro `response_model` { #response-model-parameter }
Existem alguns casos em que você precisa ou deseja retornar alguns dados que não são exatamente o que o tipo declara.
@@ -27,7 +27,7 @@ Por exemplo, você pode querer **retornar um dicionário** ou um objeto de banco
Se você adicionasse a anotação do tipo de retorno, ferramentas e editores reclamariam com um erro (correto) informando que sua função está retornando um tipo (por exemplo, um dict) diferente do que você declarou (por exemplo, um modelo Pydantic).
Nesses casos, você pode usar o parâmetro `response_model` do *decorador de operação de rota* em vez do tipo de retorno.
Nesses casos, você pode usar o parâmetro `response_model` do *decorador de operação de rota* em vez do tipo de retorno.
Você pode usar o parâmetro `response_model` em qualquer uma das *operações de rota*:
@@ -45,7 +45,7 @@ Observe que `response_model` é um parâmetro do método "decorator" (`get`, `po
///
`response_model` recebe o mesmo tipo que você declararia para um campo de modelo Pydantic, então, pode ser um modelo Pydantic, mas também pode ser, por exemplo, uma `lista` de modelos Pydantic, como `List[Item]`.
`response_model` recebe o mesmo tipo que você declararia para um campo de modelo Pydantic, então, pode ser um modelo Pydantic, mas também pode ser, por exemplo, uma `list` de modelos Pydantic, como `List[Item]`.
O FastAPI usará este `response_model` para fazer toda a documentação de dados, validação, etc. e também para **converter e filtrar os dados de saída** para sua declaração de tipo.
@@ -57,7 +57,7 @@ Dessa forma, você diz ao editor que está retornando qualquer coisa intencional
///
### Prioridade `response_model`
### Prioridade `response_model` { #response-model-priority }
Se você declarar tanto um tipo de retorno quanto um `response_model`, o `response_model` terá prioridade e será usado pelo FastAPI.
@@ -65,7 +65,7 @@ Dessa forma, você pode adicionar anotações de tipo corretas às suas funçõe
Você também pode usar `response_model=None` para desabilitar a criação de um modelo de resposta para essa *operação de rota*, você pode precisar fazer isso se estiver adicionando anotações de tipo para coisas que não são campos Pydantic válidos, você verá um exemplo disso em uma das seções abaixo.
## Retorna os mesmos dados de entrada
## Retorne os mesmos dados de entrada { #return-the-same-input-data }
Aqui estamos declarando um modelo `UserIn`, ele conterá uma senha em texto simples:
@@ -99,13 +99,13 @@ Neste caso, pode não ser um problema, porque é o mesmo usuário enviando a sen
Mas se usarmos o mesmo modelo para outra *operação de rota*, poderíamos estar enviando as senhas dos nossos usuários para todos os clientes.
/// danger | Perigo
/// danger | Cuidado
Nunca armazene a senha simples de um usuário ou envie-a em uma resposta como esta, a menos que você saiba todas as ressalvas e saiba o que está fazendo.
///
## Adicionar um modelo de saída
## Adicione um modelo de saída { #add-an-output-model }
Podemos, em vez disso, criar um modelo de entrada com a senha em texto simples e um modelo de saída sem ela:
@@ -121,7 +121,7 @@ Aqui, embora nossa *função de operação de rota* esteja retornando o mesmo us
Então, **FastAPI** cuidará de filtrar todos os dados que não são declarados no modelo de saída (usando Pydantic).
### `response_model` ou Tipo de Retorno
### `response_model` ou Tipo de Retorno { #response-model-or-return-type }
Neste caso, como os dois modelos são diferentes, se anotássemos o tipo de retorno da função como `UserOut`, o editor e as ferramentas reclamariam que estamos retornando um tipo inválido, pois são classes diferentes.
@@ -129,7 +129,7 @@ Neste caso, como os dois modelos são diferentes, se anotássemos o tipo de reto
...mas continue lendo abaixo para ver como superar isso.
## Tipo de Retorno e Filtragem de Dados
## Tipo de Retorno e Filtragem de Dados { #return-type-and-data-filtering }
Vamos continuar do exemplo anterior. Queríamos **anotar a função com um tipo**, mas queríamos poder retornar da função algo que realmente incluísse **mais dados**.
@@ -147,7 +147,7 @@ Com isso, temos suporte de ferramentas, de editores e mypy, pois este código es
Como isso funciona? Vamos verificar. 🤓
### Anotações de tipo e ferramentas
### Anotações de tipo e ferramentas { #type-annotations-and-tooling }
Primeiro, vamos ver como editores, mypy e outras ferramentas veriam isso.
@@ -157,7 +157,7 @@ Anotamos o tipo de retorno da função como `BaseUser`, mas na verdade estamos r
O editor, mypy e outras ferramentas não reclamarão disso porque, em termos de digitação, `UserIn` é uma subclasse de `BaseUser`, o que significa que é um tipo *válido* quando o que é esperado é qualquer coisa que seja um `BaseUser`.
### Filtragem de dados FastAPI
### Filtragem de dados FastAPI { #fastapi-data-filtering }
Agora, para FastAPI, ele verá o tipo de retorno e garantirá que o que você retornar inclua **apenas** os campos que são declarados no tipo.
@@ -165,7 +165,7 @@ O FastAPI faz várias coisas internamente com o Pydantic para garantir que essas
Dessa forma, você pode obter o melhor dos dois mundos: anotações de tipo com **suporte a ferramentas** e **filtragem de dados**.
## Veja na documentação
## Veja na documentação { #see-it-in-the-docs }
Quando você vê a documentação automática, pode verificar se o modelo de entrada e o modelo de saída terão seus próprios esquemas JSON:
@@ -175,13 +175,13 @@ E ambos os modelos serão usados para a documentação interativa da API:
<img src="/img/tutorial/response-model/image02.png">
## Outras anotações de tipo de retorno
## Outras anotações de tipo de retorno { #other-return-type-annotations }
Pode haver casos em que você retorna algo que não é um campo Pydantic válido e anota na função, apenas para obter o suporte fornecido pelas ferramentas (o editor, mypy, etc).
### Retornar uma resposta diretamente
### Retorne uma Response diretamente { #return-a-response-directly }
O caso mais comum seria [retornar uma resposta diretamente, conforme explicado posteriormente na documentação avançada](../advanced/response-directly.md){.internal-link target=_blank}.
O caso mais comum seria [retornar uma Response diretamente, conforme explicado posteriormente na documentação avançada](../advanced/response-directly.md){.internal-link target=_blank}.
{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *}
@@ -189,7 +189,7 @@ Este caso simples é tratado automaticamente pelo FastAPI porque a anotação do
E as ferramentas também ficarão felizes porque `RedirectResponse` e `JSONResponse` são subclasses de `Response`, então a anotação de tipo está correta.
### Anotar uma subclasse de resposta
### Anote uma subclasse de Response { #annotate-a-response-subclass }
Você também pode usar uma subclasse de `Response` na anotação de tipo:
@@ -197,7 +197,7 @@ Você também pode usar uma subclasse de `Response` na anotação de tipo:
Isso também funcionará porque `RedirectResponse` é uma subclasse de `Response`, e o FastAPI tratará automaticamente este caso simples.
### Anotações de Tipo de Retorno Inválido
### Anotações de Tipo de Retorno Inválido { #invalid-return-type-annotations }
Mas quando você retorna algum outro objeto arbitrário que não é um tipo Pydantic válido (por exemplo, um objeto de banco de dados) e você o anota dessa forma na função, o FastAPI tentará criar um modelo de resposta Pydantic a partir dessa anotação de tipo e falhará.
@@ -205,9 +205,9 @@ O mesmo aconteceria se você tivesse algo como uma <abbr title='Uma união entre
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}
... isso falha porque a anotação de tipo não é um tipo Pydantic e não é apenas uma única classe ou subclasse `Response`, é uma união (qualquer uma das duas) entre um `Response` e um `dict`.
...isso falha porque a anotação de tipo não é um tipo Pydantic e não é apenas uma única classe ou subclasse `Response`, é uma união (qualquer uma das duas) entre um `Response` e um `dict`.
### Desabilitar modelo de resposta
### Desative o modelo de resposta { #disable-response-model }
Continuando com o exemplo acima, você pode não querer ter a validação de dados padrão, documentação, filtragem, etc. que é realizada pelo FastAPI.
@@ -219,7 +219,7 @@ Neste caso, você pode desabilitar a geração do modelo de resposta definindo `
Isso fará com que o FastAPI pule a geração do modelo de resposta e, dessa forma, você pode ter quaisquer anotações de tipo de retorno que precisar sem afetar seu aplicativo FastAPI. 🤓
## Parâmetros de codificação do modelo de resposta
## Parâmetros de codificação do modelo de resposta { #response-model-encoding-parameters }
Seu modelo de resposta pode ter valores padrão, como:
@@ -233,9 +233,9 @@ mas você pode querer omiti-los do resultado se eles não foram realmente armaze
Por exemplo, se você tem modelos com muitos atributos opcionais em um banco de dados NoSQL, mas não quer enviar respostas JSON muito longas cheias de valores padrão.
### Usar o parâmetro `response_model_exclude_unset`
### Use o parâmetro `response_model_exclude_unset` { #use-the-response-model-exclude-unset-parameter }
Você pode definir o parâmetro `response_model_exclude_unset=True` do *decorador de operação de rota* :
Você pode definir o parâmetro `response_model_exclude_unset=True` do *decorador de operação de rota*:
{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *}
@@ -245,8 +245,8 @@ Então, se você enviar uma solicitação para essa *operação de rota* para o
```JSON
{
"name": "Foo",
"price": 50.2
"name": "Foo",
"price": 50.2
}
```
@@ -275,32 +275,32 @@ conforme descrito na <a href="https://docs.pydantic.dev/1.10/usage/exporting_mod
///
#### Dados com valores para campos com padrões
#### Dados com valores para campos com padrões { #data-with-values-for-fields-with-defaults }
Mas se seus dados tiverem valores para os campos do modelo com valores padrões, como o item com ID `bar`:
```Python hl_lines="3 5"
```Python hl_lines="3 5"
{
"name": "Bar",
"description": "The bartenders",
"price": 62,
"tax": 20.2
"name": "Bar",
"description": "The bartenders",
"price": 62,
"tax": 20.2
}
```
eles serão incluídos na resposta.
#### Dados com os mesmos valores que os padrões
#### Dados com os mesmos valores que os padrões { #data-with-the-same-values-as-the-defaults }
Se os dados tiverem os mesmos valores que os padrões, como o item com ID `baz`:
```Python hl_lines="3 5-6"
```Python hl_lines="3 5-6"
{
"name": "Baz",
"description": None,
"price": 50.2,
"tax": 10.5,
"tags": []
"name": "Baz",
"description": None,
"price": 50.2,
"tax": 10.5,
"tags": []
}
```
@@ -316,7 +316,7 @@ Eles podem ser uma lista (`[]`), um `float` de `10.5`, etc.
///
### `response_model_include` e `response_model_exclude`
### `response_model_include` e `response_model_exclude` { #response-model-include-and-response-model-exclude }
Você também pode usar os parâmetros `response_model_include` e `response_model_exclude` do *decorador de operação de rota*.
@@ -328,7 +328,7 @@ Isso pode ser usado como um atalho rápido se você tiver apenas um modelo Pydan
Mas ainda é recomendado usar as ideias acima, usando várias classes, em vez desses parâmetros.
Isso ocorre porque o Schema JSON gerado no OpenAPI do seu aplicativo (e a documentação) ainda será o único para o modelo completo, mesmo que você use `response_model_include` ou `response_model_exclude` para omitir alguns atributos.
Isso ocorre porque o JSON Schema gerado no OpenAPI do seu aplicativo (e a documentação) ainda será o único para o modelo completo, mesmo que você use `response_model_include` ou `response_model_exclude` para omitir alguns atributos.
Isso também se aplica ao `response_model_by_alias` que funciona de forma semelhante.
@@ -338,19 +338,19 @@ Isso também se aplica ao `response_model_by_alias` que funciona de forma semelh
/// tip | Dica
A sintaxe `{"nome", "descrição"}` cria um `conjunto` com esses dois valores.
A sintaxe `{"name", "description"}` cria um `set` com esses dois valores.
É equivalente a `set(["nome", "descrição"])`.
É equivalente a `set(["name", "description"])`.
///
#### Usando `list`s em vez de `set`s
#### Usando `list`s em vez de `set`s { #using-lists-instead-of-sets }
Se você esquecer de usar um `set` e usar uma `lista` ou `tupla` em vez disso, o FastAPI ainda o converterá em um `set` e funcionará corretamente:
Se você esquecer de usar um `set` e usar uma `list` ou `tuple` em vez disso, o FastAPI ainda o converterá em um `set` e funcionará corretamente:
{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *}
## Recapitulação
## Recapitulação { #recap }
Use o parâmetro `response_model` do *decorador de operação de rota* para definir modelos de resposta e, especialmente, para garantir que dados privados sejam filtrados.

View File

@@ -1,6 +1,6 @@
# Código de status de resposta
# Código de status de resposta { #response-status-code }
Da mesma forma que você pode especificar um modelo de resposta, você também pode declarar o código de status HTTP usado para a resposta com o parâmetro `status_code` em qualquer uma das *operações de caminho*:
Da mesma forma que você pode especificar um modelo de resposta, você também pode declarar o código de status HTTP usado para a resposta com o parâmetro `status_code` em qualquer uma das *operações de rota*:
* `@app.get()`
* `@app.post()`
@@ -12,7 +12,7 @@ Da mesma forma que você pode especificar um modelo de resposta, você também p
/// note | Nota
Observe que `status_code` é um parâmetro do método "decorador" (get, post, etc). Não da sua função de *operação de caminho*, como todos os parâmetros e corpo.
Observe que `status_code` é um parâmetro do método "decorador" (`get`, `post`, etc). Não da sua função de *operação de rota*, como todos os parâmetros e corpo.
///
@@ -39,7 +39,7 @@ O FastAPI sabe disso e produzirá documentos OpenAPI informando que não há cor
///
## Sobre os códigos de status HTTP
## Sobre os códigos de status HTTP { #about-http-status-codes }
/// note | Nota
@@ -53,25 +53,24 @@ Esses códigos de status têm um nome associado para reconhecê-los, mas o impor
Resumidamente:
* `100` e acima são para "Informações". Você raramente os usa diretamente. As respostas com esses códigos de status não podem ter um corpo.
* **`200`** e acima são para respostas "Bem-sucedidas". Estes são os que você mais usaria.
* `100 - 199` são para "Informações". Você raramente os usa diretamente. As respostas com esses códigos de status não podem ter um corpo.
* **`200 - 299`** são para respostas "Bem-sucedidas". Estes são os que você mais usaria.
* `200` é o código de status padrão, o que significa que tudo estava "OK".
* Outro exemplo seria `201`, "Criado". É comumente usado após a criação de um novo registro no banco de dados.
* Um caso especial é `204`, "Sem Conteúdo". Essa resposta é usada quando não há conteúdo para retornar ao cliente e, portanto, a resposta não deve ter um corpo.
* **`300`** e acima são para "Redirecionamento". As respostas com esses códigos de status podem ou não ter um corpo, exceto `304`, "Não modificado", que não deve ter um.
* **`400`** e acima são para respostas de "Erro do cliente". Este é o segundo tipo que você provavelmente mais usaria.
* **`300 - 399`** são para "Redirecionamento". As respostas com esses códigos de status podem ou não ter um corpo, exceto `304`, "Não modificado", que não deve ter um.
* **`400 - 499`** são para respostas de "Erro do cliente". Este é o segundo tipo que você provavelmente mais usaria.
* Um exemplo é `404`, para uma resposta "Não encontrado".
* Para erros genéricos do cliente, você pode usar apenas `400`.
* `500` e acima são para erros do servidor. Você quase nunca os usa diretamente. Quando algo der errado em alguma parte do código do seu aplicativo ou servidor, ele retornará automaticamente um desses códigos de status.
* `500 - 599` são para erros do servidor. Você quase nunca os usa diretamente. Quando algo der errado em alguma parte do código do seu aplicativo ou servidor, ele retornará automaticamente um desses códigos de status.
/// tip | Dica
Para saber mais sobre cada código de status e qual código serve para quê, verifique o <a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> documentação sobre códigos de status HTTP</a>.
Para saber mais sobre cada código de status e qual código serve para quê, verifique a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank">documentação do <abbr title="Mozilla Developer Network Rede de Desenvolvedores da Mozilla">MDN</abbr> sobre códigos de status HTTP</a>.
///
## Atalho para lembrar os nomes
## Atalho para lembrar os nomes { #shortcut-to-remember-the-names }
Vamos ver o exemplo anterior novamente:
@@ -85,11 +84,11 @@ Você pode usar as variáveis de conveniência de `fastapi.status`.
{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o autocomplete do editor para encontrá-los:
Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o preenchimento automático do editor para encontrá-los:
<img src="/img/tutorial/response-status-code/image02.png">
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Você também pode usar `from starlette import status`.
@@ -97,6 +96,6 @@ Você também pode usar `from starlette import status`.
///
## Alterando o padrão
## Alterando o padrão { #changing-the-default }
Mais tarde, no [Guia do usuário avançado](../advanced/response-change-status-code.md){.internal-link target=_blank}, você verá como retornar um código de status diferente do padrão que você está declarando aqui.
Mais tarde, no [Guia do Usuário Avançado](../advanced/response-change-status-code.md){.internal-link target=_blank}, você verá como retornar um código de status diferente do padrão que você está declarando aqui.

View File

@@ -1,42 +1,70 @@
# Declare um exemplo dos dados da requisição
# Declarar dados de exemplo da requisição { #declare-request-example-data }
Você pode declarar exemplos dos dados que a sua aplicação pode receber.
Você pode declarar exemplos dos dados que sua aplicação pode receber.
Aqui estão várias formas de se fazer isso.
Aqui estão várias maneiras de fazer isso.
## `schema_extra` do Pydantic
## Dados extras de JSON Schema em modelos Pydantic { #extra-json-schema-data-in-pydantic-models }
Você pode declarar um `example` para um modelo Pydantic usando `Config` e `schema_extra`, conforme descrito em <a href="https://docs.pydantic.dev/latest/concepts/json_schema/#schema-customization" class="external-link" target="_blank">Documentação do Pydantic: Schema customization</a>:
Você pode declarar `examples` para um modelo Pydantic que serão adicionados ao JSON Schema gerado.
{* ../../docs_src/schema_extra_example/tutorial001.py hl[15:23] *}
//// tab | Pydantic v2
Essas informações extras serão adicionadas como se encontram no **JSON Schema** de resposta desse modelo e serão usadas na documentação da API.
{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
////
//// tab | Pydantic v1
{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *}
////
Essas informações extras serão adicionadas como estão ao **JSON Schema** de saída para esse modelo e serão usadas na documentação da API.
//// tab | Pydantic v2
Na versão 2 do Pydantic, você usaria o atributo `model_config`, que recebe um `dict`, conforme descrito na <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">documentação do Pydantic: Configuration</a>.
Você pode definir `"json_schema_extra"` com um `dict` contendo quaisquer dados adicionais que você queira que apareçam no JSON Schema gerado, incluindo `examples`.
////
//// tab | Pydantic v1
Na versão 1 do Pydantic, você usaria uma classe interna `Config` e `schema_extra`, conforme descrito na <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">documentação do Pydantic: Schema customization</a>.
Você pode definir `schema_extra` com um `dict` contendo quaisquer dados adicionais que você queira que apareçam no JSON Schema gerado, incluindo `examples`.
////
/// tip | Dica
Você pode usar a mesma técnica para estender o JSON Schema e adicionar suas próprias informações extras de forma personalizada.
Você pode usar a mesma técnica para estender o JSON Schema e adicionar suas próprias informações extras personalizadas.
Por exemplo, você pode usar isso para adicionar metadados para uma interface de usuário de front-end, etc.
Por exemplo, você poderia usá-la para adicionar metadados para uma interface de usuário de front-end, etc.
///
## `Field` de argumentos adicionais
/// info | Informação
Ao usar `Field ()` com modelos Pydantic, você também pode declarar informações extras para o **JSON Schema** passando quaisquer outros argumentos arbitrários para a função.
O OpenAPI 3.1.0 (usado desde o FastAPI 0.99.0) adicionou suporte a `examples`, que faz parte do padrão **JSON Schema**.
Você pode usar isso para adicionar um `example` para cada campo:
Antes disso, ele suportava apenas a palavrachave `example` com um único exemplo. Isso ainda é suportado pelo OpenAPI 3.1.0, mas é descontinuado e não faz parte do padrão JSON Schema. Portanto, é recomendado migrar de `example` para `examples`. 🤓
{* ../../docs_src/schema_extra_example/tutorial002.py hl[4,10:13] *}
/// warning | Atenção
Lembre-se de que esses argumentos extras passados não adicionarão nenhuma validação, apenas informações extras, para fins de documentação.
Você pode ler mais no final desta página.
///
## `example` e `examples` no OpenAPI
## Argumentos adicionais de `Field` { #field-additional-arguments }
Ao usar quaisquer dos:
Ao usar `Field()` com modelos Pydantic, você também pode declarar `examples` adicionais:
{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *}
## `examples` no JSON Schema - OpenAPI { #examples-in-json-schema-openapi }
Ao usar qualquer um de:
* `Path()`
* `Query()`
@@ -46,65 +74,151 @@ Ao usar quaisquer dos:
* `Form()`
* `File()`
você também pode declarar um dado `example` ou um grupo de `examples` com informações adicionais que serão adicionadas ao **OpenAPI**.
você também pode declarar um grupo de `examples` com informações adicionais que serão adicionadas aos seus **JSON Schemas** dentro do **OpenAPI**.
### `Body` com `example`
### `Body` com `examples` { #body-with-examples }
Aqui nós passamos um `example` dos dados esperados por `Body()`:
Aqui passamos `examples` contendo um exemplo dos dados esperados em `Body()`:
{* ../../docs_src/schema_extra_example/tutorial003.py hl[21:26] *}
{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *}
### Exemplo na UI da documentação
### Exemplo na UI da documentação { #example-in-the-docs-ui }
Com qualquer um dos métodos acima, os `/docs` vão ficar assim:
Com qualquer um dos métodos acima, ficaria assim em `/docs`:
<img src="/img/tutorial/body-fields/image01.png">
### `Body` com vários `examples`
### `Body` com vários `examples` { #body-with-multiple-examples }
Alternativamente ao único `example`, você pode passar `examples` usando um `dict` com **vários examples**, cada um com informações extras que serão adicionadas no **OpenAPI** também.
Você também pode, é claro, passar vários `examples`:
{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *}
Quando fizer isso, os exemplos farão parte do **JSON Schema** interno para esses dados do body.
No entanto, <abbr title="2023-08-26">no momento em que isto foi escrito</abbr>, o Swagger UI, a ferramenta responsável por exibir a UI da documentação, não suporta mostrar vários exemplos para os dados no **JSON Schema**. Mas leia abaixo para uma solução alternativa.
### `examples` específicos do OpenAPI { #openapi-specific-examples }
Antes do **JSON Schema** suportar `examples`, o OpenAPI já tinha suporte para um campo diferente também chamado `examples`.
Esse `examples` específico do OpenAPI vai em outra seção da especificação. Ele fica nos **detalhes de cada função de operação de rota**, não dentro de cada JSON Schema.
E o Swagger UI tem suportado esse campo `examples` particular há algum tempo. Então, você pode usá-lo para **mostrar** diferentes **exemplos na UI da documentação**.
O formato desse campo `examples` específico do OpenAPI é um `dict` com **vários exemplos** (em vez de uma `list`), cada um com informações extras que também serão adicionadas ao **OpenAPI**.
Isso não vai dentro de cada JSON Schema contido no OpenAPI, vai fora, diretamente na *operação de rota*.
### Usando o parâmetro `openapi_examples` { #using-the-openapi-examples-parameter }
Você pode declarar o `examples` específico do OpenAPI no FastAPI com o parâmetro `openapi_examples` para:
* `Path()`
* `Query()`
* `Header()`
* `Cookie()`
* `Body()`
* `Form()`
* `File()`
As chaves do `dict` identificam cada exemplo, e cada valor é outro `dict`.
Cada `dict` de exemplo específico em `examples` pode conter:
* `summary`: Pequena descrição do exemplo.
* `summary`: Descrição curta do exemplo.
* `description`: Uma descrição longa que pode conter texto em Markdown.
* `value`: O próprio exemplo mostrado, ex: um `dict`.
* `externalValue`: alternativa ao `value`, uma URL apontando para o exemplo. Embora isso possa não ser suportado por tantas ferramentas quanto `value`.
* `value`: Este é o exemplo em si, por exemplo, um `dict`.
* `externalValue`: Alternativa a `value`, uma URL apontando para o exemplo. Embora isso possa não ser suportado por tantas ferramentas quanto `value`.
{* ../../docs_src/schema_extra_example/tutorial004.py hl[22:48] *}
Você pode usá-lo assim:
### Exemplos na UI da documentação
{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
Com `examples` adicionado a `Body()`, os `/docs` vão ficar assim:
### Exemplos do OpenAPI na UI da documentação { #openapi-examples-in-the-docs-ui }
Com `openapi_examples` adicionado a `Body()`, o `/docs` ficaria assim:
<img src="/img/tutorial/body-fields/image02.png">
## Detalhes técnicos
## Detalhes Técnicos { #technical-details }
/// warning | Atenção
/// tip | Dica
Esses são detalhes muito técnicos sobre os padrões **JSON Schema** e **OpenAPI**.
Se você já está usando o **FastAPI** na versão **0.99.0 ou superior**, você provavelmente pode **pular** esses detalhes.
Se as ideias explicadas acima já funcionam para você, isso pode ser o suficiente, e você provavelmente não precisa desses detalhes, fique à vontade para pular.
Eles são mais relevantes para versões antigas, antes de o OpenAPI 3.1.0 estar disponível.
Você pode considerar isto uma breve **aula de história** sobre OpenAPI e JSON Schema. 🤓
///
Quando você adiciona um exemplo dentro de um modelo Pydantic, usando `schema_extra` ou` Field(example="something") `esse exemplo é adicionado ao **JSON Schema** para esse modelo Pydantic.
/// warning | Atenção
E esse **JSON Schema** do modelo Pydantic está incluído no **OpenAPI** da sua API e, em seguida, é usado na UI da documentação.
Estes são detalhes muito técnicos sobre os padrões **JSON Schema** e **OpenAPI**.
O **JSON Schema** na verdade não tem um campo `example` nos padrões. Versões recentes do JSON Schema definem um campo <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a>, mas o OpenAPI 3.0.3 é baseado numa versão mais antiga do JSON Schema que não tinha `examples`.
Se as ideias acima já funcionam para você, isso pode ser suficiente, e você provavelmente não precisa desses detalhes, sinta-se à vontade para pular.
Por isso, o OpenAPI 3.0.3 definiu o seu próprio <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-20" class="external-link" target="_blank">`example`</a> para a versão modificada do **JSON Schema** que é usada, para o mesmo próposito (mas é apenas `example` no singular, não `examples`), e é isso que é usado pela UI da documentação da API(usando o Swagger UI).
///
Portanto, embora `example` não seja parte do JSON Schema, é parte da versão customizada do JSON Schema usada pelo OpenAPI, e é isso que vai ser usado dentro da UI de documentação.
Antes do OpenAPI 3.1.0, o OpenAPI usava uma versão mais antiga e modificada do **JSON Schema**.
Mas quando você usa `example` ou `examples` com qualquer um dos outros utilitários (`Query()`, `Body()`, etc.) esses exemplos não são adicionados ao JSON Schema que descreve esses dados (nem mesmo para versão própria do OpenAPI do JSON Schema), eles são adicionados diretamente à declaração da *operação de rota* no OpenAPI (fora das partes do OpenAPI que usam o JSON Schema).
O JSON Schema não tinha `examples`, então o OpenAPI adicionou seu próprio campo `example` à sua versão modificada.
Para `Path()`, `Query()`, `Header()`, e `Cookie()`, o `example` e `examples` são adicionados a <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameter-object" class="external-link" target="_blank">definição do OpenAPI, dentro do `Parameter Object` (na especificação)</a>.
O OpenAPI também adicionou os campos `example` e `examples` a outras partes da especificação:
E para `Body()`, `File()`, e `Form()`, o `example` e `examples` são de maneira equivalente adicionados para a <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject" class="external-link" target="_blank">definição do OpenAPI, dentro do `Request Body Object`, no campo `content`, no `Media Type Object` (na especificação)</a>.
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object" class="external-link" target="_blank">`Parameter Object` (na especificação)</a>, usado no FastAPI por:
* `Path()`
* `Query()`
* `Header()`
* `Cookie()`
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object" class="external-link" target="_blank">`Request Body Object`, no campo `content`, no `Media Type Object` (na especificação)</a>, usado no FastAPI por:
* `Body()`
* `File()`
* `Form()`
Por outro lado, há uma versão mais recente do OpenAPI: **3.1.0**, lançada recentemente. Baseado no JSON Schema mais recente e a maioria das modificações da versão customizada do OpenAPI do JSON Schema são removidas, em troca dos recursos das versões recentes do JSON Schema, portanto, todas essas pequenas diferenças são reduzidas. No entanto, a UI do Swagger atualmente não oferece suporte a OpenAPI 3.1.0, então, por enquanto, é melhor continuar usando as opções acima.
/// info | Informação
Esse parâmetro antigo `examples` específico do OpenAPI agora é `openapi_examples` desde o FastAPI `0.103.0`.
///
### Campo `examples` do JSON Schema { #json-schemas-examples-field }
Depois, o JSON Schema adicionou um campo <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a> em uma nova versão da especificação.
E então o novo OpenAPI 3.1.0 passou a se basear na versão mais recente (JSON Schema 2020-12), que incluiu esse novo campo `examples`.
Agora, esse novo campo `examples` tem precedência sobre o antigo (e customizado) campo único `example`, que agora está descontinuado.
Esse novo campo `examples` no JSON Schema é **apenas uma `list`** de exemplos, não um `dict` com metadados extras como nos outros lugares do OpenAPI (descritos acima).
/// info | Informação
Mesmo após o lançamento do OpenAPI 3.1.0 com essa nova integração mais simples com o JSON Schema, por um tempo o Swagger UI, a ferramenta que fornece a documentação automática, não suportava OpenAPI 3.1.0 (passou a suportar desde a versão 5.0.0 🎉).
Por causa disso, versões do FastAPI anteriores à 0.99.0 ainda usavam versões do OpenAPI inferiores à 3.1.0.
///
### `examples` no Pydantic e no FastAPI { #pydantic-and-fastapi-examples }
Quando você adiciona `examples` dentro de um modelo Pydantic, usando `schema_extra` ou `Field(examples=["something"])`, esse exemplo é adicionado ao **JSON Schema** para esse modelo Pydantic.
E esse **JSON Schema** do modelo Pydantic é incluído no **OpenAPI** da sua API e, então, é usado na UI da documentação.
Em versões do FastAPI anteriores à 0.99.0 (0.99.0 e superiores usam o novo OpenAPI 3.1.0), quando você usava `example` ou `examples` com qualquer uma das outras utilidades (`Query()`, `Body()`, etc.), esses exemplos não eram adicionados ao JSON Schema que descreve esses dados (nem mesmo à versão própria do JSON Schema do OpenAPI), eles eram adicionados diretamente à declaração da *operação de rota* no OpenAPI (fora das partes do OpenAPI que usam o JSON Schema).
Mas agora que o FastAPI 0.99.0 e superiores usam o OpenAPI 3.1.0, que usa o JSON Schema 2020-12, e o Swagger UI 5.0.0 e superiores, tudo é mais consistente e os exemplos são incluídos no JSON Schema.
### Swagger UI e `examples` específicos do OpenAPI { #swagger-ui-and-openapi-specific-examples }
Como o Swagger UI não suportava vários exemplos no JSON Schema (em 2023-08-26), os usuários não tinham uma forma de mostrar vários exemplos na documentação.
Para resolver isso, o FastAPI `0.103.0` **adicionou suporte** para declarar o mesmo antigo campo **específico do OpenAPI** `examples` com o novo parâmetro `openapi_examples`. 🤓
### Resumo { #summary }
Eu costumava dizer que não gostava tanto de história... e olha eu aqui agora dando aulas de "história tech". 😅
Em resumo, **atualize para o FastAPI 0.99.0 ou superior**, e as coisas ficam muito mais **simples, consistentes e intuitivas**, e você não precisa saber todos esses detalhes históricos. 😎

View File

@@ -1,53 +1,58 @@
# Segurança - Primeiros Passos
# Segurança - Primeiros Passos { #security-first-steps }
Vamos imaginar que você tem a sua API **backend** em algum domínio.
Vamos imaginar que você tem a sua API de **backend** em algum domínio.
E você tem um **frontend** em outro domínio ou em um path diferente no mesmo domínio (ou em uma aplicação mobile).
E você quer uma maneira de o frontend autenticar o backend, usando um **username** e **senha**.
E você quer uma maneira de o frontend autenticar com o backend, usando um **username** e **password**.
Nós podemos usar o **OAuth2** junto com o **FastAPI**.
Podemos usar **OAuth2** para construir isso com o **FastAPI**.
Mas, vamos poupar-lhe o tempo de ler toda a especificação apenas para achar as pequenas informações que você precisa.
Mas vamos poupar o seu tempo de ler toda a especificação extensa apenas para achar as pequenas informações de que você precisa.
Vamos usar as ferramentas fornecidas pela **FastAPI** para lidar com segurança.
Vamos usar as ferramentas fornecidas pelo **FastAPI** para lidar com segurança.
## Como Parece
## Como Parece { #how-it-looks }
Vamos primeiro usar o código e ver como funciona, e depois voltaremos para entender o que está acontecendo.
## Crie um `main.py`
## Crie um `main.py` { #create-main-py }
Copie o exemplo em um arquivo `main.py`:
{* ../../docs_src/security/tutorial001.py *}
{* ../../docs_src/security/tutorial001_an_py39.py *}
## Execute-o
## Execute-o { #run-it }
/// info | informação
/// info | Informação
O pacote <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a> é instalado automaticamente com o **FastAPI** quando você executa o comando `pip install "fastapi[standard]"`.
Entretanto, se você usar o comando `pip install fastapi`, o pacote `python-multipart` não é incluído por padrão.
Para instalá-lo manualmente, certifique-se de criar um [ambiente virtual](../../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalá-lo com:
```console
$ pip install python-multipart
```
Isso ocorre porque o **OAuth2** usa "form data" para enviar o `username` e o `password`.
///
Primeiro, instale <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>.
Ex: `pip install python-multipart`.
Isso ocorre porque o **OAuth2** usa "dados de um formulário" para mandar o **username** e **senha**.
Execute esse exemplo com:
Execute o exemplo com:
<div class="termy">
```console
$ uvicorn main:app --reload
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
## Verifique-o
## Verifique-o { #check-it }
Vá até a documentação interativa em: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
@@ -55,156 +60,144 @@ Você verá algo deste tipo:
<img src="/img/tutorial/security/image01.png">
/// check | Botão de Autorizar!
/// check | Botão Autorizar!
Você já tem um novo botão 'Authorize'.
E sua operação de rota tem um pequeno cadeado no canto superior direito em que você pode clicar.
///
Você já tem um novo "botão de autorizar!".
E seu *path operation* tem um pequeno cadeado no canto superior direito que você pode clicar.
E se você clicar, você terá um pequeno formulário de autorização para digitar o `username` e `senha` (e outros campos opcionais):
E se você clicar, verá um pequeno formulário de autorização para digitar um `username` e um `password` (e outros campos opcionais):
<img src="/img/tutorial/security/image02.png">
/// note | Nota
Não importa o que você digite no formulário, ainda não vai funcionar. Mas nós vamos chegar lá.
///
Não importa o que você digita no formulário, não vai funcionar ainda. Mas nós vamos chegar lá.
Claro que este não é o frontend para os usuários finais, mas é uma ótima ferramenta automática para documentar interativamente toda a sua API.
Claro que este não é o frontend para os usuários finais, mas é uma ótima ferramenta automática para documentar interativamente toda sua API.
Pode ser usada pelo time de frontend (que pode ser você mesmo).
Pode ser usado pelo time de frontend (que pode ser você no caso).
Pode ser usada por aplicações e sistemas de terceiros.
Pode ser usado por aplicações e sistemas third party (de terceiros).
E também pode ser usada por você mesmo, para depurar, verificar e testar a mesma aplicação.
E também pode ser usada por você mesmo, para debugar, checar e testar a mesma aplicação.
## O Fluxo da `senha`
## O fluxo de `password` { #the-password-flow }
Agora vamos voltar um pouco e entender o que é isso tudo.
O "fluxo" da `senha` é um dos caminhos ("fluxos") definidos no OAuth2, para lidar com a segurança e autenticação.
O "fluxo" `password` é uma das formas ("fluxos") definidas no OAuth2 para lidar com segurança e autenticação.
OAuth2 foi projetado para que o backend ou a API pudesse ser independente do servidor que autentica o usuário.
O OAuth2 foi projetado para que o backend ou a API pudesse ser independente do servidor que autentica o usuário.
Mas nesse caso, a mesma aplicação **FastAPI** irá lidar com a API e a autenticação.
Mas, neste caso, a mesma aplicação **FastAPI** irá lidar com a API e com a autenticação.
Então, vamos rever de um ponto de vista simplificado:
* O usuário digita o `username` e a `senha` no frontend e aperta `Enter`.
* O frontend (rodando no browser do usuário) manda o `username` e a `senha` para uma URL específica na sua API (declarada com `tokenUrl="token"`).
* A API checa aquele `username` e `senha`, e responde com um "token" (nós não implementamos nada disso ainda).
* Um "token" é apenas uma string com algum conteúdo que nós podemos utilizar mais tarde para verificar o usuário.
* Normalmente, um token é definido para expirar depois de um tempo.
* Então, o usuário terá que se logar de novo depois de um tempo.
* E se o token for roubado, o risco é menor. Não é como se fosse uma chave permanente que vai funcionar para sempre (na maioria dos casos).
* O frontend armazena aquele token temporariamente em algum lugar.
* O usuário clica no frontend para ir à outra seção daquele frontend do aplicativo web.
* O frontend precisa buscar mais dados daquela API.
* Mas precisa de autenticação para aquele endpoint em específico.
* Então, para autenticar com nossa API, ele manda um header de `Autorização` com o valor `Bearer` mais o token.
* Se o token contém `foobar`, o conteúdo do header de `Autorização` será: `Bearer foobar`.
* O usuário digita o `username` e o `password` no frontend e pressiona `Enter`.
* O frontend (rodando no navegador do usuário) envia esse `username` e `password` para uma URL específica na nossa API (declarada com `tokenUrl="token"`).
* A API verifica esse `username` e `password`, e responde com um "token" (ainda não implementamos nada disso).
* Um "token" é apenas uma string com algum conteúdo que podemos usar depois para verificar esse usuário.
* Normalmente, um token é definido para expirar depois de algum tempo.
* Então, o usuário terá que fazer login novamente em algum momento.
* E se o token for roubado, o risco é menor. Não é como uma chave permanente que funcionará para sempre (na maioria dos casos).
* O frontend armazena esse token temporariamente em algum lugar.
* O usuário clica no frontend para ir para outra seção do aplicativo web.
* O frontend precisa buscar mais dados da API.
* Mas precisa de autenticação para aquele endpoint específico.
* Então, para autenticar com nossa API, ele envia um header `Authorization` com o valor `Bearer ` mais o token.
* Se o token contém `foobar`, o conteúdo do header `Authorization` seria: `Bearer foobar`.
## **FastAPI**'s `OAuth2PasswordBearer`
## O `OAuth2PasswordBearer` do **FastAPI** { #fastapis-oauth2passwordbearer }
**FastAPI** fornece várias ferramentas, em diferentes níveis de abstração, para implementar esses recursos de segurança.
O **FastAPI** fornece várias ferramentas, em diferentes níveis de abstração, para implementar essas funcionalidades de segurança.
Neste exemplo, nós vamos usar o **OAuth2** com o fluxo de **Senha**, usando um token **Bearer**. Fazemos isso usando a classe `OAuth2PasswordBearer`.
Neste exemplo, vamos usar **OAuth2**, com o fluxo **Password**, usando um token **Bearer**. Fazemos isso usando a classe `OAuth2PasswordBearer`.
/// info | informação
/// info | Informação
Um token "bearer" não é a única opção.
Mas é a melhor para o nosso caso de uso.
E pode ser a melhor para a maioria dos casos de uso, a menos que você seja um especialista em OAuth2 e saiba exatamente por que existe outra opção que se adapta melhor às suas necessidades.
Nesse caso, o **FastAPI** também fornece as ferramentas para construí-la.
///
Um token "bearer" não é a única opção.
Quando criamos uma instância da classe `OAuth2PasswordBearer`, passamos o parâmetro `tokenUrl`. Esse parâmetro contém a URL que o client (o frontend rodando no navegador do usuário) usará para enviar o `username` e o `password` para obter um token.
Mas é a melhor no nosso caso.
E talvez seja a melhor para a maioria dos casos, a não ser que você seja um especialista em OAuth2 e saiba exatamente o porquê de existir outras opções que se adequam melhor às suas necessidades.
Nesse caso, **FastAPI** também fornece as ferramentas para construir.
Quando nós criamos uma instância da classe `OAuth2PasswordBearer`, nós passamos pelo parâmetro `tokenUrl` Esse parâmetro contém a URL que o client (o frontend rodando no browser do usuário) vai usar para mandar o `username` e `senha` para obter um token.
{* ../../docs_src/security/tutorial001.py hl[6] *}
{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
/// tip | Dica
Aqui `tokenUrl="token"` refere-se a uma URL relativa `token` que ainda não criamos. Como é uma URL relativa, é equivalente a `./token`.
Como estamos usando uma URL relativa, se sua API estivesse localizada em `https://example.com/`, então se referiria a `https://example.com/token`. Mas se sua API estivesse localizada em `https://example.com/api/v1/`, então se referiria a `https://example.com/api/v1/token`.
Usar uma URL relativa é importante para garantir que sua aplicação continue funcionando mesmo em um caso de uso avançado como [Atrás de um Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}.
///
Esse `tokenUrl="token"` se refere a uma URL relativa que nós não criamos ainda. Como é uma URL relativa, é equivalente a `./token`.
Esse parâmetro não cria aquele endpoint/operação de rota, mas declara que a URL `/token` será aquela que o client deve usar para obter o token. Essa informação é usada no OpenAPI e depois nos sistemas de documentação interativa da API.
Porque estamos usando uma URL relativa, se sua API estava localizada em `https://example.com/`, então irá referir-se à `https://example.com/token`. Mas se sua API estava localizada em `https://example.com/api/v1/`, então irá referir-se à `https://example.com/api/v1/token`.
Em breve também criaremos a operação de rota real.
Usar uma URL relativa é importante para garantir que sua aplicação continue funcionando, mesmo em um uso avançado tipo [Atrás de um Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}.
Esse parâmetro não cria um endpoint / *path operation*, mas declara que a URL `/token` vai ser aquela que o client deve usar para obter o token. Essa informação é usada no OpenAPI, e depois na API Interativa de documentação de sistemas.
Em breve também criaremos o atual path operation.
/// info | informação
/// info | Informação
Se você é um "Pythonista" muito rigoroso, pode não gostar do estilo do nome do parâmetro `tokenUrl` em vez de `token_url`.
Isso ocorre porque ele usa o mesmo nome da especificação do OpenAPI. Assim, se você precisar investigar mais sobre qualquer um desses esquemas de segurança, pode simplesmente copiar e colar para encontrar mais informações sobre isso.
///
Se você é um "Pythonista" muito rigoroso, você pode não gostar do estilo do nome do parâmetro `tokenUrl` em vez de `token_url`.
A variável `oauth2_scheme` é uma instância de `OAuth2PasswordBearer`, mas também é "chamável" (callable).
Isso ocorre porque está utilizando o mesmo nome que está nas especificações do OpenAPI. Então, se você precisa investigar mais sobre qualquer um desses esquemas de segurança, você pode simplesmente copiar e colar para encontrar mais informações sobre isso.
A variável `oauth2_scheme` é um instância de `OAuth2PasswordBearer`, mas também é um "callable".
Pode ser chamada de:
Ela pode ser chamada como:
```Python
oauth2_scheme(some, parameters)
```
Então, pode ser usado com `Depends`.
Então, pode ser usada com `Depends`.
## Use-o
### Use-o { #use-it }
Agora você pode passar aquele `oauth2_scheme` em uma dependência com `Depends`.
Agora você pode passar esse `oauth2_scheme` em uma dependência com `Depends`.
{* ../../docs_src/security/tutorial001.py hl[10] *}
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
Esse dependência vai fornecer uma `str` que é atribuído ao parâmetro `token da *função do path operation*
Essa dependência fornecerá uma `str` que é atribuída ao parâmetro `token` da função de operação de rota.
A **FastAPI** saberá que pode usar essa dependência para definir um "esquema de segurança" no esquema da OpenAPI (e na documentação da API automática).
O **FastAPI** saberá que pode usar essa dependência para definir um "esquema de segurança" no esquema OpenAPI (e na documentação automática da API).
/// info | Detalhes técnicos
/// info | Detalhes Técnicos
O **FastAPI** saberá que pode usar a classe `OAuth2PasswordBearer` (declarada em uma dependência) para definir o esquema de segurança no OpenAPI porque ela herda de `fastapi.security.oauth2.OAuth2`, que por sua vez herda de `fastapi.security.base.SecurityBase`.
Todos os utilitários de segurança que se integram com o OpenAPI (e com a documentação automática da API) herdam de `SecurityBase`, é assim que o **FastAPI** sabe como integrá-los ao OpenAPI.
///
**FastAPI** saberá que pode usar a classe `OAuth2PasswordBearer` (declarada na dependência) para definir o esquema de segurança na OpenAPI porque herda de `fastapi.security.oauth2.OAuth2`, que por sua vez herda de `fastapi.security.base.Securitybase`.
## O que ele faz { #what-it-does }
Todos os utilitários de segurança que se integram com OpenAPI (e na documentação da API automática) herdam de `SecurityBase`, é assim que **FastAPI** pode saber como integrá-los no OpenAPI.
Ele irá procurar na requisição pelo header `Authorization`, verificar se o valor é `Bearer ` mais algum token e retornará o token como uma `str`.
## O que ele faz
Se não houver um header `Authorization`, ou se o valor não tiver um token `Bearer `, ele responderá diretamente com um erro de status 401 (`UNAUTHORIZED`).
Ele irá e olhará na requisição para aquele header de `Autorização`, verificará se o valor é `Bearer` mais algum token, e vai retornar o token como uma `str`
Se ele não ver o header de `Autorização` ou o valor não tem um token `Bearer`, vai responder com um código de erro 401 (`UNAUTHORIZED`) diretamente.
Você nem precisa verificar se o token existe para retornar um erro. Você pode ter certeza de que se a sua função for executada, ela terá um `str` nesse token.
Você nem precisa verificar se o token existe para retornar um erro. Você pode ter certeza de que, se sua função for executada, ela terá uma `str` nesse token.
Você já pode experimentar na documentação interativa:
<img src="/img/tutorial/security/image03.png">
Não estamos verificando a validade do token ainda, mas isso já é um começo
Ainda não estamos verificando a validade do token, mas isso já é um começo.
## Recapitulando
## Recapitulando { #recap }
Então, em apenas 3 ou 4 linhas extras, você já tem alguma forma primitiva de segurança.
Então, com apenas 3 ou 4 linhas extras, você já tem alguma forma primitiva de segurança.

View File

@@ -1,105 +1,105 @@
# Obter Usuário Atual
No capítulo anterior, o sistema de segurança (que é baseado no sistema de injeção de dependências) estava fornecendo à *função de operação de rota* um `token` como uma `str`:
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
Mas isso ainda não é tão útil.
Vamos fazer com que ele nos forneça o usuário atual.
## Criar um modelo de usuário
Primeiro, vamos criar um modelo de usuário com Pydantic.
Da mesma forma que usamos o Pydantic para declarar corpos, podemos usá-lo em qualquer outro lugar:
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *}
## Criar uma dependência `get_current_user`
Vamos criar uma dependência chamada `get_current_user`.
Lembra que as dependências podem ter subdependências?
`get_current_user` terá uma dependência com o mesmo `oauth2_scheme` que criamos antes.
Da mesma forma que estávamos fazendo antes diretamente na *operação de rota*, a nossa nova dependência `get_current_user` receberá um `token` como uma `str` da subdependência `oauth2_scheme`:
{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *}
## Obter o usuário
`get_current_user` usará uma função utilitária (falsa) que criamos, que recebe um token como uma `str` e retorna nosso modelo Pydantic `User`:
{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *}
## Injetar o usuário atual
Então agora nós podemos usar o mesmo `Depends` com nosso `get_current_user` na *operação de rota*:
{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *}
Observe que nós declaramos o tipo de `current_user` como o modelo Pydantic `User`.
Isso nos ajudará dentro da função com todo o preenchimento automático e verificações de tipo.
/// tip | Dica
Você pode se lembrar que corpos de requisição também são declarados com modelos Pydantic.
Aqui, o **FastAPI** não ficará confuso porque você está usando `Depends`.
///
/// check | Verifique
A forma como esse sistema de dependências foi projetado nos permite ter diferentes dependências (diferentes "dependables") que retornam um modelo `User`.
Não estamos restritos a ter apenas uma dependência que possa retornar esse tipo de dado.
///
## Outros modelos
Agora você pode obter o usuário atual diretamente nas *funções de operação de rota* e lidar com os mecanismos de segurança no nível da **Injeção de Dependências**, usando `Depends`.
E você pode usar qualquer modelo ou dado para os requisitos de segurança (neste caso, um modelo Pydantic `User`).
Mas você não está restrito a usar um modelo de dados, classe ou tipo específico.
Você quer ter apenas um `id` e `email`, sem incluir nenhum `username` no modelo? Claro. Você pode usar essas mesmas ferramentas.
Você quer ter apenas uma `str`? Ou apenas um `dict`? Ou uma instância de modelo de classe de banco de dados diretamente? Tudo funciona da mesma forma.
Na verdade, você não tem usuários que fazem login no seu aplicativo, mas sim robôs, bots ou outros sistemas, que possuem apenas um token de acesso? Novamente, tudo funciona da mesma forma.
Apenas use qualquer tipo de modelo, qualquer tipo de classe, qualquer tipo de banco de dados que você precise para a sua aplicação. O **FastAPI** cobre tudo com o sistema de injeção de dependências.
## Tamanho do código
Este exemplo pode parecer verboso. Lembre-se de que estamos misturando segurança, modelos de dados, funções utilitárias e *operações de rota* no mesmo arquivo.
Mas aqui está o ponto principal.
O código relacionado à segurança e à injeção de dependências é escrito apenas uma vez.
E você pode torná-lo tão complexo quanto quiser. E ainda assim, tê-lo escrito apenas uma vez, em um único lugar. Com toda a flexibilidade.
Mas você pode ter milhares de endpoints (*operações de rota*) usando o mesmo sistema de segurança.
E todos eles (ou qualquer parte deles que você desejar) podem aproveitar o reuso dessas dependências ou de quaisquer outras dependências que você criar.
E todos esses milhares de *operações de rota* podem ter apenas 3 linhas:
{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *}
## Recapitulação
Agora você pode obter o usuário atual diretamente na sua *função de operação de rota*.
Já estamos na metade do caminho.
Só precisamos adicionar uma *operação de rota* para que o usuário/cliente realmente envie o `username` e `password`.
# Obter Usuário Atual { #get-current-user }
No capítulo anterior, o sistema de segurança (que é baseado no sistema de injeção de dependências) estava fornecendo à *função de operação de rota* um `token` como uma `str`:
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
Mas isso ainda não é tão útil.
Vamos fazer com que ele nos forneça o usuário atual.
## Criar um modelo de usuário { #create-a-user-model }
Primeiro, vamos criar um modelo de usuário com Pydantic.
Da mesma forma que usamos o Pydantic para declarar corpos, podemos usá-lo em qualquer outro lugar:
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *}
## Criar uma dependência `get_current_user` { #create-a-get-current-user-dependency }
Vamos criar uma dependência chamada `get_current_user`.
Lembra que as dependências podem ter subdependências?
`get_current_user` terá uma dependência com o mesmo `oauth2_scheme` que criamos antes.
Da mesma forma que estávamos fazendo antes diretamente na *operação de rota*, a nossa nova dependência `get_current_user` receberá um `token` como uma `str` da subdependência `oauth2_scheme`:
{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *}
## Obter o usuário { #get-the-user }
`get_current_user` usará uma função utilitária (falsa) que criamos, que recebe um token como uma `str` e retorna nosso modelo Pydantic `User`:
{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *}
## Injetar o usuário atual { #inject-the-current-user }
Então agora nós podemos usar o mesmo `Depends` com nosso `get_current_user` na *operação de rota*:
{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *}
Observe que nós declaramos o tipo de `current_user` como o modelo Pydantic `User`.
Isso nos ajudará dentro da função com todo o preenchimento automático e verificações de tipo.
/// tip | Dica
Você pode se lembrar que corpos de requisição também são declarados com modelos Pydantic.
Aqui, o **FastAPI** não ficará confuso porque você está usando `Depends`.
///
/// check | Verifique
A forma como esse sistema de dependências foi projetado nos permite ter diferentes dependências (diferentes "dependables") que retornam um modelo `User`.
Não estamos restritos a ter apenas uma dependência que possa retornar esse tipo de dado.
///
## Outros modelos { #other-models }
Agora você pode obter o usuário atual diretamente nas *funções de operação de rota* e lidar com os mecanismos de segurança no nível da **Injeção de Dependências**, usando `Depends`.
E você pode usar qualquer modelo ou dado para os requisitos de segurança (neste caso, um modelo Pydantic `User`).
Mas você não está restrito a usar um modelo de dados, classe ou tipo específico.
Você quer ter apenas um `id` e `email`, sem incluir nenhum `username` no modelo? Claro. Você pode usar essas mesmas ferramentas.
Você quer ter apenas uma `str`? Ou apenas um `dict`? Ou uma instância de modelo de classe de banco de dados diretamente? Tudo funciona da mesma forma.
Na verdade, você não tem usuários que fazem login no seu aplicativo, mas sim robôs, bots ou outros sistemas, que possuem apenas um token de acesso? Novamente, tudo funciona da mesma forma.
Apenas use qualquer tipo de modelo, qualquer tipo de classe, qualquer tipo de banco de dados que você precise para a sua aplicação. O **FastAPI** cobre tudo com o sistema de injeção de dependências.
## Tamanho do código { #code-size }
Este exemplo pode parecer verboso. Lembre-se de que estamos misturando segurança, modelos de dados, funções utilitárias e *operações de rota* no mesmo arquivo.
Mas aqui está o ponto principal.
O código relacionado à segurança e à injeção de dependências é escrito apenas uma vez.
E você pode torná-lo tão complexo quanto quiser. E ainda assim, tê-lo escrito apenas uma vez, em um único lugar. Com toda a flexibilidade.
Mas você pode ter milhares de endpoints (*operações de rota*) usando o mesmo sistema de segurança.
E todos eles (ou qualquer parte deles que você desejar) podem aproveitar o reuso dessas dependências ou de quaisquer outras dependências que você criar.
E todos esses milhares de *operações de rota* podem ter apenas 3 linhas:
{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *}
## Recapitulação { #recap }
Agora você pode obter o usuário atual diretamente na sua *função de operação de rota*.
Já estamos na metade do caminho.
Só precisamos adicionar uma *operação de rota* para que o usuário/cliente realmente envie o `username` e `password`.
Isso vem a seguir.

View File

@@ -1,4 +1,4 @@
# OAuth2 com Senha (e hashing), Bearer com tokens JWT
# OAuth2 com Senha (e hashing), Bearer com tokens JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens }
Agora que temos todo o fluxo de segurança, vamos tornar a aplicação realmente segura, usando tokens <abbr title="JSON Web Tokens">JWT</abbr> e hashing de senhas seguras.
@@ -6,7 +6,7 @@ Este código é algo que você pode realmente usar na sua aplicação, salvar os
Vamos começar de onde paramos no capítulo anterior e incrementá-lo.
## Sobre o JWT
## Sobre o JWT { #about-jwt }
JWT significa "JSON Web Tokens".
@@ -26,7 +26,7 @@ Depois de uma semana, o token expirará e o usuário não estará autorizado, pr
Se você quiser brincar com tokens JWT e ver como eles funcionam, visite <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>.
## Instalar `PyJWT`
## Instalar `PyJWT` { #install-pyjwt }
Nós precisamos instalar o `PyJWT` para criar e verificar os tokens JWT em Python.
@@ -50,7 +50,7 @@ Você pode ler mais sobre isso na <a href="https://pyjwt.readthedocs.io/en/lates
///
## Hashing de senhas
## Hashing de senhas { #password-hashing }
"Hashing" significa converter algum conteúdo (uma senha neste caso) em uma sequência de bytes (apenas uma string) que parece um monte de caracteres sem sentido.
@@ -58,26 +58,26 @@ Sempre que você passar exatamente o mesmo conteúdo (exatamente a mesma senha),
Mas não é possível converter os caracteres sem sentido de volta para a senha original.
### Por que usar hashing de senhas
### Por que usar hashing de senhas { #why-use-password-hashing }
Se o seu banco de dados for roubado, o invasor não terá as senhas em texto puro dos seus usuários, apenas os hashes.
Então, o invasor não poderá tentar usar essas senhas em outro sistema (como muitos usuários utilizam a mesma senha em vários lugares, isso seria perigoso).
## Instalar o `passlib`
## Instalar o `pwdlib` { #install-pwdlib }
O PassLib é uma excelente biblioteca Python para lidar com hashes de senhas.
pwdlib é um excelente pacote Python para lidar com hashes de senhas.
Ele suporta muitos algoritmos de hashing seguros e utilitários para trabalhar com eles.
O algoritmo recomendado é o "Bcrypt".
O algoritmo recomendado é o "Argon2".
Certifique-se de criar um [ambiente virtual](../../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar o PassLib com Bcrypt:
Certifique-se de criar um [ambiente virtual](../../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar o pwdlib com Argon2:
<div class="termy">
```console
$ pip install "passlib[bcrypt]"
$ pip install "pwdlib[argon2]"
---> 100%
```
@@ -86,7 +86,7 @@ $ pip install "passlib[bcrypt]"
/// tip | Dica
Com o `passlib`, você poderia até configurá-lo para ser capaz de ler senhas criadas pelo **Django**, um plug-in de segurança do **Flask** ou muitos outros.
Com o `pwdlib`, você poderia até configurá-lo para ser capaz de ler senhas criadas pelo **Django**, um plug-in de segurança do **Flask** ou muitos outros.
Assim, você poderia, por exemplo, compartilhar os mesmos dados de um aplicativo Django em um banco de dados com um aplicativo FastAPI. Ou migrar gradualmente uma aplicação Django usando o mesmo banco de dados.
@@ -94,17 +94,17 @@ E seus usuários poderiam fazer login tanto pela sua aplicação Django quanto p
///
## Criar o hash e verificar as senhas
## Criar o hash e verificar as senhas { #hash-and-verify-the-passwords }
Importe as ferramentas que nós precisamos de `passlib`.
Importe as ferramentas que nós precisamos de `pwdlib`.
Crie um "contexto" do PassLib. Este será usado para criar o hash e verificar as senhas.
Crie uma instância de PasswordHash com as configurações recomendadas ela será usada para criar o hash e verificar as senhas.
/// tip | Dica
O contexto do PassLib também possui funcionalidades para usar diferentes algoritmos de hashing, incluindo algoritmos antigos que estão obsoletos, apenas para permitir verificá-los, etc.
pwdlib também oferece suporte ao algoritmo de hashing bcrypt, mas não inclui algoritmos legados para trabalhar com hashes antigos, é recomendado usar a biblioteca passlib.
Por exemplo, você poderia usá-lo para ler e verificar senhas geradas por outro sistema (como Django), mas criar o hash de novas senhas com um algoritmo diferente, como o Bcrypt.
Por exemplo, você poderia usá-lo para ler e verificar senhas geradas por outro sistema (como Django), mas criar o hash de novas senhas com um algoritmo diferente, como o Argon2 ou o Bcrypt.
E ser compatível com todos eles ao mesmo tempo.
@@ -120,11 +120,11 @@ E outra para autenticar e retornar um usuário.
/// note | Nota
Se você verificar o novo banco de dados (falso) `fake_users_db`, você verá como o hash da senha se parece agora: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
Se você verificar o novo banco de dados (falso) `fake_users_db`, você verá como o hash da senha se parece agora: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`.
///
## Manipular tokens JWT
## Manipular tokens JWT { #handle-jwt-tokens }
Importe os módulos instalados.
@@ -154,7 +154,7 @@ Crie uma função utilitária para gerar um novo token de acesso.
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
## Atualize as dependências
## Atualize as dependências { #update-the-dependencies }
Atualize `get_current_user` para receber o mesmo token de antes, mas desta vez, usando tokens JWT.
@@ -164,7 +164,7 @@ Se o token for inválido, retorne um erro HTTP imediatamente.
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
## Atualize a *operação de rota* `/token`
## Atualize a *operação de rota* `/token` { #update-the-token-path-operation }
Crie um `timedelta` com o tempo de expiração do token.
@@ -172,7 +172,7 @@ Crie um token de acesso JWT real e o retorne.
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
### Detalhes técnicos sobre o "sujeito" `sub` do JWT
### Detalhes técnicos sobre o "sujeito" `sub` do JWT { #technical-details-about-the-jwt-subject-sub }
A especificação JWT diz que existe uma chave `sub`, com o sujeito do token.
@@ -194,7 +194,7 @@ Então, para evitar colisões de ID, ao criar o token JWT para o usuário, você
O importante a se lembrar é que a chave `sub` deve ter um identificador único em toda a aplicação e deve ser uma string.
## Testando
## Verifique { #check-it }
Execute o servidor e vá para a documentação: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
@@ -240,7 +240,7 @@ Perceba que o cabeçalho `Authorization`, com o valor que começa com `Bearer `.
///
## Uso avançado com `scopes`
## Uso avançado com `scopes` { #advanced-usage-with-scopes }
O OAuth2 tem a noção de "scopes" (escopos).
@@ -250,8 +250,7 @@ Então, você pode dar este token diretamente a um usuário ou a uma terceira pa
Você pode aprender como usá-los e como eles são integrados ao **FastAPI** mais adiante no **Guia Avançado do Usuário**.
## Recapitulação
## Recapitulação { #recap }
Com o que você viu até agora, você pode configurar uma aplicação **FastAPI** segura usando padrões como OAuth2 e JWT.
@@ -265,7 +264,7 @@ O **FastAPI** não faz nenhuma concessão com nenhum banco de dados, modelo de d
Ele oferece toda a flexibilidade para você escolher as opções que melhor se ajustam ao seu projeto.
E você pode usar diretamente muitos pacotes bem mantidos e amplamente utilizados, como `passlib` e `PyJWT`, porque o **FastAPI** não exige mecanismos complexos para integrar pacotes externos.
E você pode usar diretamente muitos pacotes bem mantidos e amplamente utilizados, como `pwdlib` e `PyJWT`, porque o **FastAPI** não exige mecanismos complexos para integrar pacotes externos.
Mas ele fornece as ferramentas para simplificar o processo o máximo possível, sem comprometer a flexibilidade, robustez ou segurança.

View File

@@ -1,8 +1,8 @@
# Simples OAuth2 com senha e Bearer
# Simples OAuth2 com senha e Bearer { #simple-oauth2-with-password-and-bearer }
Agora vamos construir a partir do capítulo anterior e adicionar as partes que faltam para ter um fluxo de segurança completo.
## Pegue o `username` (nome de usuário) e `password` (senha)
## Obtenha o `username` e a `password` { #get-the-username-and-password }
É utilizado o utils de segurança da **FastAPI** para obter o `username` e a `password`.
@@ -18,9 +18,9 @@ Mas para a *operação de rota* de login, precisamos usar esses nomes para serem
A especificação também afirma que o `username` e a `password` devem ser enviados como dados de formulário (portanto, não há JSON aqui).
### `scope`
### `scope` { #scope }
A especificação também diz que o cliente pode enviar outro campo de formulário "`scope`" (Escopo).
A especificação também diz que o cliente pode enviar outro campo de formulário "`scope`".
O nome do campo do formulário é `scope` (no singular), mas na verdade é uma longa string com "escopos" separados por espaços.
@@ -44,11 +44,11 @@ Para OAuth2 são apenas strings.
///
## Código para conseguir o `username` e a `password`
## Código para conseguir o `username` e a `password` { #code-to-get-the-username-and-password }
Agora vamos usar os utilitários fornecidos pelo **FastAPI** para lidar com isso.
### `OAuth2PasswordRequestForm`
### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform }
Primeiro, importe `OAuth2PasswordRequestForm` e use-o como uma dependência com `Depends` na *operação de rota* para `/token`:
@@ -59,7 +59,7 @@ Primeiro, importe `OAuth2PasswordRequestForm` e use-o como uma dependência com
* O `username`.
* A `password`.
* Um campo `scope` opcional como uma string grande, composta de strings separadas por espaços.
* Um `grant_type` (tipo de concessão) opcional.
* Um `grant_type` opcional.
/// tip | Dica
@@ -84,7 +84,7 @@ Mas como é um caso de uso comum, ele é fornecido diretamente pelo **FastAPI**,
///
### Use os dados do formulário
### Use os dados do formulário { #use-the-form-data }
/// tip | Dica
@@ -96,13 +96,13 @@ Não estamos usando `scopes` neste exemplo, mas a funcionalidade está disponív
Agora, obtenha os dados do usuário do banco de dados (falso), usando o `username` do campo do formulário.
Se não existir tal usuário, retornaremos um erro dizendo "Incorrect username or password" (Nome de usuário ou senha incorretos).
Se não existir tal usuário, retornaremos um erro dizendo "Incorrect username or password".
Para o erro, usamos a exceção `HTTPException`:
{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *}
### Confira a password (senha)
### Confira a senha { #check-the-password }
Neste ponto temos os dados do usuário do nosso banco de dados, mas não verificamos a senha.
@@ -112,7 +112,7 @@ Você nunca deve salvar senhas em texto simples, portanto, usaremos o sistema de
Se as senhas não corresponderem, retornaremos o mesmo erro.
#### Hashing de senha
#### Hashing de senha { #password-hashing }
"Hashing" significa: converter algum conteúdo (uma senha neste caso) em uma sequência de bytes (apenas uma string) que parece algo sem sentido.
@@ -120,7 +120,7 @@ Sempre que você passa exatamente o mesmo conteúdo (exatamente a mesma senha),
Mas você não pode converter a sequência aleatória de caracteres de volta para a senha.
##### Porque usar hashing de senha
##### Porque usar hashing de senha { #why-use-password-hashing }
Se o seu banco de dados for roubado, o ladrão não terá as senhas em texto simples dos seus usuários, apenas os hashes.
@@ -128,11 +128,11 @@ Assim, o ladrão não poderá tentar usar essas mesmas senhas em outro sistema (
{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *}
#### Sobre `**user_dict`
#### Sobre `**user_dict` { #about-user-dict }
`UserInDB(**user_dict)` significa:
*Passe as keys (chaves) e values (valores) de `user_dict` diretamente como argumentos de valor-chave, equivalente a:*
*Passe as chaves e valores de `user_dict` diretamente como argumentos de valor-chave, equivalente a:*
```Python
UserInDB(
@@ -146,11 +146,11 @@ UserInDB(
/// info | Informação
Para uma explicação mais completa de `**user_dict`, verifique [a documentação para **Extra Models**](../extra-models.md#about-user_indict){.internal-link target=_blank}.
Para uma explicação mais completa de `**user_dict`, verifique [a documentação para **Extra Models**](../extra-models.md#about-user-in-dict){.internal-link target=_blank}.
///
## Retorne o token
## Retorne o token { #return-the-token }
A resposta do endpoint `token` deve ser um objeto JSON.
@@ -182,11 +182,11 @@ De resto, **FastAPI** cuida disso para você.
///
## Atualize as dependências
## Atualize as dependências { #update-the-dependencies }
Agora vamos atualizar nossas dependências.
Queremos obter o `user_user` *somente* se este usuário estiver ativo.
Queremos obter o `current_user` *somente* se este usuário estiver ativo.
Portanto, criamos uma dependência adicional `get_current_active_user` que por sua vez usa `get_current_user` como dependência.
@@ -214,11 +214,11 @@ Esse é o benefício dos padrões...
///
## Veja em ação
## Veja em ação { #see-it-in-action }
Abra o docs interativo: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
### Autenticação
### Autentique-se { #authenticate }
Clique no botão "Authorize".
@@ -234,7 +234,7 @@ Após autenticar no sistema, você verá assim:
<img src="/img/tutorial/security/image05.png">
### Obtenha seus próprios dados de usuário
### Obtenha seus próprios dados de usuário { #get-your-own-user-data }
Agora use a operação `GET` com o caminho `/users/me`.
@@ -260,7 +260,7 @@ Se você clicar no ícone de cadeado, sair e tentar a mesma operação novamente
}
```
### Usuário inativo
### Usuário inativo { #inactive-user }
Agora tente com um usuário inativo, autentique-se com:
@@ -278,7 +278,7 @@ Você receberá um erro "Usuário inativo", como:
}
```
## Recaptulando
## Recapitulando { #recap }
Agora você tem as ferramentas para implementar um sistema de segurança completo baseado em `username` e `password` para sua API.

View File

@@ -1,4 +1,4 @@
# Bancos de Dados SQL (Relacionais)
# Bancos de Dados SQL (Relacionais) { #sql-relational-databases }
**FastAPI** não exige que você use um banco de dados SQL (relacional). Mas você pode usar **qualquer banco de dados** que quiser.
@@ -8,7 +8,7 @@ Aqui veremos um exemplo usando <a href="https://sqlmodel.tiangolo.com/" class="e
/// tip | Dica
Você pode usar qualquer outra biblioteca de banco de dados SQL ou NoSQL que quiser (em alguns casos chamadas de <abbr title="Object Relational Mapper, um termo sofisticado para uma biblioteca onde algumas classes representam tabelas SQL e instâncias representam linhas nessas tabelas">"ORMs"</abbr>), o FastAPI não obriga você a usar nada. 😎
Você pode usar qualquer outra biblioteca de banco de dados SQL ou NoSQL que quiser (em alguns casos chamadas de <abbr title="Object Relational Mapper Mapeador Objeto-Relacional: um termo sofisticado para uma biblioteca onde algumas classes representam tabelas SQL e instâncias representam linhas nessas tabelas">"ORMs"</abbr>), o FastAPI não obriga você a usar nada. 😎
///
@@ -32,7 +32,7 @@ Existe um gerador de projetos oficial com **FastAPI** e **PostgreSQL** incluindo
Este é um tutorial muito simples e curto, se você quiser aprender sobre bancos de dados em geral, sobre SQL ou recursos mais avançados, acesse a <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">documentação do SQLModel</a>.
## Instalar o `SQLModel`
## Instalar o `SQLModel` { #install-sqlmodel }
Primeiro, certifique-se de criar seu [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e, em seguida, instalar o `sqlmodel`:
@@ -45,13 +45,13 @@ $ pip install sqlmodel
</div>
## Criar o App com um Único Modelo
## Criar o App com um Único Modelo { #create-the-app-with-a-single-model }
Vamos criar a primeira versão mais simples do app com um único modelo **SQLModel**.
Depois, vamos melhorá-lo aumentando a segurança e versatilidade com **múltiplos modelos** abaixo. 🤓
### Criar Modelos
### Criar Modelos { #create-models }
Importe o `SQLModel` e crie um modelo de banco de dados:
@@ -71,7 +71,7 @@ Existem algumas diferenças:
O SQLModel saberá que algo declarado como `str` será uma coluna SQL do tipo `TEXT` (ou `VARCHAR`, dependendo do banco de dados).
### Criar um Engine
### Criar um Engine { #create-an-engine }
Um `engine` SQLModel (por baixo dos panos, ele é na verdade um `engine` do SQLAlchemy) é o que **mantém as conexões** com o banco de dados.
Você teria **um único objeto `engine`** para todo o seu código se conectar ao mesmo banco de dados.
@@ -82,13 +82,13 @@ Usar `check_same_thread=False` permite que o FastAPI use o mesmo banco de dados
Não se preocupe, com a forma como o código está estruturado, garantiremos que usamos **uma única *sessão* SQLModel por requisição** mais tarde, isso é realmente o que o `check_same_thread` está tentando conseguir.
### Criar as Tabelas
### Criar as Tabelas { #create-the-tables }
Em seguida, adicionamos uma função que usa `SQLModel.metadata.create_all(engine)` para **criar as tabelas** para todos os *modelos de tabela*.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *}
### Criar uma Dependência de Sessão
### Criar uma Dependência de Sessão { #create-a-session-dependency }
Uma **`Session`** é o que armazena os **objetos na memória** e acompanha as alterações necessárias nos dados, para então **usar o `engine`** para se comunicar com o banco de dados.
@@ -98,7 +98,7 @@ Então, criamos uma dependência `Annotated` chamada `SessionDep` para simplific
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *}
### Criar Tabelas de Banco de Dados na Inicialização
### Criar Tabelas de Banco de Dados na Inicialização { #create-database-tables-on-startup }
Vamos criar as tabelas do banco de dados quando o aplicativo for iniciado.
@@ -114,7 +114,7 @@ O SQLModel terá utilitários de migração envolvendo o Alembic, mas por enquan
///
### Criar um Hero
### Criar um Hero { #create-a-hero }
Como cada modelo SQLModel também é um modelo Pydantic, você pode usá-lo nas mesmas **anotações de tipo** que usaria para modelos Pydantic.
@@ -124,29 +124,27 @@ Da mesma forma, você pode declará-lo como o **tipo de retorno** da função, e
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *}
</details>
Aqui, usamos a dependência `SessionDep` (uma `Session`) para adicionar o novo `Hero` à instância `Session`, fazer commit das alterações no banco de dados, atualizar os dados no `hero` e então retorná-lo.
### Ler Heroes
### Ler Heroes { #read-heroes }
Podemos **ler** `Hero`s do banco de dados usando um `select()`. Podemos incluir um `limit` e `offset` para paginar os resultados.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *}
### Ler um Único Hero
### Ler um Único Hero { #read-one-hero }
Podemos **ler** um único `Hero`.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *}
### Deletar um Hero
### Deletar um Hero { #delete-a-hero }
Também podemos **deletar** um `Hero`.
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *}
### Executar o App
### Executar o App { #run-the-app }
Você pode executar o app:
@@ -166,7 +164,7 @@ Então, vá para a interface `/docs`, você verá que o **FastAPI** está usando
<img src="/img/tutorial/sql-databases/image01.png">
</div>
## Atualizar o App com Múltiplos Modelos
## Atualizar o App com Múltiplos Modelos { #update-the-app-with-multiple-models }
Agora vamos **refatorar** este app um pouco para aumentar a **segurança** e **versatilidade**.
@@ -178,7 +176,7 @@ Além disso, criamos um `secret_name` para o hero, mas até agora estamos retorn
Vamos corrigir essas coisas adicionando alguns **modelos extras**. Aqui é onde o SQLModel vai brilhar. ✨
### Criar Múltiplos Modelos
### Criar Múltiplos Modelos { #create-multiple-models }
No **SQLModel**, qualquer classe de modelo que tenha `table=True` é um **modelo de tabela**.
@@ -186,7 +184,7 @@ E qualquer classe de modelo que não tenha `table=True` é um **modelo de dados*
Com o SQLModel, podemos usar a **herança** para **evitar duplicação** de todos os campos em todos os casos.
#### `HeroBase` - a classe base
#### `HeroBase` - a classe base { #herobase-the-base-class }
Vamos começar com um modelo `HeroBase` que tem todos os **campos compartilhados** por todos os modelos:
@@ -195,7 +193,7 @@ Vamos começar com um modelo `HeroBase` que tem todos os **campos compartilhados
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *}
#### `Hero` - o *modelo de tabela*
#### `Hero` - o *modelo de tabela* { #hero-the-table-model }
Em seguida, vamos criar `Hero`, o verdadeiro *modelo de tabela*, com os **campos extras** que nem sempre estão nos outros modelos:
@@ -211,7 +209,7 @@ Como `Hero` herda de `HeroBase`, ele **também** tem os **campos** declarados em
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *}
#### `HeroPublic` - o *modelo de dados* público
#### `HeroPublic` - o *modelo de dados* público { #heropublic-the-public-data-model }
Em seguida, criamos um modelo `HeroPublic`, que será **retornado** para os clientes da API.
@@ -234,11 +232,10 @@ Todos os campos em `HeroPublic` são os mesmos que em `HeroBase`, com `id` decla
* `id`
* `name`
* `age`
* `secret_name`
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *}
#### `HeroCreate` - o *modelo de dados* para criar um hero
#### `HeroCreate` - o *modelo de dados* para criar um hero { #herocreate-the-data-model-to-create-a-hero }
Agora criamos um modelo `HeroCreate`, este é o que **validará** os dados dos clientes.
@@ -262,7 +259,7 @@ Os campos de `HeroCreate` são:
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *}
#### `HeroUpdate` - o *modelo de dados* para atualizar um hero
#### `HeroUpdate` - o *modelo de dados* para atualizar um hero { #heroupdate-the-data-model-to-update-a-hero }
Não tínhamos uma maneira de **atualizar um hero** na versão anterior do app, mas agora com **múltiplos modelos**, podemos fazer isso. 🎉
@@ -280,7 +277,7 @@ Os campos de `HeroUpdate` são:
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *}
### Criar com `HeroCreate` e retornar um `HeroPublic`
### Criar com `HeroCreate` e retornar um `HeroPublic` { #create-with-herocreate-and-return-a-heropublic }
Agora que temos **múltiplos modelos**, podemos atualizar as partes do app que os utilizam.
@@ -302,19 +299,19 @@ Ao declará-lo no `response_model`, estamos dizendo ao **FastAPI** para fazer o
///
### Ler Heroes com `HeroPublic`
### Ler Heroes com `HeroPublic` { #read-heroes-with-heropublic }
Podemos fazer o mesmo que antes para **ler** `Hero`s, novamente, usamos `response_model=list[HeroPublic]` para garantir que os dados sejam validados e serializados corretamente.
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *}
### Ler Um Hero com `HeroPublic`
### Ler Um Hero com `HeroPublic` { #read-one-hero-with-heropublic }
Podemos **ler** um único herói:
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *}
### Atualizar um Hero com `HeroUpdate`
### Atualizar um Hero com `HeroUpdate` { #update-a-hero-with-heroupdate }
Podemos **atualizar um hero**. Para isso, usamos uma operação HTTP `PATCH`.
@@ -324,7 +321,7 @@ Em seguida, usamos `hero_db.sqlmodel_update(hero_data)` para atualizar o `hero_d
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *}
### Deletar um Hero Novamente
### Deletar um Hero Novamente { #delete-a-hero-again }
**Deletar** um hero permanece praticamente o mesmo.
@@ -332,7 +329,7 @@ Não vamos satisfazer o desejo de refatorar tudo neste aqui. 😅
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *}
### Executar o App Novamente
### Executar o App Novamente { #run-the-app-again }
Você pode executar o app novamente:
@@ -346,13 +343,13 @@ $ fastapi dev main.py
</div>
If you go to the `/docs` API UI, you will see that it is now updated, and it won't expect to receive the `id` from the client when creating a hero, etc.
Se você for para a interface `/docs` da API, verá que agora ela está atualizada e não esperará receber o `id` do cliente ao criar um hero, etc.
<div class="screenshot">
<img src="/img/tutorial/sql-databases/image02.png">
</div>
## Recapitulando
## Recapitulando { #recap }
Você pode usar <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">**SQLModel**</a> para interagir com um banco de dados SQL e simplificar o código com *modelos de dados* e *modelos de tabela*.

View File

@@ -1,15 +1,15 @@
# Arquivos Estáticos
# Arquivos Estáticos { #static-files }
Você pode servir arquivos estáticos automaticamente de um diretório usando `StaticFiles`.
Você pode servir arquivos estáticos automaticamente a partir de um diretório usando `StaticFiles`.
## Use `StaticFiles`
## Use `StaticFiles` { #use-staticfiles }
* Importe `StaticFiles`.
* "Monte" uma instância de `StaticFiles()` em um caminho específico.
* "Monte" uma instância de `StaticFiles()` em um path específico.
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Você também pode usar `from starlette.staticfiles import StaticFiles`.
@@ -17,24 +17,24 @@ O **FastAPI** fornece o mesmo que `starlette.staticfiles` como `fastapi.staticfi
///
### O que é "Montagem"
### O que é "Montagem" { #what-is-mounting }
"Montagem" significa adicionar um aplicativo completamente "independente" em uma rota específica, que então cuida de todas as subrotas.
"Montagem" significa adicionar uma aplicação completamente "independente" em um path específico, que então cuida de lidar com todos os sub-paths.
Isso é diferente de usar um `APIRouter`, pois um aplicativo montado é completamente independente. A OpenAPI e a documentação do seu aplicativo principal não incluirão nada do aplicativo montado, etc.
Isso é diferente de usar um `APIRouter`, pois uma aplicação montada é completamente independente. A OpenAPI e a documentação da sua aplicação principal não incluirão nada da aplicação montada, etc.
Você pode ler mais sobre isso no **Guia Avançado do Usuário**.
Você pode ler mais sobre isso no [Guia Avançado do Usuário](../advanced/index.md){.internal-link target=_blank}.
## Detalhes
## Detalhes { #details }
O primeiro `"/static"` refere-se à subrota em que este "subaplicativo" será "montado". Portanto, qualquer caminho que comece com `"/static"` será tratado por ele.
O primeiro `"/static"` refere-se ao sub-path no qual este "subaplicativo" será "montado". Assim, qualquer path que comece com `"/static"` será tratado por ele.
O `directory="static"` refere-se ao nome do diretório que contém seus arquivos estáticos.
O `name="static"` dá a ela um nome que pode ser usado internamente pelo FastAPI.
O `name="static"` dá a ele um nome que pode ser usado internamente pelo **FastAPI**.
Todos esses parâmetros podem ser diferentes de "`static`", ajuste-os de acordo com as necessidades e detalhes específicos de sua própria aplicação.
Todos esses parâmetros podem ser diferentes de "`static`", ajuste-os de acordo com as necessidades e detalhes específicos da sua própria aplicação.
## Mais informações
## Mais informações { #more-info }
Para mais detalhes e opções, verifique <a href="https://www.starlette.dev/staticfiles/" class="external-link" target="_blank">Starlette's docs about Static Files</a>.
Para mais detalhes e opções, consulte <a href="https://www.starlette.dev/staticfiles/" class="external-link" target="_blank">a documentação da Starlette sobre Arquivos Estáticos</a>.

View File

@@ -1,4 +1,4 @@
# Testando
# Testando { #testing }
Graças ao <a href="https://www.starlette.dev/testclient/" class="external-link" target="_blank">Starlette</a>, testar aplicativos **FastAPI** é fácil e agradável.
@@ -6,7 +6,7 @@ Ele é baseado no <a href="https://www.python-httpx.org" class="external-link" t
Com ele, você pode usar o <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> diretamente com **FastAPI**.
## Usando `TestClient`
## Usando `TestClient` { #using-testclient }
/// info | Informação
@@ -42,7 +42,7 @@ Isso permite que você use `pytest` diretamente sem complicações.
///
/// note | Detalhes técnicos
/// note | Detalhes Técnicos
Você também pode usar `from starlette.testclient import TestClient`.
@@ -56,15 +56,15 @@ Se você quiser chamar funções `async` em seus testes além de enviar solicita
///
## Separando testes
## Separando testes { #separating-tests }
Em uma aplicação real, você provavelmente teria seus testes em um arquivo diferente.
E seu aplicativo **FastAPI** também pode ser composto de vários arquivos/módulos, etc.
### Arquivo do aplicativo **FastAPI**
### Arquivo do aplicativo **FastAPI** { #fastapi-app-file }
Digamos que você tenha uma estrutura de arquivo conforme descrito em [Aplicativos maiores](bigger-applications.md){.internal-link target=_blank}:
Digamos que você tenha uma estrutura de arquivo conforme descrito em [Aplicações maiores](bigger-applications.md){.internal-link target=_blank}:
```
.
@@ -78,7 +78,7 @@ No arquivo `main.py` você tem seu aplicativo **FastAPI**:
{* ../../docs_src/app_testing/main.py *}
### Arquivo de teste
### Arquivo de teste { #testing-file }
Então você poderia ter um arquivo `test_main.py` com seus testes. Ele poderia estar no mesmo pacote Python (o mesmo diretório com um arquivo `__init__.py`):
@@ -96,11 +96,11 @@ Como esse arquivo está no mesmo pacote, você pode usar importações relativas
...e ter o código para os testes como antes.
## Testando: exemplo estendido
## Testando: exemplo estendido { #testing-extended-example }
Agora vamos estender este exemplo e adicionar mais detalhes para ver como testar diferentes partes.
### Arquivo de aplicativo **FastAPI** estendido
### Arquivo de aplicativo **FastAPI** estendido { #extended-fastapi-app-file }
Vamos continuar com a mesma estrutura de arquivo de antes:
@@ -172,7 +172,7 @@ Prefira usar a versão `Annotated` se possível.
////
### Arquivo de teste estendido
### Arquivo de teste estendido { #extended-testing-file }
Você pode então atualizar `test_main.py` com os testes estendidos:
@@ -200,7 +200,7 @@ Se você tiver um modelo Pydantic em seu teste e quiser enviar seus dados para o
///
## Execute-o
## Execute-o { #run-it }
Depois disso, você só precisa instalar o `pytest`.