mirror of
https://github.com/fastapi/fastapi.git
synced 2026-02-14 16:21:08 -05:00
Update all
This commit is contained in:
@@ -104,8 +104,8 @@ $ cd code
|
||||
...e um exemplo de código Python...
|
||||
|
||||
```Python
|
||||
wont_work() # This won't work 😱
|
||||
works(foo="bar") # This works 🎉
|
||||
wont_work() # Isto não vai funcionar 😱
|
||||
works(foo="bar") # Isto funciona 🎉
|
||||
```
|
||||
|
||||
...e é isso.
|
||||
@@ -204,8 +204,8 @@ Aqui estão algumas coisas envolvidas em elementos HTML "abbr" (algumas são inv
|
||||
|
||||
### O abbr fornece uma frase completa e uma explicação { #the-abbr-gives-a-full-phrase-and-an-explanation }
|
||||
|
||||
* <abbr title="Mozilla Developer Network: documentação para desenvolvedores, escrita pelo pessoal do Firefox">MDN</abbr>
|
||||
* <abbr title="Input/Output: leitura ou escrita em disco, comunicações de rede.">I/O</abbr>.
|
||||
* <abbr title="Mozilla Developer Network – Rede de Desenvolvedores da Mozilla: documentação para desenvolvedores, escrita pelo pessoal do Firefox">MDN</abbr>
|
||||
* <abbr title="Input/Output – Entrada/Saída: leitura ou escrita em disco, comunicações de rede.">I/O</abbr>.
|
||||
|
||||
////
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ O **FastAPI** pegará este modelo, gerará o esquema JSON dele e incluirá no lo
|
||||
|
||||
Por exemplo, para declarar um outro retorno com o status code `404` e um modelo do Pydantic chamado `Message`, você pode escrever:
|
||||
|
||||
{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
|
||||
{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
@@ -203,7 +203,7 @@ Por exemplo, você pode declarar um retorno com o código de status `404` que ut
|
||||
|
||||
E um retorno com o código de status `200` que utiliza o seu `response_model`, porém inclui um `example` customizado:
|
||||
|
||||
{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
|
||||
{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *}
|
||||
|
||||
Isso será combinado e incluído em seu OpenAPI, e disponibilizado na documentação da sua API:
|
||||
|
||||
@@ -243,5 +243,5 @@ Por exemplo:
|
||||
|
||||
Para verificar exatamente o que você pode incluir nos retornos, você pode conferir estas seções na especificação do OpenAPI:
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, inclui o `Response Object`.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que você declara diferentes media types e esquemas JSON), e `links`.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">Objeto de Retornos do OpenAPI</a>, inclui o `Response Object`.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">Objeto de Retorno do OpenAPI</a>, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que você declara diferentes media types e esquemas JSON), e `links`.
|
||||
|
||||
@@ -18,7 +18,7 @@ Não propriamente a classe (que já é um chamável), mas a instância desta cla
|
||||
|
||||
Para fazer isso, nós declaramos o método `__call__`:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *}
|
||||
|
||||
Neste caso, o `__call__` é o que o **FastAPI** utilizará para verificar parâmetros adicionais e sub dependências, e isso é o que será chamado para passar o valor ao parâmetro na sua *função de operação de rota* posteriormente.
|
||||
|
||||
@@ -26,7 +26,7 @@ Neste caso, o `__call__` é o que o **FastAPI** utilizará para verificar parâm
|
||||
|
||||
E agora, nós podemos utilizar o `__init__` para declarar os parâmetros da instância que podemos utilizar para "parametrizar" a dependência:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *}
|
||||
|
||||
Neste caso, o **FastAPI** nunca tocará ou se importará com o `__init__`, nós vamos utilizar diretamente em nosso código.
|
||||
|
||||
@@ -34,7 +34,7 @@ Neste caso, o **FastAPI** nunca tocará ou se importará com o `__init__`, nós
|
||||
|
||||
Nós poderíamos criar uma instância desta classe com:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *}
|
||||
|
||||
E deste modo nós podemos "parametrizar" a nossa dependência, que agora possui `"bar"` dentro dele, como o atributo `checker.fixed_content`.
|
||||
|
||||
@@ -50,7 +50,7 @@ checker(q="somequery")
|
||||
|
||||
...e passar o que quer que isso retorne como valor da dependência em nossa *função de operação de rota* como o parâmetro `fixed_content_included`:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *}
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
61
docs/pt/docs/advanced/advanced-python-types.md
Normal file
61
docs/pt/docs/advanced/advanced-python-types.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Tipos Avançados de Python { #advanced-python-types }
|
||||
|
||||
Aqui estão algumas ideias adicionais que podem ser úteis ao trabalhar com tipos em Python.
|
||||
|
||||
## Usando `Union` ou `Optional` { #using-union-or-optional }
|
||||
|
||||
Se, por algum motivo, seu código não puder usar `|`, por exemplo, se não for em uma anotação de tipo, mas em algo como `response_model=`, em vez de usar a barra vertical (`|`) você pode usar `Union` do `typing`.
|
||||
|
||||
Por exemplo, você poderia declarar que algo pode ser `str` ou `None`:
|
||||
|
||||
```python
|
||||
from typing import Union
|
||||
|
||||
|
||||
def say_hi(name: Union[str, None]):
|
||||
print(f"Hi {name}!")
|
||||
```
|
||||
|
||||
O `typing` também tem um atalho para declarar que algo pode ser `None`, com `Optional`.
|
||||
|
||||
Aqui vai uma dica do meu ponto de vista bem subjetivo:
|
||||
|
||||
* 🚨 Evite usar `Optional[SomeType]`
|
||||
* Em vez disso ✨ use **`Union[SomeType, None]`** ✨.
|
||||
|
||||
Ambos são equivalentes e, por baixo, são a mesma coisa, mas eu recomendaria `Union` em vez de `Optional` porque a palavra "opcional" sugere que o valor é opcional; na verdade, significa "pode ser `None`", mesmo quando não é opcional e continua sendo obrigatório.
|
||||
|
||||
Acho que `Union[SomeType, None]` é mais explícito quanto ao significado.
|
||||
|
||||
É apenas uma questão de palavras e nomes. Mas essas palavras podem influenciar como você e sua equipe pensam sobre o código.
|
||||
|
||||
Como exemplo, veja esta função:
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def say_hi(name: Optional[str]):
|
||||
print(f"Hey {name}!")
|
||||
```
|
||||
|
||||
O parâmetro `name` é definido como `Optional[str]`, mas não é opcional; não é possível chamar a função sem o parâmetro:
|
||||
|
||||
```Python
|
||||
say_hi() # Ah, não, isso gera um erro! 😱
|
||||
```
|
||||
|
||||
O parâmetro `name` continua obrigatório (não é opcional) porque não tem valor padrão. Ainda assim, `name` aceita `None` como valor:
|
||||
|
||||
```Python
|
||||
say_hi(name=None) # Isso funciona, None é válido 🎉
|
||||
```
|
||||
|
||||
A boa notícia é que, na maioria dos casos, você poderá simplesmente usar `|` para definir uniões de tipos:
|
||||
|
||||
```python
|
||||
def say_hi(name: str | None):
|
||||
print(f"Hey {name}!")
|
||||
```
|
||||
|
||||
Então, normalmente você não precisa se preocupar com nomes como `Optional` e `Union`. 😎
|
||||
@@ -32,11 +32,11 @@ Para um exemplos simples, vamos considerar uma estrutura de arquivos semelhante
|
||||
|
||||
O arquivo `main.py` teria:
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/main.py *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/main.py *}
|
||||
|
||||
O arquivo `test_main.py` teria os testes para para o arquivo `main.py`, ele poderia ficar assim:
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/test_main.py *}
|
||||
|
||||
## Executá-lo { #run-it }
|
||||
|
||||
@@ -56,7 +56,7 @@ $ pytest
|
||||
|
||||
O marcador `@pytest.mark.anyio` informa ao pytest que esta função de teste deve ser invocada de maneira assíncrona:
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -66,7 +66,7 @@ Note que a função de teste é `async def` agora, no lugar de apenas `def` como
|
||||
|
||||
Então podemos criar um `AsyncClient` com a aplicação, e enviar requisições assíncronas para ela utilizando `await`.
|
||||
|
||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *}
|
||||
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *}
|
||||
|
||||
Isso é equivalente a:
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*"
|
||||
|
||||
Por exemplo, suponha que você defina uma *operação de rota* `/items/`:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *}
|
||||
|
||||
Se o cliente tentar ir para `/items`, por padrão, ele seria redirecionado para `/items/`.
|
||||
|
||||
@@ -91,9 +91,9 @@ O **proxy** intercepta a requisição original do cliente e adiciona os headers
|
||||
|
||||
Esses headers preservam informações sobre a requisição original que, de outra forma, seriam perdidas:
|
||||
|
||||
* X-Forwarded-For: o endereço IP original do cliente
|
||||
* X-Forwarded-Proto: o protocolo original (`https`)
|
||||
* X-Forwarded-Host: o host original (`mysuperapp.com`)
|
||||
* **X-Forwarded-For**: o endereço IP original do cliente
|
||||
* **X-Forwarded-Proto**: o protocolo original (`https`)
|
||||
* **X-Forwarded-Host**: o host original (`mysuperapp.com`)
|
||||
|
||||
Quando a **CLI do FastAPI** é configurada com `--forwarded-allow-ips`, ela confia nesses headers e os utiliza, por exemplo, para gerar as URLs corretas em redirecionamentos.
|
||||
|
||||
@@ -115,7 +115,7 @@ Nesse caso, o path original `/app` seria servido em `/api/v1/app`.
|
||||
|
||||
Embora todo o seu código esteja escrito assumindo que existe apenas `/app`.
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *}
|
||||
|
||||
E o proxy estaria **"removendo"** o **prefixo de path** dinamicamente antes de transmitir a solicitação para o servidor da aplicação (provavelmente Uvicorn via CLI do FastAPI), mantendo sua aplicação convencida de que está sendo servida em `/app`, para que você não precise atualizar todo o seu código para incluir o prefixo `/api/v1`.
|
||||
|
||||
@@ -193,7 +193,7 @@ Você pode obter o `root_path` atual usado pela sua aplicação para cada solici
|
||||
|
||||
Aqui estamos incluindo-o na mensagem apenas para fins de demonstração.
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *}
|
||||
|
||||
Então, se você iniciar o Uvicorn com:
|
||||
|
||||
@@ -220,7 +220,7 @@ A resposta seria algo como:
|
||||
|
||||
Alternativamente, se você não tiver uma maneira de fornecer uma opção de linha de comando como `--root-path` ou equivalente, você pode definir o parâmetro `root_path` ao criar sua aplicação FastAPI:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *}
|
||||
|
||||
Passar o `root_path` para `FastAPI` seria o equivalente a passar a opção de linha de comando `--root-path` para Uvicorn ou Hypercorn.
|
||||
|
||||
@@ -400,7 +400,7 @@ Se você passar uma lista personalizada de `servers` e houver um `root_path` (po
|
||||
|
||||
Por exemplo:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *}
|
||||
|
||||
Gerará um OpenAPI schema como:
|
||||
|
||||
@@ -455,7 +455,7 @@ Se você não especificar o parâmetro `servers` e `root_path` for igual a `/`,
|
||||
|
||||
Se você não quiser que o **FastAPI** inclua um servidor automático usando o `root_path`, você pode usar o parâmetro `root_path_in_servers=False`:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *}
|
||||
{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *}
|
||||
|
||||
e então ele não será incluído no OpenAPI schema.
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Isso ocorre por que, por padrão, o FastAPI irá verificar cada item dentro do d
|
||||
|
||||
Mas se você tem certeza que o conteúdo que você está retornando é **serializável com JSON**, você pode passá-lo diretamente para a classe de resposta e evitar o trabalho extra que o FastAPI teria ao passar o conteúdo pelo `jsonable_encoder` antes de passar para a classe de resposta.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *}
|
||||
{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *}
|
||||
|
||||
/// info | Informação
|
||||
|
||||
@@ -55,7 +55,7 @@ Para retornar uma resposta com HTML diretamente do **FastAPI**, utilize `HTMLRes
|
||||
* Importe `HTMLResponse`
|
||||
* Passe `HTMLResponse` como o parâmetro de `response_class` do seu *decorador de operação de rota*.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *}
|
||||
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
|
||||
|
||||
/// info | Informação
|
||||
|
||||
@@ -73,7 +73,7 @@ Como visto em [Retornando uma Resposta Diretamente](response-directly.md){.inter
|
||||
|
||||
O mesmo exemplo de antes, retornando uma `HTMLResponse`, poderia parecer com:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *}
|
||||
{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *}
|
||||
|
||||
/// warning | Atenção
|
||||
|
||||
@@ -97,7 +97,7 @@ A `response_class` será usada apenas para documentar o OpenAPI da *operação d
|
||||
|
||||
Por exemplo, poderia ser algo como:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *}
|
||||
{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *}
|
||||
|
||||
Neste exemplo, a função `generate_html_response()` já cria e retorna uma `Response` em vez de retornar o HTML em uma `str`.
|
||||
|
||||
@@ -136,7 +136,7 @@ Ela aceita os seguintes parâmetros:
|
||||
|
||||
O FastAPI (Starlette, na verdade) irá incluir o cabeçalho Content-Length automaticamente. Ele também irá incluir o cabeçalho Content-Type, baseado no `media_type` e acrescentando uma codificação para tipos textuais.
|
||||
|
||||
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
|
||||
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
|
||||
|
||||
### `HTMLResponse` { #htmlresponse }
|
||||
|
||||
@@ -146,7 +146,7 @@ Usa algum texto ou sequência de bytes e retorna uma resposta HTML. Como você l
|
||||
|
||||
Usa algum texto ou sequência de bytes para retornar uma resposta de texto não formatado.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *}
|
||||
|
||||
### `JSONResponse` { #jsonresponse }
|
||||
|
||||
@@ -180,7 +180,7 @@ Essa resposta requer a instalação do pacote `ujson`, com o comando `pip instal
|
||||
|
||||
///
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *}
|
||||
{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -194,13 +194,13 @@ Retorna um redirecionamento HTTP. Utiliza o código de status 307 (Redirecioname
|
||||
|
||||
Você pode retornar uma `RedirectResponse` diretamente:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *}
|
||||
|
||||
---
|
||||
|
||||
Ou você pode utilizá-la no parâmetro `response_class`:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *}
|
||||
|
||||
Se você fizer isso, então você pode retornar a URL diretamente da sua *função de operação de rota*
|
||||
|
||||
@@ -210,13 +210,13 @@ Neste caso, o `status_code` utilizada será o padrão de `RedirectResponse`, que
|
||||
|
||||
Você também pode utilizar o parâmetro `status_code` combinado com o parâmetro `response_class`:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *}
|
||||
{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *}
|
||||
|
||||
### `StreamingResponse` { #streamingresponse }
|
||||
|
||||
Recebe um gerador assíncrono ou um gerador/iterador comum e retorna o corpo da resposta de forma contínua (stream).
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *}
|
||||
{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *}
|
||||
|
||||
#### Utilizando `StreamingResponse` com objetos semelhantes a arquivos { #using-streamingresponse-with-file-like-objects }
|
||||
|
||||
@@ -226,7 +226,7 @@ Dessa forma, você não precisa ler todo o arquivo na memória primeiro, e você
|
||||
|
||||
Isso inclui muitas bibliotecas que interagem com armazenamento em nuvem, processamento de vídeos, entre outras.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *}
|
||||
{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *}
|
||||
|
||||
1. Essa é a função geradora. É definida como "função geradora" porque contém declarações `yield` nela.
|
||||
2. Ao utilizar o bloco `with`, nós garantimos que o objeto semelhante a um arquivo é fechado após a função geradora ser finalizada. Isto é, após a resposta terminar de ser enviada.
|
||||
@@ -255,11 +255,11 @@ Recebe um conjunto de argumentos do construtor diferente dos outros tipos de res
|
||||
|
||||
Respostas de Arquivos incluem o tamanho do arquivo, data da última modificação e ETags apropriados, nos cabeçalhos `Content-Length`, `Last-Modified` e `ETag`, respectivamente.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *}
|
||||
{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *}
|
||||
|
||||
Você também pode usar o parâmetro `response_class`:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *}
|
||||
{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *}
|
||||
|
||||
Nesse caso, você pode retornar o caminho do arquivo diretamente da sua *função de operação de rota*.
|
||||
|
||||
@@ -273,7 +273,7 @@ Vamos supor também que você queira retornar um JSON indentado e formatado, ent
|
||||
|
||||
Você poderia criar uma classe `CustomORJSONResponse`. A principal coisa a ser feita é sobrecarregar o método render da classe Response, `Response.render(content)`, que retorna o conteúdo em bytes:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *}
|
||||
{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *}
|
||||
|
||||
Agora em vez de retornar:
|
||||
|
||||
@@ -299,7 +299,7 @@ O padrão que define isso é o `default_response_class`.
|
||||
|
||||
No exemplo abaixo, o **FastAPI** irá utilizar `ORJSONResponse` por padrão, em todas as *operações de rota*, em vez de `JSONResponse`.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *}
|
||||
{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ Nesse caso, você pode simplesmente trocar as `dataclasses` padrão por `pydanti
|
||||
|
||||
6. Aqui estamos retornando um dicionário que contém `items`, que é uma lista de dataclasses.
|
||||
|
||||
O FastAPI ainda é capaz de <abbr title="converter os dados para um formato que pode ser transmitido">serializar</abbr> os dados para JSON.
|
||||
O FastAPI ainda é capaz de <dfn title="converter os dados para um formato que pode ser transmitido">serializar</dfn> os dados para JSON.
|
||||
|
||||
7. Aqui o `response_model` está usando uma anotação de tipo de uma lista de dataclasses `Author`.
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ Da mesma forma, você pode definir a lógica (código) que deve ser executada qu
|
||||
|
||||
Como esse código é executado antes de a aplicação **começar** a receber requisições e logo depois que ela **termina** de lidar com as requisições, ele cobre todo o **lifespan** da aplicação (a palavra "lifespan" será importante em um segundo 😉).
|
||||
|
||||
Isso pode ser muito útil para configurar **recursos** que você precisa usar por toda a aplicação, e que são **compartilhados** entre as requisições e/ou que você precisa **limpar** depois. Por exemplo, um pool de conexões com o banco de dados ou o carregamento de um modelo de machine learning compartilhado.
|
||||
Isso pode ser muito útil para configurar **recursos** que você precisa usar por toda a aplicação, e que são **compartilhados** entre as requisições e/ou que você precisa **limpar** depois. Por exemplo, um pool de conexões com o banco de dados ou o carregamento de um modelo de Aprendizado de Máquina compartilhado.
|
||||
|
||||
## Caso de uso { #use-case }
|
||||
|
||||
Vamos começar com um exemplo de **caso de uso** e então ver como resolvê-lo com isso.
|
||||
|
||||
Vamos imaginar que você tem alguns **modelos de machine learning** que deseja usar para lidar com as requisições. 🤖
|
||||
Vamos imaginar que você tem alguns **modelos de Aprendizado de Máquina** que deseja usar para lidar com as requisições. 🤖
|
||||
|
||||
Os mesmos modelos são compartilhados entre as requisições, então não é um modelo por requisição, ou um por usuário, ou algo parecido.
|
||||
|
||||
@@ -30,9 +30,9 @@ Vamos começar com um exemplo e depois ver em detalhes.
|
||||
|
||||
Nós criamos uma função assíncrona `lifespan()` com `yield` assim:
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *}
|
||||
|
||||
Aqui estamos simulando a operação de *inicialização* custosa de carregar o modelo, colocando a (falsa) função do modelo no dicionário com modelos de machine learning antes do `yield`. Esse código será executado **antes** de a aplicação **começar a receber requisições**, durante a *inicialização*.
|
||||
Aqui estamos simulando a operação de *inicialização* custosa de carregar o modelo, colocando a (falsa) função do modelo no dicionário com modelos de Aprendizado de Máquina antes do `yield`. Esse código será executado **antes** de a aplicação **começar a receber requisições**, durante a *inicialização*.
|
||||
|
||||
E então, logo após o `yield`, descarregamos o modelo. Esse código será executado **depois** de a aplicação **terminar de lidar com as requisições**, pouco antes do *encerramento*. Isso poderia, por exemplo, liberar recursos como memória ou uma GPU.
|
||||
|
||||
@@ -48,7 +48,7 @@ Talvez você precise iniciar uma nova versão, ou apenas cansou de executá-la.
|
||||
|
||||
A primeira coisa a notar é que estamos definindo uma função assíncrona com `yield`. Isso é muito semelhante a Dependências com `yield`.
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *}
|
||||
|
||||
A primeira parte da função, antes do `yield`, será executada **antes** de a aplicação iniciar.
|
||||
|
||||
@@ -60,7 +60,7 @@ Se você verificar, a função está decorada com um `@asynccontextmanager`.
|
||||
|
||||
Isso converte a função em algo chamado "**gerenciador de contexto assíncrono**".
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *}
|
||||
|
||||
Um **gerenciador de contexto** em Python é algo que você pode usar em uma declaração `with`, por exemplo, `open()` pode ser usado como um gerenciador de contexto:
|
||||
|
||||
@@ -82,7 +82,7 @@ No nosso exemplo de código acima, não o usamos diretamente, mas passamos para
|
||||
|
||||
O parâmetro `lifespan` da aplicação `FastAPI` aceita um **gerenciador de contexto assíncrono**, então podemos passar para ele nosso novo gerenciador de contexto assíncrono `lifespan`.
|
||||
|
||||
{* ../../docs_src/events/tutorial003_py39.py hl[22] *}
|
||||
{* ../../docs_src/events/tutorial003_py310.py hl[22] *}
|
||||
|
||||
## Eventos alternativos (descontinuados) { #alternative-events-deprecated }
|
||||
|
||||
@@ -104,7 +104,7 @@ Essas funções podem ser declaradas com `async def` ou `def` normal.
|
||||
|
||||
Para adicionar uma função que deve rodar antes de a aplicação iniciar, declare-a com o evento `"startup"`:
|
||||
|
||||
{* ../../docs_src/events/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/events/tutorial001_py310.py hl[8] *}
|
||||
|
||||
Nesse caso, a função de manipulador do evento `startup` inicializará os itens do "banco de dados" (apenas um `dict`) com alguns valores.
|
||||
|
||||
@@ -116,7 +116,7 @@ E sua aplicação não começará a receber requisições até que todos os mani
|
||||
|
||||
Para adicionar uma função que deve ser executada quando a aplicação estiver encerrando, declare-a com o evento `"shutdown"`:
|
||||
|
||||
{* ../../docs_src/events/tutorial002_py39.py hl[6] *}
|
||||
{* ../../docs_src/events/tutorial002_py310.py hl[6] *}
|
||||
|
||||
Aqui, a função de manipulador do evento `shutdown` escreverá uma linha de texto `"Application shutdown"` no arquivo `log.txt`.
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ Algumas dessas soluções também podem ser open source ou oferecer planos gratu
|
||||
|
||||
Vamos começar com uma aplicação FastAPI simples:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
|
||||
{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *}
|
||||
|
||||
Note que as *operações de rota* definem os modelos que usam para o corpo da requisição e o corpo da resposta, usando os modelos `Item` e `ResponseMessage`.
|
||||
|
||||
@@ -98,7 +98,7 @@ Em muitos casos, sua aplicação FastAPI será maior, e você provavelmente usar
|
||||
|
||||
Por exemplo, você poderia ter uma seção para **items** e outra seção para **users**, e elas poderiam ser separadas por tags:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
|
||||
{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *}
|
||||
|
||||
### Gere um cliente TypeScript com Tags { #generate-a-typescript-client-with-tags }
|
||||
|
||||
@@ -141,11 +141,11 @@ O FastAPI usa um **ID exclusivo** para cada *operação de rota*, ele é usado p
|
||||
|
||||
Você pode personalizar essa função. Ela recebe uma `APIRoute` e retorna uma string.
|
||||
|
||||
Por exemplo, aqui está usando a primeira tag (você provavelmente terá apenas uma tag) e o nome da *operação de rota* (o nome da função).
|
||||
Por exemplo, aqui está usando a primeira tag (Você provavelmente terá apenas uma tag) e o nome da *operação de rota* (o nome da função).
|
||||
|
||||
Você pode então passar essa função personalizada para o **FastAPI** como o parâmetro `generate_unique_id_function`:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
|
||||
{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *}
|
||||
|
||||
### Gere um cliente TypeScript com IDs de operação personalizados { #generate-a-typescript-client-with-custom-operation-ids }
|
||||
|
||||
@@ -167,7 +167,7 @@ Mas para o cliente gerado, poderíamos **modificar** os IDs de operação do Ope
|
||||
|
||||
Poderíamos baixar o JSON do OpenAPI para um arquivo `openapi.json` e então poderíamos **remover essa tag prefixada** com um script como este:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial004_py39.py *}
|
||||
{* ../../docs_src/generate_clients/tutorial004_py310.py *}
|
||||
|
||||
//// tab | Node.js
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Nas próximas seções você verá outras opções, configurações, e recursos
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
As próximas seções **não são necessáriamente "avançadas"**
|
||||
As próximas seções **não são necessariamente "avançadas"**.
|
||||
|
||||
E é possível que para seu caso de uso, a solução esteja em uma delas.
|
||||
|
||||
|
||||
@@ -57,13 +57,13 @@ Garante que todas as requisições devem ser `https` ou `wss`.
|
||||
|
||||
Qualquer requisição para `http` ou `ws` será redirecionada para o esquema seguro.
|
||||
|
||||
{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *}
|
||||
{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *}
|
||||
|
||||
## `TrustedHostMiddleware` { #trustedhostmiddleware }
|
||||
|
||||
Garante que todas as requisições recebidas tenham um cabeçalho `Host` corretamente configurado, a fim de proteger contra ataques de cabeçalho de host HTTP.
|
||||
|
||||
{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *}
|
||||
{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *}
|
||||
|
||||
Os seguintes argumentos são suportados:
|
||||
|
||||
@@ -78,7 +78,7 @@ Gerencia respostas GZip para qualquer requisição que inclua `"gzip"` no cabeç
|
||||
|
||||
O middleware lidará com respostas padrão e de streaming.
|
||||
|
||||
{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *}
|
||||
{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *}
|
||||
|
||||
Os seguintes argumentos são suportados:
|
||||
|
||||
@@ -91,7 +91,7 @@ Há muitos outros middlewares ASGI.
|
||||
|
||||
Por exemplo:
|
||||
|
||||
* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn's `ProxyHeadersMiddleware`</a>
|
||||
* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">`ProxyHeadersMiddleware` do Uvicorn</a>
|
||||
* <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>
|
||||
|
||||
Para checar outros middlewares disponíveis, confira <a href="https://www.starlette.dev/middleware/" class="external-link" target="_blank">Documentação de Middlewares do Starlette</a> e a <a href="https://github.com/florimondmanca/awesome-asgi" class="external-link" target="_blank">Lista Incrível do ASGI</a>.
|
||||
|
||||
@@ -106,11 +106,11 @@ Ela deve parecer exatamente como uma *operação de rota* normal do FastAPI:
|
||||
Há 2 diferenças principais de uma *operação de rota* normal:
|
||||
|
||||
* Ela não necessita ter nenhum código real, porque seu aplicativo nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`.
|
||||
* O *path* pode conter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> (veja mais abaixo) em que pode usar variáveis com parâmetros e partes da solicitação original enviada para *sua API*.
|
||||
* O *path* pode conter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> (veja mais abaixo) em que pode usar variáveis com parâmetros e partes do request original enviado para *sua API*.
|
||||
|
||||
### A expressão do path do callback { #the-callback-path-expression }
|
||||
|
||||
O *path* do callback pode ter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> que pode conter partes da solicitação original enviada para *sua API*.
|
||||
O *path* do callback pode ter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> que pode conter partes do request original enviado para *sua API*.
|
||||
|
||||
Nesse caso, é a `str`:
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ Webhooks estão disponíveis a partir do OpenAPI 3.1.0, e possui suporte do Fast
|
||||
|
||||
Quando você cria uma aplicação com o **FastAPI**, existe um atributo chamado `webhooks`, que você utilizar para defini-los da mesma maneira que você definiria as suas **operações de rotas**, utilizando por exemplo `@app.webhooks.post()`.
|
||||
|
||||
{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *}
|
||||
{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *}
|
||||
|
||||
Os webhooks que você define aparecerão no esquema do **OpenAPI** e na **página de documentação** gerada automaticamente.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Você pode definir o `operationId` do OpenAPI que será utilizado na sua *opera
|
||||
|
||||
Você deveria ter certeza que ele é único para cada operação.
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *}
|
||||
|
||||
### Utilizando o nome da *função de operação de rota* como o operationId { #using-the-path-operation-function-name-as-the-operationid }
|
||||
|
||||
@@ -20,7 +20,7 @@ Se você quiser utilizar o nome das funções da sua API como `operationId`s, vo
|
||||
|
||||
Você deveria fazer isso depois de adicionar todas as suas *operações de rota*.
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -40,7 +40,7 @@ Mesmo que elas estejam em módulos (arquivos Python) diferentes.
|
||||
|
||||
Para excluir uma *operação de rota* do esquema OpenAPI gerado (e por consequência, dos sistemas de documentação automáticos), utilize o parâmetro `include_in_schema` e defina ele como `False`:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *}
|
||||
|
||||
## Descrição avançada a partir de docstring { #advanced-description-from-docstring }
|
||||
|
||||
@@ -92,7 +92,7 @@ Você pode estender o esquema do OpenAPI para uma *operação de rota* utilizand
|
||||
|
||||
Esse parâmetro `openapi_extra` pode ser útil, por exemplo, para declarar [Extensões do OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *}
|
||||
|
||||
Se você abrir os documentos criados automaticamente para a API, sua extensão aparecerá no final da *operação de rota* específica.
|
||||
|
||||
@@ -139,9 +139,9 @@ Por exemplo, você poderia decidir ler e validar a requisição com seu próprio
|
||||
|
||||
Você pode fazer isso com `openapi_extra`:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *}
|
||||
|
||||
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <abbr title="converted from some plain format, like bytes, into Python objects - convertido de algum formato simples, como bytes, em objetos Python">analisado</abbr> como JSON, ele é lido diretamente como `bytes`, e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
|
||||
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <dfn title="convertido de algum formato simples, como bytes, em objetos Python">analisado</dfn> como JSON, ele é lido diretamente como `bytes`, e a função `magic_data_reader()` seria a responsável por analisá-lo de alguma forma.
|
||||
|
||||
De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição.
|
||||
|
||||
@@ -153,7 +153,7 @@ E você pode fazer isso até mesmo quando o tipo de dados na requisição não
|
||||
|
||||
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validação automática para JSON. Na verdade, estamos declarando o tipo de conteúdo da requisição como YAML, em vez de JSON:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *}
|
||||
|
||||
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber em YAML.
|
||||
|
||||
@@ -161,7 +161,7 @@ Então utilizamos a requisição diretamente e extraímos o corpo como `bytes`.
|
||||
|
||||
E então no nosso código, nós analisamos o conteúdo YAML diretamente e, em seguida, estamos usando novamente o mesmo modelo Pydantic para validar o conteúdo YAML:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ Para estes casos, você pode utilizar um parâmetro `Response`.
|
||||
|
||||
Você pode declarar um parâmetro do tipo `Response` em sua *função de operação de rota* (assim como você pode fazer para cookies e headers).
|
||||
|
||||
E então você pode definir o `status_code` neste objeto de retorno temporal.
|
||||
E então você pode definir o `status_code` neste objeto de retorno *temporal*.
|
||||
|
||||
{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *}
|
||||
{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *}
|
||||
|
||||
E então você pode retornar qualquer objeto que você precise, como você faria normalmente (um `dict`, um modelo de banco de dados, etc.).
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Você pode declarar um parâmetro do tipo `Response` na sua *função de operaç
|
||||
|
||||
E então você pode definir cookies nesse objeto de resposta *temporário*.
|
||||
|
||||
{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *}
|
||||
{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *}
|
||||
|
||||
Em seguida, você pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc).
|
||||
|
||||
@@ -24,7 +24,7 @@ Para fazer isso, você pode criar uma resposta como descrito em [Retorne uma Res
|
||||
|
||||
Então, defina os cookies nela e a retorne:
|
||||
|
||||
{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *}
|
||||
{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Quando você cria uma *operação de rota* no **FastAPI** você pode retornar qualquer dado nela: um dicionário (`dict`), uma lista (`list`), um modelo do Pydantic ou do seu banco de dados, etc.
|
||||
|
||||
Por padrão, o **FastAPI** irá converter automaticamente o valor do retorno para JSON utilizando o `jsonable_encoder` explicado em [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
|
||||
Por padrão, o **FastAPI** irá converter automaticamente o valor do retorno para JSON utilizando o `jsonable_encoder` explicado em [Codificador Compatível com JSON](../tutorial/encoder.md){.internal-link target=_blank}.
|
||||
|
||||
Então, por baixo dos panos, ele incluiria esses dados compatíveis com JSON (e.g. um `dict`) dentro de uma `JSONResponse` que é utilizada para enviar uma resposta para o cliente.
|
||||
|
||||
@@ -54,7 +54,7 @@ Vamos dizer que você quer retornar uma resposta <a href="https://en.wikipedia.o
|
||||
|
||||
Você pode colocar o seu conteúdo XML em uma string, colocar em uma `Response`, e retorná-lo:
|
||||
|
||||
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
|
||||
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
|
||||
|
||||
## Notas { #notes }
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Você pode declarar um parâmetro do tipo `Response` na sua *função de operaç
|
||||
|
||||
Então você pode definir os cabeçalhos nesse objeto de resposta *temporário*.
|
||||
|
||||
{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *}
|
||||
{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *}
|
||||
|
||||
Em seguida você pode retornar qualquer objeto que precisar, da maneira que faria normalmente (um `dict`, um modelo de banco de dados, etc.).
|
||||
|
||||
@@ -22,7 +22,7 @@ Você também pode adicionar cabeçalhos quando retornar uma `Response` diretame
|
||||
|
||||
Crie uma resposta conforme descrito em [Retornar uma resposta diretamente](response-directly.md){.internal-link target=_blank} e passe os cabeçalhos como um parâmetro adicional:
|
||||
|
||||
{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *}
|
||||
{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *}
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
@@ -38,4 +38,4 @@ E como a `Response` pode ser usada frequentemente para definir cabeçalhos e coo
|
||||
|
||||
Tenha em mente que cabeçalhos personalizados proprietários 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>.
|
||||
|
||||
Porém, se voce tiver cabeçalhos personalizados que deseja que um cliente no navegador possa ver, você precisa adicioná-los às suas configurações de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parâmetro `expose_headers` descrito na <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">documentação de CORS do Starlette</a>.
|
||||
Porém, se você tiver cabeçalhos personalizados que deseja que um cliente no navegador possa ver, você precisa adicioná-los às suas configurações de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parâmetro `expose_headers` descrito na <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">documentação de CORS do Starlette</a>.
|
||||
|
||||
@@ -20,7 +20,7 @@ Então, quando você digitar o usuário e senha, o navegador os envia automatica
|
||||
* Isso retorna um objeto do tipo `HTTPBasicCredentials`:
|
||||
* Isto contém o `username` e o `password` enviado.
|
||||
|
||||
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
|
||||
{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *}
|
||||
|
||||
Quando você tentar abrir a URL pela primeira vez (ou clicar no botão "Executar" na documentação) o navegador vai pedir pelo seu usuário e senha:
|
||||
|
||||
@@ -40,7 +40,7 @@ Para lidar com isso, primeiramente nós convertemos o `username` e o `password`
|
||||
|
||||
Então nós podemos utilizar o `secrets.compare_digest()` para garantir que o `credentials.username` é `"stanleyjobson"`, e que o `credentials.password` é `"swordfish"`.
|
||||
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
|
||||
{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *}
|
||||
|
||||
Isso seria parecido com:
|
||||
|
||||
@@ -104,4 +104,4 @@ Deste modo, ao utilizar `secrets.compare_digest()` no código de sua aplicação
|
||||
|
||||
Após detectar que as credenciais estão incorretas, retorne um `HTTPException` com o status 401 (o mesmo retornado quando nenhuma credencial foi informada) e adicione o cabeçalho `WWW-Authenticate` para fazer com que o navegador mostre o prompt de login novamente:
|
||||
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
|
||||
{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *}
|
||||
|
||||
@@ -94,7 +94,7 @@ E nós retornamos os escopos como parte do token JWT.
|
||||
|
||||
Para manter as coisas simples, aqui nós estamos apenas adicionando os escopos recebidos diretamente ao token.
|
||||
|
||||
Porém em sua aplicação, por segurança, você deve garantir que você apenas adiciona os escopos que o usuário possui permissão de fato, ou aqueles que você predefiniu.
|
||||
Porém em sua aplicação, por segurança, você deveria garantir que você apenas adiciona os escopos que o usuário possui permissão de fato, ou aqueles que você predefiniu.
|
||||
|
||||
///
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ Da mesma forma que com modelos do Pydantic, você declara atributos de classe co
|
||||
|
||||
Você pode usar as mesmas funcionalidades e ferramentas de validação que usa em modelos do Pydantic, como diferentes tipos de dados e validações adicionais com `Field()`.
|
||||
|
||||
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
|
||||
{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -70,7 +70,7 @@ Em seguida, ele converterá e validará os dados. Assim, quando você usar esse
|
||||
|
||||
Depois você pode usar o novo objeto `settings` na sua aplicação:
|
||||
|
||||
{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *}
|
||||
{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *}
|
||||
|
||||
### Executar o servidor { #run-the-server }
|
||||
|
||||
@@ -104,11 +104,11 @@ Você pode colocar essas configurações em outro arquivo de módulo como visto
|
||||
|
||||
Por exemplo, você poderia ter um arquivo `config.py` com:
|
||||
|
||||
{* ../../docs_src/settings/app01_py39/config.py *}
|
||||
{* ../../docs_src/settings/app01_py310/config.py *}
|
||||
|
||||
E então usá-lo em um arquivo `main.py`:
|
||||
|
||||
{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *}
|
||||
{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -126,7 +126,7 @@ Isso pode ser especialmente útil durante os testes, pois é muito fácil sobres
|
||||
|
||||
Vindo do exemplo anterior, seu arquivo `config.py` poderia ser assim:
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *}
|
||||
|
||||
Perceba que agora não criamos uma instância padrão `settings = Settings()`.
|
||||
|
||||
@@ -134,7 +134,7 @@ Perceba que agora não criamos uma instância padrão `settings = Settings()`.
|
||||
|
||||
Agora criamos uma dependência que retorna um novo `config.Settings()`.
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -146,13 +146,13 @@ Por enquanto, você pode assumir que `get_settings()` é uma função normal.
|
||||
|
||||
E então podemos exigi-la na *função de operação de rota* como dependência e usá-la onde for necessário.
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *}
|
||||
|
||||
### Configurações e testes { #settings-and-testing }
|
||||
|
||||
Então seria muito fácil fornecer um objeto de configurações diferente durante os testes criando uma sobrescrita de dependência para `get_settings`:
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *}
|
||||
{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *}
|
||||
|
||||
Na sobrescrita da dependência definimos um novo valor para `admin_email` ao criar o novo objeto `Settings`, e então retornamos esse novo objeto.
|
||||
|
||||
@@ -193,7 +193,7 @@ APP_NAME="ChimichangApp"
|
||||
|
||||
E então atualizar seu `config.py` com:
|
||||
|
||||
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
|
||||
{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -226,7 +226,7 @@ criaríamos esse objeto para cada requisição e leríamos o arquivo `.env` para
|
||||
|
||||
Mas como estamos usando o decorador `@lru_cache` por cima, o objeto `Settings` será criado apenas uma vez, na primeira vez em que for chamado. ✔️
|
||||
|
||||
{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
|
||||
{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *}
|
||||
|
||||
Em qualquer chamada subsequente de `get_settings()` nas dependências das próximas requisições, em vez de executar o código interno de `get_settings()` e criar um novo objeto `Settings`, ele retornará o mesmo objeto que foi retornado na primeira chamada, repetidamente.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Se você precisar ter duas aplicações FastAPI independentes, cada uma com seu
|
||||
|
||||
Primeiro, crie a aplicação principal, de nível superior, **FastAPI**, e suas *operações de rota*:
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *}
|
||||
|
||||
### Sub-aplicação { #sub-application }
|
||||
|
||||
@@ -18,7 +18,7 @@ Em seguida, crie sua sub-aplicação e suas *operações de rota*.
|
||||
|
||||
Essa sub-aplicação é apenas outra aplicação FastAPI padrão, mas esta é a que será "montada":
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *}
|
||||
|
||||
### Monte a sub-aplicação { #mount-the-sub-application }
|
||||
|
||||
@@ -26,7 +26,7 @@ Na sua aplicação de nível superior, `app`, monte a sub-aplicação, `subapi`.
|
||||
|
||||
Neste caso, ela será montada no path `/subapi`:
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *}
|
||||
|
||||
### Verifique a documentação automática da API { #check-the-automatic-api-docs }
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ $ pip install jinja2
|
||||
* Declare um parâmetro `Request` no *path operation* que retornará um template.
|
||||
* Use o `templates` que você criou para renderizar e retornar uma `TemplateResponse`, passe o nome do template, o objeto `request` e um dicionário "context" com pares chave-valor a serem usados dentro do template do Jinja2.
|
||||
|
||||
{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *}
|
||||
{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ Você pode definir uma sobreposição de dependência para uma dependência que
|
||||
|
||||
A dependência original pode estar sendo utilizada em uma *função de operação de rota*, um *decorador de operação de rota* (quando você não utiliza o valor retornado), uma chamada ao `.include_router()`, etc.
|
||||
|
||||
O FastAPI ainda poderá sobrescrevê-lo.
|
||||
O FastAPI ainda poderá sobrescrevê-la.
|
||||
|
||||
///
|
||||
|
||||
@@ -46,6 +46,7 @@ E então você pode redefinir as suas sobreposições (removê-las) definindo o
|
||||
app.dependency_overrides = {}
|
||||
```
|
||||
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Se você quer sobrepor uma dependência apenas para alguns testes, você pode definir a sobreposição no início do teste (dentro da função de teste) e reiniciá-la ao final (no final da função de teste).
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
Quando você precisa que o `lifespan` seja executado em seus testes, você pode utilizar o `TestClient` com a instrução `with`:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *}
|
||||
{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *}
|
||||
|
||||
Você pode ler mais detalhes sobre o ["Executando lifespan em testes no site oficial da documentação do Starlette."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)
|
||||
|
||||
Para os eventos `startup` e `shutdown` descontinuados, você pode usar o `TestClient` da seguinte forma:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *}
|
||||
{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *}
|
||||
|
||||
@@ -4,7 +4,7 @@ Você pode usar o mesmo `TestClient` para testar WebSockets.
|
||||
|
||||
Para isso, você utiliza o `TestClient` dentro de uma instrução `with`, conectando com o WebSocket:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *}
|
||||
{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Até agora você declarou as partes da requisição que você precisa utilizando
|
||||
Obtendo dados de:
|
||||
|
||||
* O path como parâmetros.
|
||||
* Cabeçalhos (*Headers*).
|
||||
* Cabeçalhos.
|
||||
* Cookies.
|
||||
* etc.
|
||||
|
||||
@@ -29,7 +29,7 @@ Vamos imaginar que você deseja obter o endereço de IP/host do cliente dentro d
|
||||
|
||||
Para isso você precisa acessar a requisição diretamente.
|
||||
|
||||
{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *}
|
||||
{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *}
|
||||
|
||||
Ao declarar o parâmetro com o tipo sendo um `Request` em sua *função de operação de rota*, o **FastAPI** saberá como passar o `Request` neste parâmetro.
|
||||
|
||||
|
||||
@@ -38,13 +38,13 @@ Na produção, você teria uma das opções acima.
|
||||
|
||||
Mas é a maneira mais simples de focar no lado do servidor de WebSockets e ter um exemplo funcional:
|
||||
|
||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *}
|
||||
{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *}
|
||||
|
||||
## Crie um `websocket` { #create-a-websocket }
|
||||
|
||||
Em sua aplicação **FastAPI**, crie um `websocket`:
|
||||
|
||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *}
|
||||
{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *}
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
@@ -58,7 +58,7 @@ A **FastAPI** fornece o mesmo `WebSocket` diretamente apenas como uma conveniên
|
||||
|
||||
Em sua rota WebSocket você pode esperar (`await`) por mensagens e enviar mensagens.
|
||||
|
||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *}
|
||||
{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *}
|
||||
|
||||
Você pode receber e enviar dados binários, de texto e JSON.
|
||||
|
||||
@@ -154,7 +154,7 @@ Com isso você pode conectar o WebSocket e então enviar e receber mensagens:
|
||||
|
||||
Quando uma conexão WebSocket é fechada, o `await websocket.receive_text()` levantará uma exceção `WebSocketDisconnect`, que você pode então capturar e lidar como neste exemplo.
|
||||
|
||||
{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *}
|
||||
{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *}
|
||||
|
||||
Para testar:
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Em seguida, encapsule a aplicação WSGI (e.g. Flask) com o middleware.
|
||||
|
||||
E então monte isso sob um path.
|
||||
|
||||
{* ../../docs_src/wsgi/tutorial001_py39.py hl[1,3,23] *}
|
||||
{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Mas em algum momento, não havia outra opção senão criar algo que fornecesse
|
||||
|
||||
É relativamente bem acoplado com bancos de dados relacionais (como MySQL ou PostgreSQL), então, ter um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra, etc.) como mecanismo principal de armazenamento não é muito fácil.
|
||||
|
||||
Foi criado para gerar o HTML no backend, não para criar APIs usadas por um frontend moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos <abbr title="Internet of Things – Internet das Coisas">IoT</abbr>) comunicando com ele.
|
||||
Foi criado para gerar o HTML no backend, não para criar APIs usadas por um frontend moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos <abbr title="Internet of Things - Internet das Coisas">IoT</abbr>) comunicando com ele.
|
||||
|
||||
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> { #django-rest-framework }
|
||||
|
||||
@@ -137,7 +137,7 @@ Existem vários Flask REST frameworks, mas depois de investir tempo e trabalho i
|
||||
|
||||
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
|
||||
|
||||
Uma das principais funcionalidades necessárias em sistemas de API é a "<abbr title="também chamado marshalling, conversão">serialização</abbr>" de dados, que é pegar dados do código (Python) e convertê-los em algo que possa ser enviado pela rede. Por exemplo, converter um objeto contendo dados de um banco de dados em um objeto JSON. Converter objetos `datetime` em strings, etc.
|
||||
Uma das principais funcionalidades necessárias em sistemas de API é a "<dfn title="também chamado: marshalling, conversão">serialização</dfn>" de dados, que é pegar dados do código (Python) e convertê-los em algo que possa ser enviado pela rede. Por exemplo, converter um objeto contendo dados de um banco de dados em um objeto JSON. Converter objetos `datetime` em strings, etc.
|
||||
|
||||
Outra grande funcionalidade necessária pelas APIs é a validação de dados, garantindo que os dados são válidos, dados certos parâmetros. Por exemplo, que algum campo seja `int`, e não alguma string aleatória. Isso é especialmente útil para dados de entrada.
|
||||
|
||||
@@ -145,7 +145,7 @@ Sem um sistema de validação de dados, você teria que realizar todas as verifi
|
||||
|
||||
Essas funcionalidades são o que o Marshmallow foi construído para fornecer. É uma ótima biblioteca, e eu a utilizei bastante antes.
|
||||
|
||||
Mas ele foi criado antes de existirem as anotações de tipo do Python. Então, para definir cada <abbr title="a definição de como os dados devem ser formados">schema</abbr> você precisa utilizar utilitários e classes específicos fornecidos pelo Marshmallow.
|
||||
Mas ele foi criado antes de existirem as anotações de tipo do Python. Então, para definir cada <dfn title="a definição de como os dados devem ser formados">schema</dfn> você precisa utilizar utilitários e classes específicos fornecidos pelo Marshmallow.
|
||||
|
||||
/// check | **FastAPI** inspirado para
|
||||
|
||||
@@ -155,7 +155,7 @@ Usar código para definir "schemas" que forneçam, automaticamente, tipos de dad
|
||||
|
||||
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
|
||||
|
||||
Outra grande funcionalidade requerida pelas APIs é o <abbr title="ler e converter para dados Python">parsing</abbr> de dados vindos de requisições de entrada.
|
||||
Outra grande funcionalidade requerida pelas APIs é o <dfn title="ler e converter para dados do Python">parsing</dfn> de dados vindos de requisições de entrada.
|
||||
|
||||
Webargs é uma ferramenta feita para fornecer isso no topo de vários frameworks, inclusive Flask.
|
||||
|
||||
@@ -419,7 +419,7 @@ Controlar toda a validação de dados, serialização de dados e documentação
|
||||
|
||||
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
|
||||
|
||||
Starlette é um framework/caixa de ferramentas <abbr title="O novo padrão para construir aplicações web Python assíncronas">ASGI</abbr> leve, o que é ideal para construir serviços asyncio de alta performance.
|
||||
Starlette é um framework/caixa de ferramentas <dfn title="O novo padrão para construir aplicações web Python assíncronas">ASGI</dfn> leve, o que é ideal para construir serviços asyncio de alta performance.
|
||||
|
||||
Ele é muito simples e intuitivo. É projetado para ser facilmente extensível, e ter componentes modulares.
|
||||
|
||||
|
||||
@@ -29,6 +29,6 @@ A hierarquia segue assim:
|
||||
* **FastAPI**:
|
||||
* Do mesmo modo que Starlette utiliza Uvicorn e não pode ser mais rápido que ele, **FastAPI** utiliza o Starlette, então não tem como ser mais rápido do que o Starlette.
|
||||
* FastAPI fornece mais recursos acima do Starlette. Recursos que você quase sempre precisará quando construir APIs, como validação de dados e serialização. E utilizando eles, você terá uma documentação automática de graça (a documentação automática nem sequer adiciona peso para rodar as aplicações, ela é gerada na inicialização).
|
||||
* Se você nunca utilizou FastAPI mas utilizou diretamente o Starlette (ou outra ferramenta, como Sanic, Flask, Responder, etc) você teria que implementar toda validação de dados e serialização por conta. Então, sua aplicação final poderia ainda ter a mesma sobrecarga como se fosse desenvolvida com FastAPI. Em muitos casos, a validação de dados e serialização é o maior pedaço de código escrito em aplicações.
|
||||
* Se você não utilizasse o FastAPI e utilizasse diretamente o Starlette (ou outra ferramenta, como Sanic, Flask, Responder, etc), você teria que implementar toda a validação de dados e serialização por conta. Então, sua aplicação final poderia ainda ter a mesma sobrecarga como se fosse desenvolvida com FastAPI. Em muitos casos, a validação de dados e serialização é o maior pedaço de código escrito em aplicações.
|
||||
* Então, ao utilizar o FastAPI você estará economizando tempo de desenvolvimento, evitará _bugs_, linhas de código, e você provavelmente terá a mesma performance (ou melhor) do que não utilizá-lo (já que você teria que implementar tudo isso em seu código).
|
||||
* Se você quer fazer comparações com o FastAPI, compare com um _framework_ (ou conjunto de ferramentas) para aplicações _web_ que forneça validação de dados, serialização e documentação, como Flask-apispec, NestJS, Molten, etc. _Frameworks_ com validação de dados automática, serialização e documentação integradas.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Implantar FastAPI em provedores de nuvem { #deploy-fastapi-on-cloud-providers }
|
||||
|
||||
Você pode usar praticamente **qualquer provedor de nuvem** para implantar seu aplicativo FastAPI.
|
||||
Você pode usar praticamente **qualquer provedor de nuvem** para implantar sua aplicação FastAPI.
|
||||
|
||||
Na maioria dos casos, os principais provedores de nuvem têm tutoriais para implantar o FastAPI com eles.
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Está com pressa e já sabe dessas coisas? Pode ir direto para o [`Dockerfile` a
|
||||
<summary>Visualização do Dockerfile 👀</summary>
|
||||
|
||||
```Dockerfile
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
@@ -166,7 +166,7 @@ Agora, no mesmo diretório do projeto, crie um arquivo `Dockerfile` com:
|
||||
|
||||
```{ .dockerfile .annotate }
|
||||
# (1)!
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
# (2)!
|
||||
WORKDIR /code
|
||||
@@ -390,7 +390,7 @@ Se seu FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `
|
||||
Então você só teria que alterar os caminhos correspondentes para copiar o arquivo dentro do `Dockerfile`:
|
||||
|
||||
```{ .dockerfile .annotate hl_lines="10 13" }
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
@@ -454,7 +454,7 @@ Sem usar contêineres, fazer aplicativos executarem na inicialização e com rei
|
||||
|
||||
## Replicação - Número de Processos { #replication-number-of-processes }
|
||||
|
||||
Se você tiver um <abbr title="Um grupo de máquinas que são configuradas para estarem conectadas e trabalharem juntas de alguma forma.">cluster</abbr> de máquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contêineres distribuídos em várias máquinas, então provavelmente desejará **lidar com a replicação** no **nível do cluster** em vez de usar um **gerenciador de processos** (como Uvicorn com workers) em cada contêiner.
|
||||
Se você tiver um <dfn title="Um grupo de máquinas que são configuradas para estarem conectadas e trabalharem juntas de alguma forma.">cluster</dfn> de máquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contêineres distribuídos em várias máquinas, então provavelmente desejará **lidar com a replicação** no **nível do cluster** em vez de usar um **gerenciador de processos** (como Uvicorn com workers) em cada contêiner.
|
||||
|
||||
Um desses sistemas de gerenciamento de contêineres distribuídos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contêineres** enquanto ainda oferece **balanceamento de carga** para as solicitações recebidas. Tudo no **nível do cluster**.
|
||||
|
||||
@@ -499,7 +499,7 @@ Claro, existem **casos especiais** em que você pode querer ter **um contêiner*
|
||||
Nesses casos, você pode usar a opção de linha de comando `--workers` para definir o número de workers que deseja executar:
|
||||
|
||||
```{ .dockerfile .annotate }
|
||||
FROM python:3.9
|
||||
FROM python:3.14
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
@@ -570,7 +570,7 @@ Se você tiver uma configuração simples, com um **único contêiner** que ent
|
||||
|
||||
### Imagem Docker base { #base-docker-image }
|
||||
|
||||
Antes havia uma imagem oficial do FastAPI para Docker: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi-docker</a>. Mas agora ela está descontinuada. ⛔️
|
||||
Antes havia uma imagem oficial do FastAPI para Docker: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>. Mas agora ela está descontinuada. ⛔️
|
||||
|
||||
Você provavelmente **não** deve usar essa imagem base do Docker (ou qualquer outra semelhante).
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Agora, a partir de uma perspectiva do desenvolvedor, aqui estão algumas coisas
|
||||
* Por padrão, isso significa que você só pode ter um certificado HTTPS por endereço IP.
|
||||
* Não importa o tamanho do seu servidor ou quão pequeno cada aplicativo que você tem nele possa ser.
|
||||
* No entanto, existe uma solução para isso.
|
||||
* Há uma extensão para o protocolo TLS (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamada <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>.
|
||||
* Há uma extensão para o protocolo TLS (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamada <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication - Indicação do Nome do Servidor">SNI</abbr></a>.
|
||||
* Esta extensão SNI permite que um único servidor (com um único endereço IP) tenha vários certificados HTTPS e atenda a vários domínios / aplicativos HTTPS.
|
||||
* Para que isso funcione, um único componente (programa) em execução no servidor, ouvindo no endereço IP público, deve ter todos os certificados HTTPS no servidor.
|
||||
* Depois de obter uma conexão segura, o protocolo de comunicação ainda é HTTP.
|
||||
@@ -65,7 +65,7 @@ Aqui está um exemplo de como uma API HTTPS poderia ser estruturada, passo a pas
|
||||
|
||||
A etapa inicial provavelmente seria adquirir algum nome de domínio. Então, você iria configurá-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem).
|
||||
|
||||
Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria um <abbr title="Que não muda">fixo</abbr> Endereço IP público.
|
||||
Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria um <dfn title="Não muda ao longo do tempo. Não é dinâmico.">fixo</dfn> Endereço IP público.
|
||||
|
||||
No(s) servidor(es) DNS, você configuraria um registro (um `A record`) para apontar seu domínio para o endereço IP público do seu servidor.
|
||||
|
||||
@@ -135,7 +135,7 @@ Então, o cliente envia uma solicitação HTTPS. Que é apenas uma solicitação
|
||||
|
||||
<img src="/img/deployment/https/https04.drawio.svg">
|
||||
|
||||
### Desencriptando a Solicitação { #decrypt-the-request }
|
||||
### Desencripte a Solicitação { #decrypt-the-request }
|
||||
|
||||
O Proxy de Terminação TLS então usaria a encriptação combinada para desencriptar a solicitação, e transmitiria a solicitação básica (desencriptada) para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI).
|
||||
|
||||
@@ -186,7 +186,7 @@ Para fazer isso, e acomodar as necessidades de diferentes aplicações, existem
|
||||
* Executar como um servidor (ao menos durante o processo de aquisição do certificado) no endereço IP público associado com o domínio.
|
||||
* Como dito anteriormente, apenas um processo pode estar ligado a uma porta e IP específicos.
|
||||
* Essa é uma dos motivos que fazem utilizar o mesmo Proxy de Terminação TLS para gerenciar a renovação de certificados ser tão útil.
|
||||
* Caso contrário, você pode ter que parar a execução do Proxy de Terminação TLS momentaneamente, inicializar o programa de renovação para renovar os certificados, e então reiniciar o Proxy de Terminação TLS. Isso não é o ideal, já que sua(s) aplicação(ões) não vão estar disponíveis enquanto o Proxy de Terminação TLS estiver desligado.
|
||||
* Caso contrário, você pode ter que parar a execução do Proxy de Terminação TLS momentaneamente, inicializar o programa de renovação para adquirir os certificados, depois configurá-los com o Proxy de Terminação TLS, e então reiniciar o Proxy de Terminação TLS. Isso não é o ideal, já que sua(s) aplicação(ões) não vão estar disponíveis enquanto o Proxy de Terminação TLS estiver desligado.
|
||||
|
||||
Todo esse processo de renovação, enquanto o aplicativo ainda funciona, é uma das principais razões para preferir um sistema separado para gerenciar HTTPS com um Proxy de Terminação TLS em vez de usar os certificados TLS no servidor da aplicação diretamente (e.g. com o Uvicorn).
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Implantar uma aplicação **FastAPI** é relativamente fácil.
|
||||
|
||||
## O que significa Implantação { #what-does-deployment-mean }
|
||||
|
||||
Implantar uma aplicação significa executar as etapas necessárias para torná-la disponível para os usuários.
|
||||
**Implantar** uma aplicação significa executar as etapas necessárias para torná-la **disponível para os usuários**.
|
||||
|
||||
Para uma **web API**, isso normalmente envolve colocá-la em uma **máquina remota**, com um **programa de servidor** que ofereça bom desempenho, estabilidade, etc., de modo que seus **usuários** possam **acessar** a aplicação com eficiência e sem interrupções ou problemas.
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ Você pode utilizar esse comando, por exemplo, para iniciar sua aplicação **Fa
|
||||
|
||||
Vamos nos aprofundar um pouco mais em detalhes.
|
||||
|
||||
FastAPI utiliza um padrão para construir frameworks e servidores web em Python chamado <abbr title="Asynchronous Server Gateway Interface – Interface de Gateway de Servidor Assíncrono">ASGI</abbr>. FastAPI é um framework web ASGI.
|
||||
FastAPI utiliza um padrão para construir frameworks e servidores web em Python chamado <abbr title="Asynchronous Server Gateway Interface - Interface de Gateway de Servidor Assíncrono">ASGI</abbr>. FastAPI é um framework web ASGI.
|
||||
|
||||
A principal coisa que você precisa para executar uma aplicação **FastAPI** (ou qualquer outra aplicação ASGI) em uma máquina de servidor remoto é um programa de servidor ASGI como o **Uvicorn**, que é o que vem por padrão no comando `fastapi`.
|
||||
|
||||
|
||||
@@ -65,14 +65,14 @@ $ <font color="#4E9A06">fastapi</font> run --workers 4 <u style="text-decoration
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27369</b></font><b>]</b>
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27370</b></font><b>]</b>
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>27367</b></font><b>]</b>
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
@@ -64,9 +64,9 @@ O "MINOR" é o número do meio, por exemplo, em `0.2.3`, a versão MINOR é `2`.
|
||||
|
||||
## Atualizando as versões do FastAPI { #upgrading-the-fastapi-versions }
|
||||
|
||||
Você deve adicionar testes para a sua aplicação.
|
||||
Você deveria adicionar testes para a sua aplicação.
|
||||
|
||||
Com **FastAPI** isso é muito fácil (graças ao Starlette), veja a documentação: [Testing](../tutorial/testing.md){.internal-link target=_blank}
|
||||
Com **FastAPI** isso é muito fácil (graças ao Starlette), veja a documentação: [Testes](../tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
Depois que você tiver testes, você pode atualizar a sua versão do **FastAPI** para uma mais recente e se certificar de que todo o seu código está funcionando corretamente executando seus testes.
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ $ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid
|
||||
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
|
||||
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
|
||||
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
|
||||
<b>fastapi run</b>
|
||||
|
||||
Logs:
|
||||
@@ -40,8 +40,8 @@ $ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid
|
||||
quit<b>)</b>
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
|
||||
<span style="background-color="#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
@@ -58,7 +58,7 @@ Internamente, o **FastAPI CLI** usa o <a href="https://www.uvicorn.dev" class="e
|
||||
|
||||
Executar `fastapi dev` inicia o modo de desenvolvimento.
|
||||
|
||||
Por padrão, o recarregamento automático está ativado, recarregando o servidor automaticamente quando você faz mudanças no seu código. Isso consome muitos recursos e pode ser menos estável do que quando está desativado. Você deve usá-lo apenas no desenvolvimento. Ele também escuta no endereço IP `127.0.0.1`, que é o IP para a sua máquina se comunicar apenas consigo mesma (`localhost`).
|
||||
Por padrão, o recarregamento automático está ativado, recarregando o servidor automaticamente quando você faz mudanças no seu código. Isso consome muitos recursos e pode ser menos estável do que quando está desativado. Você deveria usá-lo apenas no desenvolvimento. Ele também escuta no endereço IP `127.0.0.1`, que é o IP para a sua máquina se comunicar apenas consigo mesma (`localhost`).
|
||||
|
||||
## `fastapi run` { #fastapi-run }
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
### Baseado em padrões abertos { #based-on-open-standards }
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> para criação de APIs, incluindo declarações de <abbr title="também conhecido como: endpoints, routes">caminho</abbr> <abbr title="também conhecido como métodos HTTP, como POST, GET, PUT, DELETE">operações</abbr>, parâmetros, requisições de corpo, segurança etc.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> para criação de APIs, incluindo declarações de <dfn title="também conhecido como: endpoints, rotas">caminho</dfn> <dfn title="também conhecido como métodos HTTP, como POST, GET, PUT, DELETE">operações</dfn>, parâmetros, requisições de corpo, segurança etc.
|
||||
* Modelo de documentação automática com <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (já que o OpenAPI em si é baseado no JSON Schema).
|
||||
* Projetado em cima desses padrões após um estudo meticuloso, em vez de uma reflexão breve.
|
||||
* Isso também permite o uso de **geração de código do cliente** automaticamente em muitas linguagens.
|
||||
@@ -136,7 +136,7 @@ Tudo construído como ferramentas e componentes reutilizáveis que são fáceis
|
||||
|
||||
### Injeção de dependência { #dependency-injection }
|
||||
|
||||
FastAPI inclui um sistema de <abbr title='também conhecido como "components", "resources", "services", "providers"'><strong>injeção de dependência</strong></abbr> extremamente fácil de usar, mas extremamente poderoso.
|
||||
FastAPI inclui um sistema de <dfn title='também conhecido como "componentes", "recursos", "serviços", "provedores"'><strong>injeção de dependência</strong></dfn> extremamente fácil de usar, mas extremamente poderoso.
|
||||
|
||||
* Mesmo dependências podem ter dependências, criando uma hierarquia ou **"grafo" de dependências**.
|
||||
* Tudo **automaticamente controlado** pelo framework.
|
||||
@@ -153,8 +153,8 @@ Qualquer integração é projetada para ser tão simples de usar (com dependênc
|
||||
|
||||
### Testado { #tested }
|
||||
|
||||
* 100% <abbr title="A quantidade de código que é testada automaticamente">de cobertura de testes</abbr>.
|
||||
* 100% do código com <abbr title="Anotações de tipo do Python, com isso seu editor e ferramentas externas podem te dar um suporte melhor">anotações de tipo</abbr>.
|
||||
* 100% <dfn title="A quantidade de código que é testada automaticamente">de cobertura de testes</dfn>.
|
||||
* 100% do código com <dfn title="Anotações de tipo do Python, com isso seu editor e ferramentas externas podem te dar um suporte melhor">anotações de tipo</dfn>.
|
||||
* Usado para aplicações em produção.
|
||||
|
||||
## Recursos do Starlette { #starlette-features }
|
||||
@@ -179,7 +179,7 @@ Com **FastAPI**, você terá todos os recursos do **Starlette** (já que FastAPI
|
||||
|
||||
**FastAPI** é totalmente compatível com (e baseado no) <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Então, qualquer código Pydantic adicional que você tiver, também funcionará.
|
||||
|
||||
Incluindo bibliotecas externas também baseadas no Pydantic, como <abbr title="Object-Relational Mapper">ORM</abbr>s e <abbr title="Object-Document Mapper">ODM</abbr>s para bancos de dados.
|
||||
Incluindo bibliotecas externas também baseadas no Pydantic, como <abbr title="Object-Relational Mapper - Mapeador Objeto-Relacional">ORM</abbr>s e <abbr title="Object-Document Mapper - Mapeador Objeto-Documento">ODM</abbr>s para bancos de dados.
|
||||
|
||||
Isso também significa que em muitos casos você poderá passar o mesmo objeto que você receber de uma requisição **diretamente para o banco de dados**, já que tudo é validado automaticamente.
|
||||
|
||||
@@ -190,7 +190,7 @@ Com **FastAPI** você terá todos os recursos do **Pydantic** (já que FastAPI u
|
||||
* **Sem pegadinhas**:
|
||||
* Sem novas definições de esquema de micro-linguagem para aprender.
|
||||
* Se você conhece os tipos do Python, você sabe como usar o Pydantic.
|
||||
* Vai bem com o/a seu/sua **<abbr title="Ambiente de Desenvolvimento Integrado, similar a um editor de código">IDE</abbr>/<abbr title="Um programa que confere erros de código">linter</abbr>/cérebro**:
|
||||
* Vai bem com o/a seu/sua **<abbr title="Integrated Development Environment - Ambiente de Desenvolvimento Integrado: similar a um editor de código">IDE</abbr>/<dfn title="Um programa que confere erros de código">linter</dfn>/cérebro**:
|
||||
* Como as estruturas de dados do Pydantic são apenas instâncias de classes que você define, o preenchimento automático, linting, mypy e a sua intuição devem funcionar corretamente com seus dados validados.
|
||||
* Valida **estruturas complexas**:
|
||||
* Use modelos hierárquicos do Pydantic, `List` e `Dict` do `typing` do Python, etc.
|
||||
|
||||
@@ -24,7 +24,7 @@ Há muitas ferramentas criadas antes que ajudaram a inspirar sua criação.
|
||||
|
||||
Eu estive evitando a criação de um novo _framework_ por vários anos. Primeiro tentei resolver todas as funcionalidades cobertas por **FastAPI** usando muitos _frameworks_, _plug-ins_ e ferramentas diferentes.
|
||||
|
||||
Mas em algum ponto, não havia outra opção senão criar algo que oferecia todas as funcionalidades, aproveitando as melhores ideias de ferramentas anteriores, e combinando-as da melhor maneira possível, usando funcionalidades da linguagem que nem estavam disponíveis antes (_type hints_ do Python 3.6+).
|
||||
Mas em algum ponto, não havia outra opção senão criar algo que oferecia todas as funcionalidades, aproveitando as melhores ideias de ferramentas anteriores, e combinando-as da melhor maneira possível, usando funcionalidades da linguagem que nem estavam disponíveis antes (anotações de tipo do Python 3.6+).
|
||||
|
||||
</blockquote>
|
||||
|
||||
@@ -32,7 +32,7 @@ Mas em algum ponto, não havia outra opção senão criar algo que oferecia toda
|
||||
|
||||
Ao usar todas as alternativas anteriores, eu tive a chance de aprender com todas elas, aproveitar ideias e combiná-las da melhor maneira que encontrei para mim e para os times de desenvolvedores com os quais trabalhava.
|
||||
|
||||
Por exemplo, estava claro que idealmente ele deveria ser baseado nos _type hints_ padrões do Python.
|
||||
Por exemplo, estava claro que idealmente ele deveria ser baseado nas anotações de tipo padrão do Python.
|
||||
|
||||
Também, a melhor abordagem era usar padrões já existentes.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Mas, se por algum motivo seus clientes dependem do comportamento antigo, você p
|
||||
|
||||
Por exemplo, você pode criar uma subclasse de `HTTPBearer` que retorne um erro `403 Forbidden` em vez do erro padrão `401 Unauthorized`:
|
||||
|
||||
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
|
||||
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@ Você pode usar facilmente as mesmas configurações do Pydantic para configurar
|
||||
|
||||
Por exemplo:
|
||||
|
||||
{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *}
|
||||
{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *}
|
||||
|
||||
Aqui declaramos a configuração `openapi_url` com o mesmo padrão de `"/openapi.json"`.
|
||||
|
||||
E então a usamos ao criar a aplicação `FastAPI`.
|
||||
|
||||
Então você pode desabilitar o OpenAPI (incluindo a documentação da interface do usuário) definindo a variável de ambiente `OPENAPI_URL` como uma string vazia, como:
|
||||
Então você pode desabilitar o OpenAPI (incluindo a documentação da interface do usuário) definindo a variável de ambiente `OPENAPI_URL` como a string vazia, como:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Sem alterar as configurações, o destaque de sintaxe é habilitado por padrão:
|
||||
|
||||
Mas você pode desabilitá-lo definindo `syntaxHighlight` como `False`:
|
||||
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *}
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *}
|
||||
|
||||
...e então o Swagger UI não mostrará mais o destaque de sintaxe:
|
||||
|
||||
@@ -28,7 +28,7 @@ Mas você pode desabilitá-lo definindo `syntaxHighlight` como `False`:
|
||||
|
||||
Da mesma forma que você pode definir o tema de destaque de sintaxe com a chave `"syntaxHighlight.theme"` (observe que há um ponto no meio):
|
||||
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *}
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *}
|
||||
|
||||
Essa configuração alteraria o tema de cores de destaque de sintaxe:
|
||||
|
||||
@@ -46,7 +46,7 @@ Você pode substituir qualquer um deles definindo um valor diferente no argument
|
||||
|
||||
Por exemplo, para desabilitar `deepLinking` você pode passar essas configurações para `swagger_ui_parameters`:
|
||||
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *}
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *}
|
||||
|
||||
## Outros parâmetros da UI do Swagger { #other-swagger-ui-parameters }
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
A documentação da API usa **Swagger UI** e **ReDoc**, e cada um deles precisa de alguns arquivos JavaScript e CSS.
|
||||
|
||||
Por padrão, esses arquivos são fornecidos por um <abbr title="Content Delivery Network – Rede de Entrega de Conteúdo: Um serviço, normalmente composto por vários servidores, que fornece arquivos estáticos, como JavaScript e CSS. É comumente usado para providenciar esses arquivos do servidor mais próximo do cliente, melhorando o desempenho.">CDN</abbr>.
|
||||
Por padrão, esses arquivos são fornecidos por um <abbr title="Content Delivery Network - Rede de Entrega de Conteúdo: Um serviço, normalmente composto por vários servidores, que fornece arquivos estáticos, como JavaScript e CSS. É comumente usado para servir esses arquivos a partir do servidor mais próximo do cliente, melhorando o desempenho.">CDN</abbr>.
|
||||
|
||||
Mas é possível personalizá-los, você pode definir um CDN específico ou providenciar os arquivos você mesmo.
|
||||
|
||||
## CDN Personalizado para JavaScript e CSS { #custom-cdn-for-javascript-and-css }
|
||||
|
||||
Vamos supor que você deseja usar um <abbr title="Content Delivery Network – Rede de Entrega de Conteúdo">CDN</abbr> diferente, por exemplo, você deseja usar `https://unpkg.com/`.
|
||||
Vamos supor que você deseja usar um <abbr title="Content Delivery Network - Rede de Entrega de Conteúdo">CDN</abbr> diferente, por exemplo, você deseja usar `https://unpkg.com/`.
|
||||
|
||||
Isso pode ser útil se, por exemplo, você mora em um país que restringe algumas URLs.
|
||||
|
||||
@@ -18,7 +18,7 @@ O primeiro passo é desativar a documentação automática, pois por padrão, el
|
||||
|
||||
Para desativá-los, defina suas URLs como `None` ao criar sua aplicação FastAPI:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *}
|
||||
|
||||
### Incluir a documentação personalizada { #include-the-custom-docs }
|
||||
|
||||
@@ -34,7 +34,7 @@ Você pode reutilizar as funções internas do FastAPI para criar as páginas HT
|
||||
|
||||
E de forma semelhante para o ReDoc...
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -50,7 +50,7 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux
|
||||
|
||||
Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *}
|
||||
|
||||
### Teste { #test-it }
|
||||
|
||||
@@ -118,7 +118,7 @@ Depois disso, sua estrutura de arquivos deve se parecer com:
|
||||
* Importe `StaticFiles`.
|
||||
* "Monte" a instância `StaticFiles()` em um caminho específico.
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *}
|
||||
|
||||
### Teste os arquivos estáticos { #test-the-static-files }
|
||||
|
||||
@@ -129,7 +129,7 @@ Você deverá ver um arquivo JavaScript muito longo para o **ReDoc**.
|
||||
Esse arquivo pode começar com algo como:
|
||||
|
||||
```JavaScript
|
||||
/*! For license information please see redoc.standalone.js.LICENSE.txt */
|
||||
/*! Para informações de licença, consulte redoc.standalone.js.LICENSE.txt */
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
|
||||
...
|
||||
```
|
||||
@@ -144,7 +144,7 @@ Da mesma forma que ao usar um CDN personalizado, o primeiro passo é desativar a
|
||||
|
||||
Para desativá-los, defina suas URLs como `None` ao criar sua aplicação FastAPI:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *}
|
||||
|
||||
### Incluir a documentação personalizada para arquivos estáticos { #include-the-custom-docs-for-static-files }
|
||||
|
||||
@@ -160,7 +160,7 @@ Novamente, você pode reutilizar as funções internas do FastAPI para criar as
|
||||
|
||||
E de forma semelhante para o ReDoc...
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -176,7 +176,7 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux
|
||||
|
||||
Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
|
||||
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *}
|
||||
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *}
|
||||
|
||||
### Teste a UI de Arquivos Estáticos { #test-static-files-ui }
|
||||
|
||||
|
||||
@@ -43,19 +43,19 @@ Por exemplo, vamos adicionar <a href="https://github.com/Rebilly/ReDoc/blob/mast
|
||||
|
||||
Primeiro, escreva toda a sua aplicação **FastAPI** normalmente:
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *}
|
||||
|
||||
### Gerar o esquema OpenAPI { #generate-the-openapi-schema }
|
||||
|
||||
Em seguida, use a mesma função utilitária para gerar o esquema OpenAPI, dentro de uma função `custom_openapi()`:
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *}
|
||||
|
||||
### Modificar o esquema OpenAPI { #modify-the-openapi-schema }
|
||||
|
||||
Agora, você pode adicionar a extensão do ReDoc, incluindo um `x-logo` personalizado ao "objeto" `info` no esquema OpenAPI:
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *}
|
||||
|
||||
### Armazenar em cache o esquema OpenAPI { #cache-the-openapi-schema }
|
||||
|
||||
@@ -65,13 +65,13 @@ Dessa forma, sua aplicação não precisará gerar o esquema toda vez que um usu
|
||||
|
||||
Ele será gerado apenas uma vez, e o mesmo esquema armazenado em cache será utilizado nas próximas requisições.
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *}
|
||||
|
||||
### Sobrescrever o método { #override-the-method }
|
||||
|
||||
Agora, você pode substituir o método `.openapi()` pela sua nova função.
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *}
|
||||
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *}
|
||||
|
||||
### Verificar { #check-it }
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ Para converter qualquer dado para um formato compatível com JSON, leia a seçã
|
||||
|
||||
## OpenAPI Metadata - Docs { #openapi-metadata-docs }
|
||||
|
||||
Para adicionar metadados ao seu esquema OpenAPI, incluindo licensa, versão, contato, etc, leia a seção [Tutorial - Metadados e URLs da Documentação](../tutorial/metadata.md){.internal-link target=_blank}.
|
||||
Para adicionar metadados ao seu esquema OpenAPI, incluindo licença, versão, contato, etc, leia a seção [Tutorial - Metadados e URLs da Documentação](../tutorial/metadata.md){.internal-link target=_blank}.
|
||||
|
||||
## OpenAPI com URL customizada { #openapi-custom-url }
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ Dependendo do seu caso de uso, você pode preferir usar uma biblioteca diferente
|
||||
|
||||
Aqui está uma pequena prévia de como você poderia integrar Strawberry com FastAPI:
|
||||
|
||||
{* ../../docs_src/graphql_/tutorial001_py39.py hl[3,22,25] *}
|
||||
{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *}
|
||||
|
||||
Você pode aprender mais sobre Strawberry na <a href="https://strawberry.rocks/" class="external-link" target="_blank">documentação do Strawberry</a>.
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
Aqui você encontrará diferentes exemplos práticos ou tutoriais de "como fazer" para **vários tópicos**.
|
||||
|
||||
A maioria dessas ideias será mais ou menos **independente**, e na maioria dos casos você só precisará estudá-las se elas se aplicarem diretamente ao **seu projeto**.
|
||||
A maioria dessas ideias será mais ou menos **independente**, e na maioria dos casos você deveria estudá-las apenas se elas se aplicarem diretamente ao **seu projeto**.
|
||||
|
||||
Se algo parecer interessante e útil para o seu projeto, vá em frente e dê uma olhada. Caso contrário, você pode simplesmente ignorá-lo.
|
||||
Se algo parecer interessante e útil para o seu projeto, vá em frente e dê uma olhada. Caso contrário, você pode simplesmente ignorá-las.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ Os recursos chave são:
|
||||
* **Rápido**: alta performance, equivalente a **NodeJS** e **Go** (graças ao Starlette e Pydantic). [Um dos frameworks mais rápidos disponíveis](#performance).
|
||||
* **Rápido para codar**: Aumenta a velocidade para desenvolver recursos entre 200% a 300%. *
|
||||
* **Poucos bugs**: Reduz cerca de 40% de erros induzidos por humanos (desenvolvedores). *
|
||||
* **Intuitivo**: Grande suporte a editores. <abbr title="também conhecido como auto-complete, autocompletion, IntelliSense">Completação</abbr> em todos os lugares. Menos tempo debugando.
|
||||
* **Intuitivo**: Grande suporte a editores. <dfn title="também conhecido como: autocompletar, preenchimento automático, IntelliSense">Completação</dfn> em todos os lugares. Menos tempo debugando.
|
||||
* **Fácil**: Projetado para ser fácil de aprender e usar. Menos tempo lendo docs.
|
||||
* **Enxuto**: Minimize duplicação de código. Múltiplas funcionalidades para cada declaração de parâmetro. Menos bugs.
|
||||
* **Robusto**: Tenha código pronto para produção. E com documentação interativa automática.
|
||||
@@ -368,7 +368,7 @@ item: Item
|
||||
* Validação de dados:
|
||||
* Erros automáticos e claros quando o dado é inválido.
|
||||
* Validação até para objetos JSON profundamente aninhados.
|
||||
* <abbr title="também conhecido como: serialization, parsing, marshalling">Conversão</abbr> de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler:
|
||||
* <dfn title="também conhecido como: serialização, parsing, marshalling">Conversão</dfn> de dados de entrada: vindo da rede para dados e tipos Python. Consegue ler:
|
||||
* JSON.
|
||||
* Parâmetros de path.
|
||||
* Parâmetros query.
|
||||
@@ -376,7 +376,7 @@ item: Item
|
||||
* Cabeçalhos.
|
||||
* Formulários.
|
||||
* Arquivos.
|
||||
* <abbr title="também conhecido como: serialization, parsing, marshalling">Conversão</abbr> de dados de saída: convertendo de tipos e dados Python para dados de rede (como JSON):
|
||||
* <dfn title="também conhecido como: serialização, parsing, marshalling">Conversão</dfn> de dados de saída: convertendo de tipos e dados Python para dados de rede (como JSON):
|
||||
* Converte tipos Python (`str`, `int`, `float`, `bool`, `list` etc).
|
||||
* Objetos `datetime`.
|
||||
* Objetos `UUID`.
|
||||
@@ -439,7 +439,7 @@ Para um exemplo mais completo incluindo mais recursos, veja <a href="https://fas
|
||||
|
||||
* Declaração de **parâmetros** de diferentes lugares como: **cabeçalhos**, **cookies**, **campos de formulários** e **arquivos**.
|
||||
* Como configurar **limitações de validação** como `maximum_length` ou `regex`.
|
||||
* Um poderoso e fácil de usar sistema de **<abbr title="também conhecido como components, resources, providers, services, injectables">Injeção de Dependência</abbr>**.
|
||||
* Um poderoso e fácil de usar sistema de **<dfn title="também conhecido como: componentes, recursos, provedores, serviços, injetáveis">Injeção de Dependência</dfn>**.
|
||||
* Segurança e autenticação, incluindo suporte para **OAuth2** com autenticação com **JWT tokens** e **HTTP Basic**.
|
||||
* Técnicas mais avançadas (mas igualmente fáceis) para declaração de **modelos JSON profundamente aninhados** (graças ao Pydantic).
|
||||
* Integrações **GraphQL** com o <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> e outras bibliotecas.
|
||||
@@ -524,7 +524,7 @@ Utilizado pelo Starlette:
|
||||
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Obrigatório caso você queira utilizar o `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Obrigatório se você quer utilizar a configuração padrão de templates.
|
||||
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obrigatório se você deseja suporte a <abbr title="convertendo a string que vem de uma requisição HTTP em dados Python">"parsing"</abbr> de formulário, com `request.form()`.
|
||||
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Obrigatório se você deseja suporte a <dfn title="convertendo a string que vem de uma requisição HTTP em dados Python">"parsing"</dfn> de formulário, com `request.form()`.
|
||||
|
||||
Utilizado pelo FastAPI:
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Introdução aos tipos Python { #python-types-intro }
|
||||
|
||||
O Python possui suporte para "dicas de tipo" ou "type hints" (também chamado de "anotações de tipo" ou "type annotations")
|
||||
O Python possui suporte para "type hints" opcionais (também chamados de "type annotations").
|
||||
|
||||
Esses **"type hints"** são uma sintaxe especial que permite declarar o <abbr title = "por exemplo: str, int, float, bool">tipo</abbr> de uma variável.
|
||||
Esses **"type hints"** ou anotações são uma sintaxe especial que permite declarar o <dfn title="por exemplo: str, int, float, bool">tipo</dfn> de uma variável.
|
||||
|
||||
Ao declarar tipos para suas variáveis, editores e ferramentas podem oferecer um melhor suporte.
|
||||
|
||||
Este é apenas um **tutorial rápido / atualização** sobre type hints do Python. Ele cobre apenas o mínimo necessário para usá-los com o **FastAPI**... que é realmente muito pouco.
|
||||
|
||||
O **FastAPI** é baseado nesses type hints, eles oferecem muitas vantagens e benefícios.
|
||||
O **FastAPI** é todo baseado nesses type hints, eles oferecem muitas vantagens e benefícios.
|
||||
|
||||
Mas mesmo que você nunca use o **FastAPI**, você se beneficiaria de aprender um pouco sobre eles.
|
||||
|
||||
@@ -22,7 +22,7 @@ Se você é um especialista em Python e já sabe tudo sobre type hints, pule par
|
||||
|
||||
Vamos começar com um exemplo simples:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py *}
|
||||
{* ../../docs_src/python_types/tutorial001_py310.py *}
|
||||
|
||||
A chamada deste programa gera:
|
||||
|
||||
@@ -34,9 +34,9 @@ A função faz o seguinte:
|
||||
|
||||
* Pega um `first_name` e `last_name`.
|
||||
* Converte a primeira letra de cada uma em maiúsculas com `title()`.
|
||||
* <abbr title = "Agrupa-os, como um. Com o conteúdo de um após o outro.">Concatena</abbr> com um espaço no meio.
|
||||
* <dfn title="Coloca-os juntos, como um só. Com o conteúdo de um após o outro.">Concatena</dfn> com um espaço no meio.
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
|
||||
{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *}
|
||||
|
||||
### Edite-o { #edit-it }
|
||||
|
||||
@@ -52,7 +52,7 @@ Era `upper`? Era `uppercase`? `first_uppercase`? `capitalize`?
|
||||
|
||||
Em seguida, tente com o velho amigo do programador, o preenchimento automático do editor.
|
||||
|
||||
Você digita o primeiro parâmetro da função, `first_name`, depois um ponto (`.`) e, em seguida, pressiona `Ctrl + Space` para acionar a conclusão.
|
||||
Você digita o primeiro parâmetro da função, `first_name`, depois um ponto (`.`) e, em seguida, pressiona `Ctrl+Space` para acionar o preenchimento automático.
|
||||
|
||||
Mas, infelizmente, você não obtém nada útil:
|
||||
|
||||
@@ -78,7 +78,7 @@ para:
|
||||
|
||||
Esses são os "type hints":
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *}
|
||||
|
||||
Isso não é o mesmo que declarar valores padrão como seria com:
|
||||
|
||||
@@ -88,7 +88,7 @@ Isso não é o mesmo que declarar valores padrão como seria com:
|
||||
|
||||
É uma coisa diferente.
|
||||
|
||||
Estamos usando dois pontos (`:`), não é igual a (`=`).
|
||||
Estamos usando dois pontos (`:`), não sinal de igual (`=`).
|
||||
|
||||
E adicionar type hints normalmente não muda o que acontece do que aconteceria sem eles.
|
||||
|
||||
@@ -106,17 +106,17 @@ Com isso, você pode rolar, vendo as opções, até encontrar o que "soa familia
|
||||
|
||||
Verifique esta função, ela já possui type hints:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *}
|
||||
|
||||
Como o editor conhece os tipos de variáveis, você não obtém apenas o preenchimento automático, mas também as verificações de erro:
|
||||
Como o editor conhece os tipos das variáveis, você não obtém apenas o preenchimento automático, mas também as verificações de erro:
|
||||
|
||||
<img src="/img/python-types/image04.png">
|
||||
|
||||
Agora você sabe que precisa corrigí-lo, converta `age` em uma string com `str(age)`:
|
||||
Agora você sabe que precisa corrigi-la, convertendo `age` em uma string com `str(age)`:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
|
||||
{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *}
|
||||
|
||||
## Declarando Tipos { #declaring-types }
|
||||
## Declarando tipos { #declaring-types }
|
||||
|
||||
Você acabou de ver o local principal para declarar type hints. Como parâmetros de função.
|
||||
|
||||
@@ -133,29 +133,32 @@ Você pode usar, por exemplo:
|
||||
* `bool`
|
||||
* `bytes`
|
||||
|
||||
{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *}
|
||||
|
||||
### Tipos genéricos com parâmetros de tipo { #generic-types-with-type-parameters }
|
||||
### Módulo `typing` { #typing-module }
|
||||
|
||||
Existem algumas estruturas de dados que podem conter outros valores, como `dict`, `list`, `set` e `tuple`. E os valores internos também podem ter seu próprio tipo.
|
||||
Para alguns casos adicionais, você pode precisar importar alguns itens do módulo padrão `typing`, por exemplo, quando quiser declarar que algo pode ter "qualquer tipo", você pode usar `Any` de `typing`:
|
||||
|
||||
Estes tipos que possuem tipos internos são chamados de tipos "**genéricos**". E é possível declará-los mesmo com os seus tipos internos.
|
||||
```python
|
||||
from typing import Any
|
||||
|
||||
Para declarar esses tipos e os tipos internos, você pode usar o módulo Python padrão `typing`. Ele existe especificamente para suportar esses type hints.
|
||||
|
||||
#### Versões mais recentes do Python { #newer-versions-of-python }
|
||||
def some_function(data: Any):
|
||||
print(data)
|
||||
```
|
||||
|
||||
A sintaxe utilizando `typing` é **compatível** com todas as versões, desde o Python 3.6 até as últimas, incluindo o Python 3.9, 3.10, etc.
|
||||
### Tipos genéricos { #generic-types }
|
||||
|
||||
Conforme o Python evolui, **novas versões** chegam com suporte melhorado para esses type annotations, e em muitos casos, você não precisará nem importar e utilizar o módulo `typing` para declarar os type annotations.
|
||||
Alguns tipos podem receber "parâmetros de tipo" entre colchetes, para definir seus tipos internos, por exemplo, uma "lista de strings" seria declarada como `list[str]`.
|
||||
|
||||
Se você pode escolher uma versão mais recente do Python para o seu projeto, você poderá aproveitar isso ao seu favor.
|
||||
Esses tipos que podem receber parâmetros de tipo são chamados **tipos genéricos** ou **genéricos**.
|
||||
|
||||
Em todos os documentos existem exemplos compatíveis com cada versão do Python (quando existem diferenças).
|
||||
Você pode usar os mesmos tipos internos como genéricos (com colchetes e tipos dentro):
|
||||
|
||||
Por exemplo, "**Python 3.6+**" significa que é compatível com o Python 3.6 ou superior (incluindo o 3.7, 3.8, 3.9, 3.10, etc). E "**Python 3.9+**" significa que é compatível com o Python 3.9 ou mais recente (incluindo o 3.10, etc).
|
||||
|
||||
Se você pode utilizar a **versão mais recente do Python**, utilize os exemplos para as últimas versões. Eles terão as **melhores e mais simples sintaxes**, como por exemplo, "**Python 3.10+**".
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
#### List { #list }
|
||||
|
||||
@@ -167,11 +170,11 @@ Como o tipo, coloque `list`.
|
||||
|
||||
Como a lista é um tipo que contém tipos internos, você os coloca entre colchetes:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *}
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Estes tipos internos dentro dos colchetes são chamados "parâmetros de tipo" (type parameters).
|
||||
Esses tipos internos dentro dos colchetes são chamados de "parâmetros de tipo".
|
||||
|
||||
Neste caso, `str` é o parâmetro de tipo passado para `list`.
|
||||
|
||||
@@ -193,9 +196,9 @@ E, ainda assim, o editor sabe que é um `str` e fornece suporte para isso.
|
||||
|
||||
Você faria o mesmo para declarar `tuple`s e `set`s:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *}
|
||||
|
||||
Isso significa que:
|
||||
Isso significa:
|
||||
|
||||
* A variável `items_t` é uma `tuple` com 3 itens, um `int`, outro `int` e uma `str`.
|
||||
* A variável `items_s` é um `set`, e cada um de seus itens é do tipo `bytes`.
|
||||
@@ -208,7 +211,7 @@ O primeiro parâmetro de tipo é para as chaves do `dict`.
|
||||
|
||||
O segundo parâmetro de tipo é para os valores do `dict`:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
|
||||
{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *}
|
||||
|
||||
Isso significa que:
|
||||
|
||||
@@ -218,46 +221,22 @@ Isso significa que:
|
||||
|
||||
#### Union { #union }
|
||||
|
||||
Você pode declarar que uma variável pode ser de qualquer um dentre **diversos tipos**. Por exemplo, um `int` ou um `str`.
|
||||
Você pode declarar que uma variável pode ser de qualquer um dentre **vários tipos**, por exemplo, um `int` ou um `str`.
|
||||
|
||||
No Python 3.6 e superior (incluindo o Python 3.10), você pode utilizar o tipo `Union` de `typing`, e colocar dentro dos colchetes os possíveis tipos aceitáveis.
|
||||
Para defini-la, você usa a <dfn title='também chamado de "operador OU bit a bit", mas esse significado não é relevante aqui'>barra vertical (`|`)</dfn> para separar ambos os tipos.
|
||||
|
||||
No Python 3.10 também existe uma **nova sintaxe** onde você pode colocar os possíveis tipos separados por uma <abbr title='também chamado de "bitwise ou operador", mas o significado é irrelevante aqui'>barra vertical (`|`)</abbr>.
|
||||
|
||||
//// tab | Python 3.10+
|
||||
Isso é chamado de "união", porque a variável pode ser qualquer coisa na união desses dois conjuntos de tipos.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial008b_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Em ambos os casos, isso significa que `item` poderia ser um `int` ou um `str`.
|
||||
Isso significa que `item` pode ser um `int` ou um `str`.
|
||||
|
||||
#### Possivelmente `None` { #possibly-none }
|
||||
|
||||
Você pode declarar que um valor pode ter um tipo, como `str`, mas que ele também pode ser `None`.
|
||||
|
||||
No Python 3.6 e superior (incluindo o Python 3.10) você pode declará-lo importando e utilizando `Optional` do módulo `typing`.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009_py39.py!}
|
||||
```
|
||||
|
||||
O uso de `Optional[str]` em vez de apenas `str` permitirá que o editor o ajude a detectar erros, onde você pode estar assumindo que um valor é sempre um `str`, quando na verdade também pode ser `None`.
|
||||
|
||||
`Optional[Something]` é na verdade um atalho para `Union[Something, None]`, eles são equivalentes.
|
||||
|
||||
Isso também significa que no Python 3.10, você pode utilizar `Something | None`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
@@ -266,96 +245,7 @@ Isso também significa que no Python 3.10, você pode utilizar `Something | None
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial009_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ alternativa
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial009b_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
#### Utilizando `Union` ou `Optional` { #using-union-or-optional }
|
||||
|
||||
Se você está utilizando uma versão do Python abaixo da 3.10, aqui vai uma dica do meu ponto de vista bem **subjetivo**:
|
||||
|
||||
* 🚨 Evite utilizar `Optional[SomeType]`
|
||||
* No lugar, ✨ **use `Union[SomeType, None]`** ✨.
|
||||
|
||||
Ambos são equivalentes, e no final das contas, eles são o mesmo. Mas eu recomendaria o `Union` ao invés de `Optional` porque a palavra **Optional** parece implicar que o valor é opcional, quando na verdade significa "isso pode ser `None`", mesmo que ele não seja opcional e ainda seja obrigatório.
|
||||
|
||||
Eu penso que `Union[SomeType, None]` é mais explícito sobre o que ele significa.
|
||||
|
||||
Isso é apenas sobre palavras e nomes. Mas estas palavras podem afetar como os seus colegas de trabalho pensam sobre o código.
|
||||
|
||||
Por exemplo, vamos pegar esta função:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
|
||||
|
||||
O parâmetro `name` é definido como `Optional[str]`, mas ele **não é opcional**, você não pode chamar a função sem o parâmetro:
|
||||
|
||||
```Python
|
||||
say_hi() # Oh, no, this throws an error! 😱
|
||||
```
|
||||
|
||||
O parâmetro `name` **ainda é obrigatório** (não *opcional*) porque ele não possui um valor padrão. Mesmo assim, `name` aceita `None` como valor:
|
||||
|
||||
```Python
|
||||
say_hi(name=None) # This works, None is valid 🎉
|
||||
```
|
||||
|
||||
A boa notícia é, quando você estiver no Python 3.10 você não precisará se preocupar mais com isso, pois você poderá simplesmente utilizar o `|` para definir uniões de tipos:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
|
||||
|
||||
E então você não precisará mais se preocupar com nomes como `Optional` e `Union`. 😎
|
||||
|
||||
#### Tipos genéricos { #generic-types }
|
||||
|
||||
Esses tipos que usam parâmetros de tipo entre colchetes são chamados **tipos genéricos** ou **genéricos**. Por exemplo:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
Você pode utilizar os mesmos tipos internos como genéricos (com colchetes e tipos dentro):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
E o mesmo que com versões anteriores do Python, do módulo `typing`:
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...entre outros.
|
||||
|
||||
No Python 3.10, como uma alternativa para a utilização dos genéricos `Union` e `Optional`, você pode usar a <abbr title='também chamado de "bitwise ou operador", mas o significado não é relevante aqui'>barra vertical (`|`)</abbr> para declarar uniões de tipos. Isso é muito melhor e mais simples.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
Você pode utilizar os mesmos tipos internos como genéricos (com colchetes e tipos dentro):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
E genéricos do módulo `typing`:
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...entre outros.
|
||||
|
||||
////
|
||||
Usar `str | None` em vez de apenas `str` permitirá que o editor o ajude a detectar erros em que você poderia estar assumindo que um valor é sempre um `str`, quando na verdade ele também pode ser `None`.
|
||||
|
||||
### Classes como tipos { #classes-as-types }
|
||||
|
||||
@@ -363,13 +253,13 @@ Você também pode declarar uma classe como o tipo de uma variável.
|
||||
|
||||
Digamos que você tenha uma classe `Person`, com um nome:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
|
||||
{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *}
|
||||
|
||||
Então você pode declarar que uma variável é do tipo `Person`:
|
||||
|
||||
{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
|
||||
{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *}
|
||||
|
||||
E então, novamente, você recebe todo o apoio do editor:
|
||||
E então, novamente, você recebe todo o suporte do editor:
|
||||
|
||||
<img src="/img/python-types/image06.png">
|
||||
|
||||
@@ -379,7 +269,7 @@ Isso não significa que "`one_person` é a **classe** chamada `Person`".
|
||||
|
||||
## Modelos Pydantic { #pydantic-models }
|
||||
|
||||
O <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> é uma biblioteca Python para executar a validação de dados.
|
||||
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> é uma biblioteca Python para executar a validação de dados.
|
||||
|
||||
Você declara a "forma" dos dados como classes com atributos.
|
||||
|
||||
@@ -403,23 +293,17 @@ O **FastAPI** é todo baseado em Pydantic.
|
||||
|
||||
Você verá muito mais disso na prática no [Tutorial - Guia do usuário](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
O Pydantic tem um comportamento especial quando você usa `Optional` ou `Union[Something, None]` sem um valor padrão. Você pode ler mais sobre isso na documentação do Pydantic sobre <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">campos Opcionais Obrigatórios</a>.
|
||||
|
||||
///
|
||||
|
||||
## Type Hints com Metadados de Anotações { #type-hints-with-metadata-annotations }
|
||||
|
||||
O Python possui uma funcionalidade que nos permite incluir **<abbr title="Informação sobre a informação, neste caso, informação sobre o tipo, e.g. uma descrição.">metadados</abbr> adicionais** nos type hints utilizando `Annotated`.
|
||||
O Python também possui uma funcionalidade que permite incluir **<dfn title="Informações sobre os dados, neste caso, informações sobre o tipo, por exemplo, uma descrição.">metadados</dfn> adicionais** nesses type hints utilizando `Annotated`.
|
||||
|
||||
Desde o Python 3.9, `Annotated` faz parte da biblioteca padrão, então você pode importá-lo de `typing`.
|
||||
Você pode importar `Annotated` de `typing`.
|
||||
|
||||
{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
|
||||
{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *}
|
||||
|
||||
O Python em si não faz nada com este `Annotated`. E para editores e outras ferramentas, o tipo ainda é `str`.
|
||||
|
||||
Mas você pode utilizar este espaço dentro do `Annotated` para fornecer ao **FastAPI** metadata adicional sobre como você deseja que a sua aplicação se comporte.
|
||||
Mas você pode utilizar este espaço dentro do `Annotated` para fornecer ao **FastAPI** metadados adicionais sobre como você deseja que a sua aplicação se comporte.
|
||||
|
||||
O importante aqui de se lembrar é que **o primeiro *type parameter*** que você informar ao `Annotated` é o **tipo de fato**. O resto é apenas metadado para outras ferramentas.
|
||||
|
||||
@@ -446,12 +330,12 @@ Com o **FastAPI**, você declara parâmetros com type hints e obtém:
|
||||
|
||||
... e o **FastAPI** usa as mesmas declarações para:
|
||||
|
||||
* **Definir requisitos**: dos parâmetros de rota, parâmetros da consulta, cabeçalhos, corpos, dependências, etc.
|
||||
* **Converter dados**: da solicitação para o tipo necessário.
|
||||
* **Validar dados**: provenientes de cada solicitação:
|
||||
* **Definir requisitos**: dos parâmetros de path da request, parâmetros da query, cabeçalhos, corpos, dependências, etc.
|
||||
* **Converter dados**: da request para o tipo necessário.
|
||||
* **Validar dados**: provenientes de cada request:
|
||||
* Gerando **erros automáticos** retornados ao cliente quando os dados são inválidos.
|
||||
* **Documentar** a API usando OpenAPI:
|
||||
* que é usado pelas interfaces de usuário da documentação interativa automática.
|
||||
* que é usada pelas interfaces de usuário da documentação interativa automática.
|
||||
|
||||
Tudo isso pode parecer abstrato. Não se preocupe. Você verá tudo isso em ação no [Tutorial - Guia do usuário](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
@@ -459,6 +343,6 @@ O importante é que, usando tipos padrão de Python, em um único local (em vez
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Se você já passou por todo o tutorial e voltou para ver mais sobre os tipos, um bom recurso é <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank"> a "cheat sheet" do `mypy` </a>.
|
||||
Se você já passou por todo o tutorial e voltou para ver mais sobre os tipos, um bom recurso é <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">a "cheat sheet" do `mypy`</a>.
|
||||
|
||||
///
|
||||
|
||||
11
docs/pt/docs/translation-banner.md
Normal file
11
docs/pt/docs/translation-banner.md
Normal file
@@ -0,0 +1,11 @@
|
||||
/// details | 🌐 Tradução por IA e humanos
|
||||
|
||||
Esta tradução foi feita por IA orientada por humanos. 🤝
|
||||
|
||||
Ela pode conter erros de interpretação do significado original ou soar pouco natural, etc. 🤖
|
||||
|
||||
Você pode melhorar esta tradução [ajudando-nos a orientar melhor o LLM de IA](https://fastapi.tiangolo.com/pt/contributing/#translations).
|
||||
|
||||
[Versão em inglês](ENGLISH_VERSION_URL)
|
||||
|
||||
///
|
||||
@@ -15,7 +15,7 @@ Isso inclui, por exemplo:
|
||||
|
||||
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_py39.py hl[1,13] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *}
|
||||
|
||||
O **FastAPI** criará o objeto do tipo `BackgroundTasks` para você e o passará como esse parâmetro.
|
||||
|
||||
@@ -31,13 +31,13 @@ Neste caso, a função da tarefa escreverá em um arquivo (simulando o envio de
|
||||
|
||||
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_py39.py hl[6:9] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *}
|
||||
|
||||
## Adicione a tarefa em segundo plano { #add-the-background-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_py39.py hl[14] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *}
|
||||
|
||||
O `.add_task()` recebe como argumentos:
|
||||
|
||||
|
||||
@@ -58,17 +58,17 @@ A mesma estrutura de arquivos com comentários:
|
||||
|
||||
```bash
|
||||
.
|
||||
├── app # "app" is a Python package
|
||||
│ ├── __init__.py # this file makes "app" a "Python package"
|
||||
│ ├── main.py # "main" module, e.g. import app.main
|
||||
│ ├── dependencies.py # "dependencies" module, e.g. import app.dependencies
|
||||
│ └── routers # "routers" is a "Python subpackage"
|
||||
│ │ ├── __init__.py # makes "routers" a "Python subpackage"
|
||||
│ │ ├── items.py # "items" submodule, e.g. import app.routers.items
|
||||
│ │ └── users.py # "users" submodule, e.g. import app.routers.users
|
||||
│ └── internal # "internal" is a "Python subpackage"
|
||||
│ ├── __init__.py # makes "internal" a "Python subpackage"
|
||||
│ └── admin.py # "admin" submodule, e.g. import app.internal.admin
|
||||
├── app # "app" é um pacote Python
|
||||
│ ├── __init__.py # este arquivo torna "app" um "pacote Python"
|
||||
│ ├── main.py # módulo "main", p.ex., import app.main
|
||||
│ ├── dependencies.py # módulo "dependencies", p.ex., import app.dependencies
|
||||
│ └── routers # "routers" é um "subpacote Python"
|
||||
│ │ ├── __init__.py # torna "routers" um "subpacote Python"
|
||||
│ │ ├── items.py # submódulo "items", p.ex., import app.routers.items
|
||||
│ │ └── users.py # submódulo "users", p.ex., import app.routers.users
|
||||
│ └── internal # "internal" é um "subpacote Python"
|
||||
│ ├── __init__.py # torna "internal" um "subpacote Python"
|
||||
│ └── admin.py # submódulo "admin", p.ex., import app.internal.admin
|
||||
```
|
||||
|
||||
## `APIRouter` { #apirouter }
|
||||
@@ -85,7 +85,7 @@ Você pode criar as *operações de rota* para esse módulo usando o `APIRouter`
|
||||
|
||||
Você o importa e cria uma "instância" da mesma maneira que faria com a classe `FastAPI`:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||
|
||||
### *Operações de Rota* com `APIRouter` { #path-operations-with-apirouter }
|
||||
|
||||
@@ -93,7 +93,7 @@ E então você o utiliza para declarar suas *operações de rota*.
|
||||
|
||||
Utilize-o da mesma maneira que utilizaria a classe `FastAPI`:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
|
||||
|
||||
Você pode pensar em `APIRouter` como uma classe "mini `FastAPI`".
|
||||
|
||||
@@ -117,7 +117,7 @@ Então, as colocamos em seu próprio módulo de `dependencies` (`app/dependencie
|
||||
|
||||
Agora usaremos uma dependência simples para ler um cabeçalho `X-Token` personalizado:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -149,7 +149,7 @@ Sabemos que todas as *operações de rota* neste módulo têm o mesmo:
|
||||
|
||||
Então, em vez de adicionar tudo isso a cada *operação de rota*, podemos adicioná-lo ao `APIRouter`.
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
|
||||
|
||||
Como o path de cada *operação de rota* tem que começar com `/`, como em:
|
||||
|
||||
@@ -208,7 +208,7 @@ E precisamos obter a função de dependência do módulo `app.dependencies`, o a
|
||||
|
||||
Então usamos uma importação relativa com `..` para as dependências:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *}
|
||||
|
||||
#### Como funcionam as importações relativas { #how-relative-imports-work }
|
||||
|
||||
@@ -279,7 +279,7 @@ Não estamos adicionando o prefixo `/items` nem `tags=["items"]` a cada *operaç
|
||||
|
||||
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*:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -305,13 +305,13 @@ Você importa e cria uma classe `FastAPI` normalmente.
|
||||
|
||||
E podemos até declarar [dependências globais](dependencies/global-dependencies.md){.internal-link target=_blank} que serão combinadas com as dependências para cada `APIRouter`:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *}
|
||||
|
||||
### Importe o `APIRouter` { #import-the-apirouter }
|
||||
|
||||
Agora importamos os outros submódulos que possuem `APIRouter`s:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *}
|
||||
|
||||
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".
|
||||
|
||||
@@ -374,13 +374,13 @@ o `router` de `users` sobrescreveria o de `items` e não poderíamos usá-los ao
|
||||
|
||||
Então, para poder usar ambos no mesmo arquivo, importamos os submódulos diretamente:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *}
|
||||
|
||||
### Inclua os `APIRouter`s para `users` e `items` { #include-the-apirouters-for-users-and-items }
|
||||
|
||||
Agora, vamos incluir os `router`s dos submódulos `users` e `items`:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *}
|
||||
|
||||
/// info | Informação
|
||||
|
||||
@@ -420,13 +420,13 @@ Ele contém um `APIRouter` com algumas *operações de rota* de administração
|
||||
|
||||
Para este exemplo, será super simples. Mas digamos que, como ele é compartilhado com outros projetos na organização, não podemos modificá-lo e adicionar um `prefix`, `dependencies`, `tags`, etc. diretamente ao `APIRouter`:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
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()`:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *}
|
||||
|
||||
Dessa forma, o `APIRouter` original permanecerá inalterado, para que possamos compartilhar o mesmo arquivo `app/internal/admin.py` com outros projetos na organização.
|
||||
|
||||
@@ -447,7 +447,7 @@ Também podemos adicionar *operações de rota* diretamente ao aplicativo `FastA
|
||||
|
||||
Aqui fazemos isso... só para mostrar que podemos 🤷:
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
|
||||
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *}
|
||||
|
||||
e funcionará corretamente, junto com todas as outras *operações de rota* adicionadas com `app.include_router()`.
|
||||
|
||||
|
||||
@@ -104,12 +104,6 @@ Dado que, por padrão, valores singulares são interpretados como parâmetros de
|
||||
q: str | None = None
|
||||
```
|
||||
|
||||
Ou em Python 3.9:
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = None
|
||||
```
|
||||
|
||||
Por exemplo:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
|
||||
|
||||
@@ -164,7 +164,7 @@ images: list[Image]
|
||||
|
||||
como em:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *}
|
||||
|
||||
## Suporte de editor em todo canto { #editor-support-everywhere }
|
||||
|
||||
@@ -194,7 +194,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_py39.py hl[7] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -72,9 +72,9 @@ Apenas com essa declaração de tipos do Python, o **FastAPI** irá:
|
||||
* Validar os dados.
|
||||
* 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.
|
||||
* Como você o declarou na função como do tipo `Item`, você também terá o suporte do editor (preenchimento automático, etc) para todos os atributos e seus tipos.
|
||||
* 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.
|
||||
* 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 { #automatic-docs }
|
||||
|
||||
@@ -88,7 +88,7 @@ E também serão utilizados na documentação da API dentro de cada *operação
|
||||
|
||||
## Suporte do editor { #editor-support }
|
||||
|
||||
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):
|
||||
No seu editor, dentro da função você receberá dicas de tipos e preenchimento automático 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">
|
||||
|
||||
@@ -155,7 +155,7 @@ Os parâmetros da função serão reconhecidos conforme abaixo:
|
||||
|
||||
O FastAPI saberá que o valor de `q` não é obrigatório por causa do valor padrão `= None`.
|
||||
|
||||
O `str | None` (Python 3.10+) ou o `Union` em `Union[str, None]` (Python 3.9+) 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`.
|
||||
O `str | None` 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.
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Essa mesma técnica se aplica para `Query`, `Cookie`, e `Header`. 😎
|
||||
|
||||
## 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`:
|
||||
Declare os parâmetros de **cookie** de que você precisa em um **modelo Pydantic**, e depois declare o parâmetro como `Cookie`:
|
||||
|
||||
{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *}
|
||||
|
||||
@@ -46,7 +46,7 @@ Mas mesmo que você **adicionar os dados** e clicar em "Executar", pelo motivo d
|
||||
|
||||
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 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>. 🤪🍪
|
||||
Agora a sua API possui o poder de controlar o seu próprio <dfn 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</dfn>. 🤪🍪
|
||||
|
||||
Você pode utilizar a configuração do modelo Pydantic para `proibir` qualquer campo `extra`:
|
||||
|
||||
@@ -54,9 +54,9 @@ Você pode utilizar a configuração do modelo Pydantic para `proibir` qualquer
|
||||
|
||||
Se o cliente tentar enviar alguns **cookies extras**, eles receberão um retorno de **erro**.
|
||||
|
||||
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>. 🍪
|
||||
Coitados dos banners de cookies com todo o seu esforço para obter o seu consentimento para a <dfn title="Isso é uma outra piada. Não preste atenção em mim. Beba um café com o seu cookie. ☕">API rejeitá-lo</dfn>. 🍪
|
||||
|
||||
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>:
|
||||
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` <dfn title="O papai noel desaprova a falta de biscoitos. 🎅 Ok, chega de piadas com os cookies.">cookie não é permitido</dfn>:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -73,4 +73,4 @@ Por exemplo, se o cliente tentar enviar um cookie `santa_tracker` com o valor de
|
||||
|
||||
## Resumo { #summary }
|
||||
|
||||
Você consegue utilizar **modelos Pydantic** para declarar <abbr title="Coma um último biscoito antes de você ir embora. 🍪">**cookies**</abbr> no **FastAPI**. 😎
|
||||
Você consegue utilizar **modelos Pydantic** para declarar <dfn title="Coma um último biscoito antes de você ir embora. 🍪">**cookies**</dfn> no **FastAPI**. 😎
|
||||
|
||||
@@ -46,7 +46,8 @@ Você também pode especificar se o seu backend permite:
|
||||
* Métodos HTTP específicos (`POST`, `PUT`) ou todos eles com o curinga `"*"`.
|
||||
* Cabeçalhos HTTP específicos ou todos eles com o curinga `"*"`.
|
||||
|
||||
{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
|
||||
{* ../../docs_src/cors/tutorial001_py310.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 cross domain.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Você pode conectar o depurador no seu editor, por exemplo, com o Visual Studio
|
||||
|
||||
Em sua aplicação FastAPI, importe e execute `uvicorn` diretamente:
|
||||
|
||||
{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
|
||||
{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *}
|
||||
|
||||
### Sobre `__name__ == "__main__"` { #about-name-main }
|
||||
|
||||
@@ -62,7 +62,7 @@ from myapp import app
|
||||
# Mais um pouco de código
|
||||
```
|
||||
|
||||
nesse caso, a variável criada automaticamente dentro de `myapp.py` não terá a variável `__name__` com o valor `"__main__"`.
|
||||
nesse caso, a variável `__name__` criada automaticamente dentro de `myapp.py` não terá o valor `"__main__"`.
|
||||
|
||||
Então, a linha:
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ O **FastAPI** chama a classe `CommonQueryParams`. Isso cria uma "instância" des
|
||||
|
||||
Perceba como escrevemos `CommonQueryParams` duas vezes no código abaixo:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
@@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -137,7 +137,7 @@ O último `CommonQueryParams`, em:
|
||||
|
||||
Nesse caso, o primeiro `CommonQueryParams`, em:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, ...
|
||||
@@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ...
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -163,7 +163,7 @@ commons: CommonQueryParams ...
|
||||
|
||||
Na verdade você poderia escrever apenas:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||
@@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -197,7 +197,7 @@ Mas declarar o tipo é encorajado por que é a forma que o seu editor de texto s
|
||||
|
||||
Mas você pode ver que temos uma repetição do código neste exemplo, escrevendo `CommonQueryParams` duas vezes:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
@@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -225,7 +225,7 @@ Para esses casos específicos, você pode fazer o seguinte:
|
||||
|
||||
Em vez de escrever:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
@@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
|
||||
...escreva:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends()]
|
||||
@@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()]
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 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*.
|
||||
Em alguns casos você não precisa necessariamente do valor de retorno de uma dependência dentro de uma *função de operação de rota*.
|
||||
|
||||
Ou a dependência não retorna nenhum valor.
|
||||
|
||||
@@ -14,7 +14,7 @@ O *decorador da operação de rota* recebe um argumento opcional `dependencies`.
|
||||
|
||||
Ele deve ser uma lista de `Depends()`:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *}
|
||||
|
||||
Essas dependências serão executadas/resolvidas da mesma forma que dependências comuns. Mas o valor delas (se existir algum) não será passado para a sua *função de operação de rota*.
|
||||
|
||||
@@ -44,13 +44,13 @@ Você pode utilizar as mesmas *funções* de dependências que você usaria norm
|
||||
|
||||
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] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *}
|
||||
|
||||
### Levantar exceções { #raise-exceptions }
|
||||
|
||||
Essas dependências podem `raise` exceções, da mesma forma que dependências comuns:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *}
|
||||
|
||||
### Valores de retorno { #return-values }
|
||||
|
||||
@@ -58,7 +58,7 @@ E elas também podem ou não retornar valores, eles não serão utilizados.
|
||||
|
||||
Então, você pode reutilizar uma dependência comum (que retorna um valor) que já seja utilizada em outro lugar, e mesmo que o valor não seja utilizado, a dependência será executada:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *}
|
||||
|
||||
## Dependências para um grupo de *operações de rota* { #dependencies-for-a-group-of-path-operations }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Dependências com yield { #dependencies-with-yield }
|
||||
|
||||
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>.
|
||||
O **FastAPI** possui suporte para dependências que realizam <dfn 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</dfn>.
|
||||
|
||||
Para fazer isso, utilize `yield` em vez de `return`, e escreva os passos extras (código) depois.
|
||||
|
||||
@@ -29,15 +29,15 @@ Por exemplo, você poderia utilizar isso para criar uma sessão do banco de dado
|
||||
|
||||
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_py39.py hl[2:4] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *}
|
||||
|
||||
O valor gerado (yielded) é o que é injetado nas *operações de rota* e outras dependências:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *}
|
||||
|
||||
O código após o `yield` é executado após a resposta:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -57,7 +57,7 @@ Então, você pode procurar por essa exceção específica dentro da dependênci
|
||||
|
||||
Da mesma forma, você pode utilizar `finally` para garantir que os passos de saída são executados, com ou sem exceções.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *}
|
||||
|
||||
## Subdependências com `yield` { #sub-dependencies-with-yield }
|
||||
|
||||
@@ -67,7 +67,7 @@ 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`:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *}
|
||||
|
||||
E todas elas podem utilizar `yield`.
|
||||
|
||||
@@ -75,7 +75,7 @@ Neste caso, `dependency_c`, para executar seu código de saída, precisa que o v
|
||||
|
||||
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.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *}
|
||||
|
||||
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.
|
||||
|
||||
@@ -109,7 +109,7 @@ Mas ela existe para ser utilizada caso você precise. 🤓
|
||||
|
||||
///
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
|
||||
{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *}
|
||||
|
||||
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}.
|
||||
|
||||
@@ -117,7 +117,7 @@ Se você quiser capturar exceções e criar uma resposta personalizada com base
|
||||
|
||||
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] *}
|
||||
{* ../../docs_src/dependencies/tutorial008c_an_py310.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. 😱
|
||||
|
||||
@@ -127,7 +127,7 @@ Se você capturar uma exceção em uma dependência com `yield`, a menos que voc
|
||||
|
||||
Você pode relançar a mesma exceção utilizando `raise`:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
|
||||
{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *}
|
||||
|
||||
Agora o cliente irá receber a mesma resposta *HTTP 500 Internal Server Error*, mas o servidor terá nosso `InternalError` personalizado nos logs. 😎
|
||||
|
||||
@@ -190,7 +190,7 @@ Normalmente, o código de saída das dependências com `yield` é executado **ap
|
||||
|
||||
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**.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *}
|
||||
|
||||
`Depends()` recebe um parâmetro `scope` que pode ser:
|
||||
|
||||
@@ -269,7 +269,7 @@ Em Python, você pode criar Gerenciadores de Contexto ao <a href="https://docs.p
|
||||
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_py39.py hl[1:9,13] *}
|
||||
{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ De forma semelhante a [adicionar `dependencies` aos *decoradores de operação d
|
||||
|
||||
Nesse caso, elas serão aplicadas a todas as *operações de rota* da aplicação:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *}
|
||||
{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *}
|
||||
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Dependências { #dependencies }
|
||||
|
||||
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>**.
|
||||
O **FastAPI** possui um poderoso, mas intuitivo sistema de **<dfn title="também conhecida como: componentes, recursos, provedores, serviços, injetáveis">Injeção de Dependência</dfn>**.
|
||||
|
||||
Esse sistema foi pensado para ser fácil de usar, e permitir que qualquer desenvolvedor possa integrar facilmente outros componentes ao **FastAPI**.
|
||||
|
||||
@@ -25,7 +25,7 @@ Vamos ver um exemplo simples. Tão simples que não será muito útil, por enqua
|
||||
|
||||
Mas dessa forma podemos focar em como o sistema de **Injeção de Dependência** funciona.
|
||||
|
||||
### Criando uma dependência, ou "injetável" { #create-a-dependency-or-dependable }
|
||||
### Criando uma dependência, ou "dependable" { #create-a-dependency-or-dependable }
|
||||
|
||||
Primeiro vamos focar na dependência.
|
||||
|
||||
@@ -89,7 +89,7 @@ Você verá quais outras "coisas", além de funções, podem ser usadas como dep
|
||||
|
||||
Sempre que uma nova requisição for realizada, o **FastAPI** se encarrega de:
|
||||
|
||||
* Chamar sua dependência ("injetável") com os parâmetros corretos.
|
||||
* Chamar sua dependência ("dependable") com os parâmetros corretos.
|
||||
* Obter o resultado da função.
|
||||
* Atribuir esse resultado para o parâmetro em sua *função de operação de rota*.
|
||||
|
||||
@@ -186,7 +186,7 @@ Outros termos comuns para essa mesma ideia de "injeção de dependência" são:
|
||||
|
||||
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*.
|
||||
|
||||
E as dependências pode ser criadas de uma forma bastante simples e intuitiva que permite que você importe apenas os pacotes Python que forem necessários, e integrá-los com as funções de sua API em algumas linhas de código, *literalmente*.
|
||||
E as dependências podem ser criadas de uma forma bastante simples e intuitiva que permite que você importe apenas os pacotes Python que forem necessários, e integrá-los com as funções de sua API em algumas linhas de código, *literalmente*.
|
||||
|
||||
Você verá exemplos disso nos próximos capítulos, acerca de bancos de dados relacionais e NoSQL, segurança, etc.
|
||||
|
||||
@@ -199,7 +199,7 @@ A simplicidade do sistema de injeção de dependência do **FastAPI** faz ele co
|
||||
* pacotes externos
|
||||
* APIs externas
|
||||
* sistemas de autenticação e autorização
|
||||
* istemas de monitoramento de uso para APIs
|
||||
* sistemas de monitoramento de uso para APIs
|
||||
* sistemas de injeção de dados de resposta
|
||||
* etc.
|
||||
|
||||
@@ -209,7 +209,7 @@ Mesmo que o sistema hierárquico de injeção de dependência seja simples de de
|
||||
|
||||
Você pode definir dependências que por sua vez definem suas próprias dependências.
|
||||
|
||||
No fim, uma árvore hierárquica de dependências é criadas, e o sistema de **Injeção de Dependência** toma conta de resolver todas essas dependências (e as sub-dependências delas) para você, e provê (injeta) os resultados em cada passo.
|
||||
Por fim, uma árvore hierárquica de dependências é criada, e o sistema de **Injeção de Dependência** toma conta de resolver todas essas dependências (e as sub-dependências delas) para você, e provê (injeta) os resultados em cada passo.
|
||||
|
||||
Por exemplo, vamos supor que você possua 4 endpoints na sua API (*operações de rota*):
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query
|
||||
|
||||
Se uma de suas dependências é declarada várias vezes para a mesma *operação de rota*, por exemplo, múltiplas dependências com uma mesma subdependência, o **FastAPI** irá chamar essa subdependência uma única vez para cada requisição.
|
||||
|
||||
E o valor retornado é salvo em um <abbr title="Um utilitário/sistema para armazenar valores calculados/gerados para serem reutilizados em vez de computá-los novamente.">"cache"</abbr> e repassado para todos os "dependentes" que precisam dele em uma requisição específica, em vez de chamar a dependência múltiplas vezes para uma mesma requisição.
|
||||
E o valor retornado é salvo em um <dfn title="Um utilitário/sistema para armazenar valores calculados/gerados para serem reutilizados em vez de computá-los novamente.">"cache"</dfn> e repassado para todos os "dependentes" que precisam dele em uma requisição específica, em vez de chamar a dependência múltiplas vezes para uma mesma requisição.
|
||||
|
||||
Em um cenário avançado onde você precise que a dependência seja calculada em cada passo (possivelmente várias vezes) de uma requisição em vez de utilizar o valor em "cache", você pode definir o parâmetro `use_cache=False` em `Depends`:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
|
||||
@@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -190,9 +190,9 @@ Mas se colocarmos isso na atribuição `response_model=PlaneItem | CarItem`, ter
|
||||
|
||||
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):
|
||||
Para isso, use o padrão Python `list`:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
|
||||
{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *}
|
||||
|
||||
## Resposta com `dict` arbitrário { #response-with-arbitrary-dict }
|
||||
|
||||
@@ -200,9 +200,9 @@ Você também pode declarar uma resposta usando um simples `dict` arbitrário, d
|
||||
|
||||
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 `dict`:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
|
||||
{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *}
|
||||
|
||||
## Recapitulação { #recap }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
O arquivo FastAPI mais simples pode se parecer com:
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py *}
|
||||
|
||||
Copie o conteúdo para um arquivo `main.py`.
|
||||
|
||||
@@ -183,7 +183,7 @@ Deploying to FastAPI Cloud...
|
||||
|
||||
### Passo 1: importe `FastAPI` { #step-1-import-fastapi }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *}
|
||||
|
||||
`FastAPI` é uma classe Python que fornece todas as funcionalidades para sua API.
|
||||
|
||||
@@ -197,7 +197,7 @@ Você pode usar todas as funcionalidades do <a href="https://www.starlette.dev/"
|
||||
|
||||
### Passo 2: crie uma "instância" de `FastAPI` { #step-2-create-a-fastapi-instance }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *}
|
||||
|
||||
Aqui, a variável `app` será uma "instância" da classe `FastAPI`.
|
||||
|
||||
@@ -266,12 +266,12 @@ Vamos chamá-los de "**operações**" também.
|
||||
|
||||
#### Defina um decorador de operação de rota { #define-a-path-operation-decorator }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.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:
|
||||
|
||||
* o path `/`
|
||||
* usando uma <abbr title="um método HTTP GET">operação <code>get</code></abbr>
|
||||
* usando uma <dfn title="um método HTTP GET"><code>get</code> operação</dfn>
|
||||
|
||||
/// info | Informações sobre `@decorator`
|
||||
|
||||
@@ -320,7 +320,7 @@ Esta é a nossa "**função de operação de rota**":
|
||||
* **operação**: é `get`.
|
||||
* **função**: é a função abaixo do "decorador" (abaixo do `@app.get("/")`).
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *}
|
||||
|
||||
Esta é uma função Python.
|
||||
|
||||
@@ -332,7 +332,7 @@ Neste caso, é uma função `async`.
|
||||
|
||||
Você também pode defini-la como uma função normal em vez de `async def`:
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
|
||||
{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
@@ -342,7 +342,7 @@ Se você não sabe a diferença, verifique o [Async: *"Com pressa?"*](../async.m
|
||||
|
||||
### Passo 5: retorne o conteúdo { #step-5-return-the-content }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *}
|
||||
|
||||
Você pode retornar um `dict`, `list` e valores singulares como `str`, `int`, etc.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Para retornar ao cliente *responses* HTTP com erros, use o `HTTPException`.
|
||||
|
||||
### Import `HTTPException` { #import-httpexception }
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
|
||||
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *}
|
||||
|
||||
### Lance o `HTTPException` no seu código { #raise-an-httpexception-in-your-code }
|
||||
|
||||
@@ -33,13 +33,13 @@ Para retornar ao cliente *responses* HTTP com erros, use o `HTTPException`.
|
||||
|
||||
E porque é uma exceção do Python, você não **retorna** (return) o `HTTPException`, você lança o (raise) no seu código.
|
||||
|
||||
Isso também significa que, se você está escrevendo uma função de utilidade, a qual você está chamando dentro da sua função de operações de caminhos, e você lança o `HTTPException` dentro da função de utilidade, o resto do seu código não será executado dentro da função de operações de caminhos. Ao contrário, o `HTTPException` irá finalizar a requisição no mesmo instante e enviará o erro HTTP oriundo do `HTTPException` para o cliente.
|
||||
Isso também significa que, se você está escrevendo uma função de utilidade, a qual você está chamando dentro da sua função de operação de rota, e você lança o `HTTPException` dentro da função de utilidade, o resto do seu código não será executado dentro da função de operação de rota. Ao contrário, o `HTTPException` irá finalizar a requisição no mesmo instante e enviará o erro HTTP oriundo do `HTTPException` para o cliente.
|
||||
|
||||
O benefício de lançar uma exceção em vez de retornar um valor ficará mais evidente na seção sobre Dependências e Segurança.
|
||||
|
||||
Neste exemplo, quando o cliente pede, na requisição, por um item cujo ID não existe, a exceção com o status code `404` é lançada:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
|
||||
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *}
|
||||
|
||||
### A response resultante { #the-resulting-response }
|
||||
|
||||
@@ -77,7 +77,7 @@ Você provavelmente não precisará utilizar esses headers diretamente no seu c
|
||||
|
||||
Mas caso você precise, para um cenário mais complexo, você pode adicionar headers customizados:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
|
||||
{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *}
|
||||
|
||||
## Instale manipuladores de exceções customizados { #install-custom-exception-handlers }
|
||||
|
||||
@@ -87,9 +87,9 @@ Digamos que você tenha uma exceção customizada `UnicornException` que você (
|
||||
|
||||
Nesse cenário, se você precisa manipular essa exceção de modo global com o FastAPI, você pode adicionar um manipulador de exceção customizada com `@app.exception_handler()`.
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
|
||||
{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *}
|
||||
|
||||
Nesse cenário, se você fizer uma requisição para `/unicorns/yolo`, a *operação de caminho* vai lançar (`raise`) o `UnicornException`.
|
||||
Nesse cenário, se você fizer uma requisição para `/unicorns/yolo`, a *operação de rota* vai lançar (`raise`) o `UnicornException`.
|
||||
|
||||
Essa exceção será manipulada, contudo, pelo `unicorn_exception_handler`.
|
||||
|
||||
@@ -125,7 +125,7 @@ Para sobrescrevê-lo, importe o `RequestValidationError` e use-o com o `@app.exc
|
||||
|
||||
O manipulador de exceções receberá um `Request` e a exceção.
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
|
||||
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *}
|
||||
|
||||
Se você for ao `/items/foo`, em vez de receber o JSON padrão com o erro:
|
||||
|
||||
@@ -157,7 +157,7 @@ Do mesmo modo, você pode sobrescrever o `HTTPException`.
|
||||
|
||||
Por exemplo, você pode querer retornar uma *response* em *plain text* ao invés de um JSON para os seguintes erros:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
|
||||
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *}
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
@@ -181,7 +181,7 @@ O `RequestValidationError` contém o `body` que ele recebeu de dados inválidos.
|
||||
|
||||
Você pode utilizá-lo enquanto desenvolve seu app para registrar o *body* e debugá-lo, e assim retorná-lo ao usuário, etc.
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
|
||||
{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *}
|
||||
|
||||
Tente enviar um item inválido como este:
|
||||
|
||||
@@ -237,6 +237,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
|
||||
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`:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
|
||||
{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *}
|
||||
|
||||
Nesse exemplo você apenas imprime (`print`) o erro com uma mensagem expressiva. Mesmo assim, dá para pegar a ideia. Você pode usar a exceção e então apenas re-usar o manipulador de exceção *default*.
|
||||
|
||||
@@ -12,7 +12,7 @@ Primeiro importe `Header`:
|
||||
|
||||
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:
|
||||
Você pode definir o valor padrão, assim como todas as validações extras ou parâmetros de anotação:
|
||||
|
||||
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Metadados e Urls de Documentos { #metadata-and-docs-urls }
|
||||
# Metadados e URLs da Documentação { #metadata-and-docs-urls }
|
||||
|
||||
Você pode personalizar várias configurações de metadados na sua aplicação **FastAPI**.
|
||||
|
||||
@@ -18,7 +18,7 @@ Você pode definir os seguintes campos que são usados na especificação OpenAP
|
||||
|
||||
Você pode defini-los da seguinte maneira:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
|
||||
{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -32,11 +32,11 @@ Com essa configuração, a documentação automática da API se pareceria com:
|
||||
|
||||
## 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.
|
||||
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`.
|
||||
|
||||
Por exemplo:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
|
||||
{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *}
|
||||
|
||||
## Metadados para tags { #metadata-for-tags }
|
||||
|
||||
@@ -58,7 +58,7 @@ Vamos tentar isso em um exemplo com tags para `users` e `items`.
|
||||
|
||||
Crie metadados para suas tags e passe-os para o parâmetro `openapi_tags`:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
|
||||
{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *}
|
||||
|
||||
Observe que você pode usar Markdown dentro das descrições. Por exemplo, "login" será exibido em negrito (**login**) e "fancy" será exibido em itálico (_fancy_).
|
||||
|
||||
@@ -72,7 +72,7 @@ Você não precisa adicionar metadados para todas as tags que você usa.
|
||||
|
||||
Use o parâmetro `tags` com suas *operações de rota* (e `APIRouter`s) para atribuí-los a diferentes tags:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
|
||||
{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *}
|
||||
|
||||
/// info | Informação
|
||||
|
||||
@@ -100,7 +100,7 @@ Mas você pode configurá-lo com o parâmetro `openapi_url`.
|
||||
|
||||
Por exemplo, para defini-lo para ser servido em `/api/v1/openapi.json`:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
|
||||
{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *}
|
||||
|
||||
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.
|
||||
|
||||
@@ -117,4 +117,4 @@ Você pode configurar as duas interfaces de documentação incluídas:
|
||||
|
||||
Por exemplo, para definir o Swagger UI para ser servido em `/documentation` e desativar o ReDoc:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
|
||||
{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *}
|
||||
|
||||
@@ -31,13 +31,13 @@ A função middleware recebe:
|
||||
* Então ela retorna a `response` gerada pela *operação de rota* correspondente.
|
||||
* Você pode então modificar ainda mais o `response` antes de retorná-lo.
|
||||
|
||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
|
||||
{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *}
|
||||
|
||||
/// 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>.
|
||||
|
||||
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>.
|
||||
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">Documentação CORS da Starlette</a>.
|
||||
|
||||
///
|
||||
|
||||
@@ -57,7 +57,7 @@ E também depois que a `response` é gerada, antes de retorná-la.
|
||||
|
||||
Por exemplo, você pode adicionar um cabeçalho personalizado `X-Process-Time` contendo o tempo em segundos que levou para processar a solicitação e gerar uma resposta:
|
||||
|
||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
|
||||
{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ Nestes casos, pode fazer sentido armazenar as tags em um `Enum`.
|
||||
|
||||
**FastAPI** suporta isso da mesma maneira que com strings simples:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *}
|
||||
|
||||
## Resumo e descrição { #summary-and-description }
|
||||
|
||||
@@ -56,7 +56,7 @@ Você pode adicionar um `summary` e uma `description`:
|
||||
|
||||
## 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á.
|
||||
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 <dfn 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</dfn> 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).
|
||||
|
||||
@@ -90,9 +90,9 @@ Então, se você não fornecer uma, o **FastAPI** irá gerar automaticamente uma
|
||||
|
||||
## 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`:
|
||||
Se você precisar marcar uma *operação de rota* como <dfn title="obsoleta, recomendado não usar">descontinuada</dfn>, mas sem removê-la, passe o parâmetro `deprecated`:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *}
|
||||
|
||||
Ela será claramente marcada como descontinuada nas documentações interativas:
|
||||
|
||||
|
||||
@@ -54,11 +54,11 @@ Isso não faz diferença para o **FastAPI**. Ele vai detectar os parâmetros pel
|
||||
|
||||
Então, você pode declarar sua função assim:
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *}
|
||||
|
||||
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()`.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *}
|
||||
|
||||
## Ordene os parâmetros de acordo com sua necessidade, truques { #order-the-parameters-as-you-need-tricks }
|
||||
|
||||
@@ -81,15 +81,15 @@ Se você quiser:
|
||||
|
||||
Passe `*`, como o primeiro parâmetro da funçã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.
|
||||
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="De: 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_py39.py hl[7] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *}
|
||||
|
||||
### Melhor com `Annotated` { #better-with-annotated }
|
||||
|
||||
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 `*`.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *}
|
||||
|
||||
## Validações numéricas: maior que ou igual { #number-validations-greater-than-or-equal }
|
||||
|
||||
@@ -97,7 +97,7 @@ Com `Query` e `Path` (e outras que você verá depois) você pode declarar restr
|
||||
|
||||
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] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *}
|
||||
|
||||
## Validações numéricas: maior que e menor que ou igual { #number-validations-greater-than-and-less-than-or-equal }
|
||||
|
||||
@@ -106,7 +106,7 @@ 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_an_py39.py hl[10] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *}
|
||||
|
||||
## Validações numéricas: floats, maior que e menor que { #number-validations-floats-greater-than-and-less-than }
|
||||
|
||||
@@ -118,7 +118,7 @@ Assim, `0.5` seria um valor válido. Mas `0.0` ou `0` não seriam.
|
||||
|
||||
E o mesmo para <abbr title="less than – menor que"><code>lt</code></abbr>.
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *}
|
||||
|
||||
## Recapitulando { #recap }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
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_py39.py hl[6:7] *}
|
||||
{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *}
|
||||
|
||||
O valor do parâmetro de path `item_id` será passado para a sua função como o argumento `item_id`.
|
||||
|
||||
@@ -16,7 +16,7 @@ Então, se você executar este exemplo e acessar <a href="http://127.0.0.1:8000/
|
||||
|
||||
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_py39.py hl[7] *}
|
||||
{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *}
|
||||
|
||||
Neste caso, `item_id` é declarado como um `int`.
|
||||
|
||||
@@ -24,7 +24,7 @@ Neste caso, `item_id` é declarado como um `int`.
|
||||
Isso fornecerá suporte do editor dentro da sua função, com verificações de erros, preenchimento automático, etc.
|
||||
///
|
||||
|
||||
## Dados <abbr title="também conhecido como: serialização, parsing, marshalling">conversão</abbr> { #data-conversion }
|
||||
## Dados <dfn title="também conhecido como: serialização, parsing, marshalling">conversão</dfn> { #data-conversion }
|
||||
|
||||
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:
|
||||
|
||||
@@ -35,7 +35,7 @@ Se você executar este exemplo e abrir seu navegador em <a href="http://127.0.0.
|
||||
/// 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.
|
||||
Então, com essa declaração de tipo, o **FastAPI** fornece <dfn title="convertendo a string que vem de um request HTTP em dados Python">"parsing"</dfn> automático do request.
|
||||
///
|
||||
|
||||
## Validação de dados { #data-validation }
|
||||
@@ -110,19 +110,19 @@ E então você também pode ter um path `/users/{user_id}` para obter dados sobr
|
||||
|
||||
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_py39.py hl[6,11] *}
|
||||
{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *}
|
||||
|
||||
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"`.
|
||||
|
||||
Da mesma forma, você não pode redefinir uma operação de rota:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
|
||||
{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *}
|
||||
|
||||
A primeira sempre será usada, já que o path corresponde primeiro.
|
||||
|
||||
## Valores predefinidos { #predefined-values }
|
||||
|
||||
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.
|
||||
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 - Enumeração">`Enum`</abbr> padrão do Python.
|
||||
|
||||
### Crie uma classe `Enum` { #create-an-enum-class }
|
||||
|
||||
@@ -132,17 +132,17 @@ Ao herdar de `str`, a documentação da API saberá que os valores devem ser do
|
||||
|
||||
Em seguida, crie atributos de classe com valores fixos, que serão os valores válidos disponíveis:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *}
|
||||
|
||||
/// 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 modelos de Aprendizado de Máquina <dfn title="Tecnicamente, arquiteturas de modelos de Deep Learning">modelos</dfn>.
|
||||
///
|
||||
|
||||
### Declare um parâmetro de path { #declare-a-path-parameter }
|
||||
|
||||
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_py39.py hl[16] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
|
||||
|
||||
### Verifique a documentação { #check-the-docs }
|
||||
|
||||
@@ -158,13 +158,13 @@ O valor do *parâmetro de path* será um *membro de enumeração*.
|
||||
|
||||
Você pode compará-lo com o *membro de enumeração* no seu enum `ModelName` criado:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *}
|
||||
|
||||
#### Obtenha o valor da enumeração { #get-the-enumeration-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_py39.py hl[20] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *}
|
||||
|
||||
/// tip | Dica
|
||||
Você também pode acessar o valor `"lenet"` com `ModelName.lenet.value`.
|
||||
@@ -176,7 +176,7 @@ Você pode retornar *membros de enum* da sua *operação de rota*, até mesmo an
|
||||
|
||||
Eles serão convertidos para seus valores correspondentes (strings neste caso) antes de serem retornados ao cliente:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *}
|
||||
|
||||
No seu cliente, você receberá uma resposta JSON como:
|
||||
|
||||
@@ -215,7 +215,7 @@ Nesse caso, o nome do parâmetro é `file_path`, e a última parte, `:path`, diz
|
||||
|
||||
Então, você pode usá-lo com:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
|
||||
{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *}
|
||||
|
||||
/// tip | Dica
|
||||
Você pode precisar que o parâmetro contenha `/home/johndoe/myfile.txt`, com uma barra inicial (`/`).
|
||||
@@ -227,8 +227,8 @@ Nesse caso, a URL seria: `/files//home/johndoe/myfile.txt`, com uma barra dupla
|
||||
|
||||
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
|
||||
- Suporte no editor: verificações de erro, preenchimento automático, etc.
|
||||
- "<dfn title="convertendo a string que vem de um request HTTP em dados Python">parsing</dfn>" de dados
|
||||
- Validação de dados
|
||||
- Anotação da API e documentação automática
|
||||
|
||||
|
||||
@@ -18,10 +18,9 @@ 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 a Documentação { #check-the-docs }
|
||||
|
||||
## Verifique os Documentos { #check-the-docs }
|
||||
|
||||
Você pode ver os parâmetros de consulta nos documentos de IU em `/docs`:
|
||||
Você pode ver os parâmetros de consulta na IU da documentação em `/docs`:
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/query-param-models/image01.png">
|
||||
@@ -29,9 +28,9 @@ Você pode ver os parâmetros de consulta nos documentos de IU em `/docs`:
|
||||
|
||||
## 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.
|
||||
Em alguns casos especiais (provavelmente não muito comuns), você queira **restringir** os parâmetros de consulta que deseja receber.
|
||||
|
||||
Você pode usar a configuração do modelo Pydantic para `forbid` (proibir) qualquer campo `extra`:
|
||||
Você pode usar a configuração do modelo Pydantic para `forbid` qualquer campo `extra`:
|
||||
|
||||
{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *}
|
||||
|
||||
@@ -43,7 +42,7 @@ Por exemplo, se o cliente tentar enviar um parâmetro de consulta `tool` com o v
|
||||
https://example.com/items/?limit=10&tool=plumbus
|
||||
```
|
||||
|
||||
Eles receberão um retorno de **erro** informando-os que o parâmentro de consulta `tool` não é permitido:
|
||||
Eles receberão um retorno de **erro** informando-os que o parâmetro de consulta `tool` não é permitido:
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ Ter `str | None` permitirá que seu editor lhe ofereça melhor suporte e detecte
|
||||
|
||||
## Validação adicional { #additional-validation }
|
||||
|
||||
Vamos impor que, embora `q` seja opcional, sempre que for fornecido, **seu comprimento 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` e `Annotated` { #import-query-and-annotated }
|
||||
|
||||
@@ -47,40 +47,16 @@ Agora é a hora de usá-lo com FastAPI. 🚀
|
||||
|
||||
Tínhamos esta anotação de tipo:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
q: str | None = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
O que faremos é envolver isso com `Annotated`, para que fique assim:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
q: Annotated[str | None] = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
q: Annotated[Union[str, None]] = None
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
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. 🎉
|
||||
@@ -93,23 +69,23 @@ Agora que temos esse `Annotated` onde podemos colocar mais informações (neste
|
||||
|
||||
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. 😎
|
||||
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()`.
|
||||
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()`.
|
||||
|
||||
///
|
||||
|
||||
Agora o FastAPI vai:
|
||||
|
||||
* **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**)
|
||||
* 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)
|
||||
|
||||
## Alternativa (antiga): `Query` como valor padrão { #alternative-old-query-as-the-default-value }
|
||||
|
||||
Versões anteriores do FastAPI (antes de <abbr title="before 2023-03 - 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`, há uma grande chance de você ver código usando isso por aí, então vou explicar.
|
||||
Versões anteriores do FastAPI (antes de <dfn title="antes de 2023-03">0.95.0</dfn>) exigiam que você usasse `Query` como valor padrão do seu parâmetro, em vez de colocá-lo em `Annotated`, há uma grande chance de você ver código usando isso por aí, então vou explicar.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -144,7 +120,7 @@ Então, podemos passar mais parâmetros para `Query`. Neste caso, o parâmetro `
|
||||
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.
|
||||
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 }
|
||||
|
||||
@@ -174,13 +150,13 @@ 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. 🤓
|
||||
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. 😌
|
||||
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.
|
||||
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.
|
||||
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>. 🚀
|
||||
|
||||
@@ -192,7 +168,7 @@ Você também pode adicionar um parâmetro `min_length`:
|
||||
|
||||
## Adicione expressões regulares { #add-regular-expressions }
|
||||
|
||||
Você pode definir um `pattern` de <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings. - 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:
|
||||
Você pode definir um `pattern` de <dfn 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</dfn> que o parâmetro deve corresponder:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
|
||||
|
||||
@@ -202,9 +178,9 @@ Esse padrão específico de expressão regular verifica se o valor recebido no p
|
||||
* `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.
|
||||
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**.
|
||||
Agora você sabe que, sempre que precisar delas, pode usá-las no FastAPI.
|
||||
|
||||
## Valores padrão { #default-values }
|
||||
|
||||
@@ -212,7 +188,7 @@ 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] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
@@ -242,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None
|
||||
|
||||
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_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *}
|
||||
|
||||
### Obrigatório, pode ser `None` { #required-can-be-none }
|
||||
|
||||
@@ -266,7 +242,7 @@ Então, com uma URL como:
|
||||
http://localhost:8000/items/?q=foo&q=bar
|
||||
```
|
||||
|
||||
você receberia os múltiplos valores dos *parâmetros 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`.
|
||||
você receberia os múltiplos valores dos parâmetros 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:
|
||||
|
||||
@@ -293,7 +269,7 @@ A documentação interativa da API será atualizada de acordo, permitindo múlti
|
||||
|
||||
Você também pode definir uma `list` de valores padrão caso nenhum seja fornecido:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *}
|
||||
|
||||
Se você for até:
|
||||
|
||||
@@ -316,13 +292,13 @@ o valor padrão de `q` será: `["foo", "bar"]` e sua resposta será:
|
||||
|
||||
Você também pode usar `list` diretamente em vez de `list[str]`:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
Tenha em mente que, neste caso, o FastAPI não verificará o conteúdo da lista.
|
||||
|
||||
Por exemplo, `list[int]` verificaria (e documentaria) que os conteúdos da lista são inteiros. Mas `list` sozinho não.
|
||||
Por exemplo, `list[int]` verificaria (and documentaria) que os conteúdos da lista são inteiros. Mas `list` sozinho não.
|
||||
|
||||
///
|
||||
|
||||
@@ -372,7 +348,7 @@ Então você pode declarar um `alias`, e esse alias será usado para encontrar o
|
||||
|
||||
Agora digamos que você não gosta mais desse parâmetro.
|
||||
|
||||
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="obsolete, recommended not to use it - obsoleto, recomenda-se não usá-lo">deprecated</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á <dfn title="obsoleto, recomenda-se não usá-lo">descontinuado</dfn>.
|
||||
|
||||
Então passe o parâmetro `deprecated=True` para `Query`:
|
||||
|
||||
@@ -390,9 +366,9 @@ Para excluir um parâmetro de consulta do OpenAPI gerado (e portanto, dos sistem
|
||||
|
||||
## 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.
|
||||
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`).
|
||||
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`.
|
||||
|
||||
@@ -402,7 +378,7 @@ O Pydantic também tem <a href="https://docs.pydantic.dev/latest/concepts/valida
|
||||
|
||||
///
|
||||
|
||||
Por exemplo, este validador personalizado verifica se o ID do item começa com `isbn-` para um número de livro <abbr title="ISBN means International Standard Book Number - 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) is a website with information about movies - IMDB (Internet Movie Database) é um site com informações sobre filmes">IMDB</abbr>:
|
||||
Por exemplo, este validador personalizado verifica se o ID do item começa com `isbn-` para um número de livro <abbr title="International Standard Book Number - Número Padrão Internacional de Livro">ISBN</abbr> ou com `imdb-` para um ID de URL de filme <abbr title="Internet Movie Database - Base de Dados de Filmes da Internet: um site com informações sobre filmes">IMDB</abbr>:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
|
||||
|
||||
@@ -414,15 +390,15 @@ 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ê deveria usar **Dependências do FastAPI** em vez disso; você aprenderá sobre elas mais adiante.
|
||||
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ê deveria 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.
|
||||
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. 🤸
|
||||
O ponto importante é apenas usar `AfterValidator` com uma função dentro de `Annotated`. Sinta-se à vontade para pular esta parte. 🤸
|
||||
|
||||
---
|
||||
|
||||
@@ -436,17 +412,17 @@ Percebeu? Uma string usando `value.startswith()` pode receber uma tupla, e verif
|
||||
|
||||
#### Um item aleatório { #a-random-item }
|
||||
|
||||
Com `data.items()` obtemos um <abbr title="Something we can iterate on with a for loop, like a list, set, etc. - 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.
|
||||
Com `data.items()` obtemos um <dfn title="Algo que podemos iterar com um laço for, como uma list, set, etc.">objeto iterável</dfn> 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")`.
|
||||
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`.
|
||||
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? 🐍
|
||||
...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] *}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
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".
|
||||
|
||||
{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
|
||||
{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *}
|
||||
|
||||
A consulta é o conjunto de pares chave-valor que vai depois de `?` na URL, separado pelo caractere `&`.
|
||||
|
||||
@@ -24,7 +24,7 @@ Mas quando você declara eles com os tipos do Python (no exemplo acima, como `in
|
||||
Todo o processo que era aplicado para parâmetros de rota também é aplicado para parâmetros de consulta:
|
||||
|
||||
* Suporte do editor (obviamente)
|
||||
* <abbr title="convertendo uma string que vem de um request HTTP em um dado Python">"Parsing"</abbr> de dados
|
||||
* <dfn title="convertendo a string que vem de um request HTTP em dados Python">"análise"</dfn> de dados
|
||||
* Validação de dados
|
||||
* Documentação automática
|
||||
|
||||
@@ -127,7 +127,7 @@ Caso você não queira adicionar um valor específico mas queira apenas torná-l
|
||||
|
||||
Porém, quando você quiser fazer com que o parâmetro de consulta seja obrigatório, você pode simplesmente não declarar nenhum valor como padrão.
|
||||
|
||||
{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
|
||||
{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *}
|
||||
|
||||
Aqui o parâmetro de consulta `needy` é um valor obrigatório, do tipo `str`.
|
||||
|
||||
|
||||
@@ -20,13 +20,13 @@ Isso é necessário, visto que os arquivos enviados são enviados como "dados de
|
||||
|
||||
Importe `File` e `UploadFile` de `fastapi`:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
|
||||
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## Definir Parâmetros `File` { #define-file-parameters }
|
||||
|
||||
Crie parâmetros de arquivo da mesma forma que você faria para `Body` ou `Form`:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
|
||||
|
||||
/// info | Informação
|
||||
|
||||
@@ -54,7 +54,7 @@ Mas há muitos casos em que você pode se beneficiar do uso de `UploadFile`.
|
||||
|
||||
Defina um parâmetro de arquivo com um tipo de `UploadFile`:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
|
||||
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *}
|
||||
|
||||
Utilizar `UploadFile` tem várias vantagens sobre `bytes`:
|
||||
|
||||
@@ -121,7 +121,7 @@ Dados de formulários normalmente são codificados usando o "media type" `applic
|
||||
|
||||
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 – Rede de Desenvolvedores da Mozilla">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>.
|
||||
|
||||
///
|
||||
|
||||
@@ -143,7 +143,7 @@ Você pode tornar um arquivo opcional usando anotações de tipo padrão e defin
|
||||
|
||||
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] *}
|
||||
{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *}
|
||||
|
||||
## Uploads de Múltiplos Arquivos { #multiple-file-uploads }
|
||||
|
||||
@@ -153,13 +153,13 @@ Eles serão associados ao mesmo "campo de formulário" enviado usando "dados de
|
||||
|
||||
Para usar isso, declare uma lista de `bytes` ou `UploadFile`:
|
||||
|
||||
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
|
||||
{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *}
|
||||
|
||||
Você receberá, tal como declarado, uma `list` de `bytes` ou `UploadFile`.
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
Você pode também pode usar `from starlette.responses import HTMLResponse`.
|
||||
Você também pode usar `from starlette.responses import HTMLResponse`.
|
||||
|
||||
**FastAPI** providencia o mesmo `starlette.responses` que `fastapi.responses` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria das respostas disponíveis vem diretamente do Starlette.
|
||||
|
||||
@@ -169,7 +169,7 @@ Você pode também pode usar `from starlette.responses import HTMLResponse`.
|
||||
|
||||
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] *}
|
||||
{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *}
|
||||
|
||||
## Recapitulando { #recap }
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Isto é suportado desde a versão `0.113.0` do FastAPI. 🤓
|
||||
|
||||
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`:
|
||||
|
||||
{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *}
|
||||
{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *}
|
||||
|
||||
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.
|
||||
|
||||
@@ -42,13 +42,13 @@ Em alguns casos de uso especiais (provavelmente não muito comum), você pode de
|
||||
|
||||
/// note | Nota
|
||||
|
||||
Isso é suportado deste a versão `0.114.0` do FastAPI. 🤓
|
||||
Isso é suportado desde a versão `0.114.0` do FastAPI. 🤓
|
||||
|
||||
///
|
||||
|
||||
Você pode utilizar a configuração de modelo do Pydantic para `proibir` qualquer campo `extra`:
|
||||
|
||||
{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *}
|
||||
{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *}
|
||||
|
||||
Caso um cliente tente enviar informações adicionais, ele receberá um retorno de **erro**.
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ $ pip install python-multipart
|
||||
|
||||
## Importe `File` e `Form` { #import-file-and-form }
|
||||
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## 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_an_py39.py hl[10:12] *}
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.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.
|
||||
|
||||
@@ -30,7 +30,7 @@ E você pode declarar alguns dos arquivos como `bytes` e alguns como `UploadFile
|
||||
|
||||
/// 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`.
|
||||
Você pode declarar vários parâmetros `File` e `Form` em uma *operação de rota*, 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.
|
||||
|
||||
@@ -38,4 +38,4 @@ Isso não é uma limitação do **FastAPI**, é parte do protocolo HTTP.
|
||||
|
||||
## Recapitulando { #recap }
|
||||
|
||||
Usar `File` e `Form` juntos quando precisar receber dados e arquivos na mesma requisição.
|
||||
Use `File` e `Form` juntos quando precisar receber dados e arquivos na mesma requisição.
|
||||
|
||||
@@ -18,17 +18,17 @@ $ pip install python-multipart
|
||||
|
||||
Importe `Form` de `fastapi`:
|
||||
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## 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_an_py39.py hl[9] *}
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py310.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="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.
|
||||
A <dfn title="especificação">especificação</dfn> 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 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.
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ Pode haver casos em que você retorna algo que não é um campo Pydantic válido
|
||||
|
||||
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_py39.py hl[8,10:11] *}
|
||||
{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *}
|
||||
|
||||
Este caso simples é tratado automaticamente pelo FastAPI porque a anotação do tipo de retorno é a classe (ou uma subclasse de) `Response`.
|
||||
|
||||
@@ -193,7 +193,7 @@ E as ferramentas também ficarão felizes porque `RedirectResponse` e `JSO
|
||||
|
||||
Você também pode usar uma subclasse de `Response` na anotação de tipo:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
|
||||
{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *}
|
||||
|
||||
Isso também funcionará porque `RedirectResponse` é uma subclasse de `Response`, e o FastAPI tratará automaticamente este caso simples.
|
||||
|
||||
@@ -201,7 +201,7 @@ Isso também funcionará porque `RedirectResponse` é uma subclasse de `Response
|
||||
|
||||
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á.
|
||||
|
||||
O mesmo aconteceria se você tivesse algo como uma <abbr title='Uma união entre vários tipos significa "qualquer um desses tipos".'>união</abbr> entre tipos diferentes onde um ou mais deles não são tipos Pydantic válidos, por exemplo, isso falharia 💥:
|
||||
O mesmo aconteceria se você tivesse algo como uma <dfn title="uma união entre vários tipos significa 'qualquer um desses tipos'.">união</dfn> entre tipos diferentes onde um ou mais deles não são tipos Pydantic válidos, por exemplo, isso falharia 💥:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}
|
||||
|
||||
@@ -290,7 +290,7 @@ Se os dados tiverem os mesmos valores que os padrões, como o item com ID `baz`:
|
||||
}
|
||||
```
|
||||
|
||||
O FastAPI é inteligente o suficiente (na verdade, o Pydantic é inteligente o suficiente) para perceber que, embora `description`, `tax` e `tags` tenham os mesmos valores que os padrões, eles foram definidos explicitamente (em vez de retirados dos padrões).
|
||||
O FastAPI é inteligente o suficiente (na verdade, o Pydantic é inteligente o suficiente) para perceber que, embora `description`, `tax` e `tags` tenham os mesmos valores que os padrões, eles foram definidos explícita e diretamente (em vez de retirados dos padrões).
|
||||
|
||||
Portanto, eles serão incluídos na resposta JSON.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Da mesma forma que você pode especificar um modelo de resposta, você também p
|
||||
* `@app.delete()`
|
||||
* etc.
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
|
||||
|
||||
/// note | Nota
|
||||
|
||||
@@ -66,7 +66,7 @@ Resumidamente:
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
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>.
|
||||
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>.
|
||||
|
||||
///
|
||||
|
||||
@@ -74,7 +74,7 @@ Para saber mais sobre cada código de status e qual código serve para quê, ver
|
||||
|
||||
Vamos ver o exemplo anterior novamente:
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
|
||||
|
||||
`201` é o código de status para "Criado".
|
||||
|
||||
@@ -82,7 +82,7 @@ Mas você não precisa memorizar o que cada um desses códigos significa.
|
||||
|
||||
Você pode usar as variáveis de conveniência de `fastapi.status`.
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *}
|
||||
|
||||
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:
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ Você também pode, é claro, passar vários `examples`:
|
||||
|
||||
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.
|
||||
No entanto, <dfn title="2023-08-26">no momento em que isto foi escrito</dfn>, 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 }
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Vamos primeiro usar o código e ver como funciona, e depois voltaremos para ente
|
||||
|
||||
Copie o exemplo em um arquivo `main.py`:
|
||||
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py *}
|
||||
|
||||
## Execute-o { #run-it }
|
||||
|
||||
@@ -132,7 +132,7 @@ Nesse caso, o **FastAPI** também fornece as ferramentas para construí-la.
|
||||
|
||||
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.
|
||||
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -156,7 +156,7 @@ Isso ocorre porque ele usa o mesmo nome da especificação do OpenAPI. Assim, se
|
||||
|
||||
///
|
||||
|
||||
A variável `oauth2_scheme` é uma instância de `OAuth2PasswordBearer`, mas também é "chamável" (callable).
|
||||
A variável `oauth2_scheme` é uma instância de `OAuth2PasswordBearer`, mas também é um "callable".
|
||||
|
||||
Ela pode ser chamada como:
|
||||
|
||||
@@ -170,7 +170,7 @@ Então, pode ser usada com `Depends`.
|
||||
|
||||
Agora você pode passar esse `oauth2_scheme` em uma dependência com `Depends`.
|
||||
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
|
||||
|
||||
Essa dependência fornecerá uma `str` que é atribuída ao parâmetro `token` da função de operação de rota.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
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] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
|
||||
|
||||
Mas isso ainda não é tão útil.
|
||||
|
||||
|
||||
@@ -88,7 +88,6 @@ OpenAPI define os seguintes esquemas de segurança:
|
||||
* `openIdConnect`: tem uma forma para definir como descobrir automaticamente o dado da autenticação OAuth2.
|
||||
* Essa descoberta automática é o que é definido na especificação OpenID Connect.
|
||||
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Integração com outros provedores de autenticação/autorização como Google, Facebook, X (Twitter), GitHub, etc. é bem possível e relativamente fácil.
|
||||
@@ -99,7 +98,7 @@ O problema mais complexo é criar um provedor de autenticação/autorização co
|
||||
|
||||
## **FastAPI** utilitários { #fastapi-utilities }
|
||||
|
||||
**FastAPI** fornece várias ferramentas para cada um desses esquemas de segurança no módulo `fastapi.security` que simplesmente usa esses mecanismos de segurança.
|
||||
**FastAPI** fornece várias ferramentas para cada um desses esquemas de segurança no módulo `fastapi.security` que simplificam o uso desses mecanismos de segurança.
|
||||
|
||||
Nos próximos capítulos você irá ver como adicionar segurança à sua API usando essas ferramentas disponibilizadas pelo **FastAPI**.
|
||||
|
||||
|
||||
@@ -116,7 +116,11 @@ E outra função utilitária para verificar se uma senha recebida corresponde ao
|
||||
|
||||
E outra para autenticar e retornar um usuário.
|
||||
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *}
|
||||
|
||||
Quando `authenticate_user` é chamado com um nome de usuário que não existe no banco de dados, ainda executamos `verify_password` contra um hash fictício.
|
||||
|
||||
Isso garante que o endpoint leve aproximadamente o mesmo tempo para responder, seja o nome de usuário válido ou não, prevenindo **timing attacks** que poderiam ser usados para enumerar nomes de usuário existentes.
|
||||
|
||||
/// note | Nota
|
||||
|
||||
@@ -152,7 +156,7 @@ Defina um modelo Pydantic que será usado no endpoint de token para a resposta.
|
||||
|
||||
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] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *}
|
||||
|
||||
## Atualize as dependências { #update-the-dependencies }
|
||||
|
||||
@@ -162,7 +166,7 @@ Decodifique o token recebido, verifique-o e retorne o usuário atual.
|
||||
|
||||
Se o token for inválido, retorne um erro HTTP imediatamente.
|
||||
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *}
|
||||
|
||||
## Atualize a *operação de rota* `/token` { #update-the-token-path-operation }
|
||||
|
||||
@@ -170,7 +174,7 @@ Crie um `timedelta` com o tempo de expiração do token.
|
||||
|
||||
Crie um token de acesso JWT real e o retorne.
|
||||
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *}
|
||||
|
||||
### Detalhes técnicos sobre o "sujeito" `sub` do JWT { #technical-details-about-the-jwt-subject-sub }
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Você pode servir arquivos estáticos automaticamente a partir de um diretório
|
||||
* Importe `StaticFiles`.
|
||||
* "Monte" uma instância de `StaticFiles()` em um path específico.
|
||||
|
||||
{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
|
||||
{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *}
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Use o objeto `TestClient` da mesma forma que você faz com `httpx`.
|
||||
|
||||
Escreva instruções `assert` simples com as expressões Python padrão que você precisa verificar (novamente, `pytest` padrão).
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
|
||||
{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -76,7 +76,7 @@ Digamos que você tenha uma estrutura de arquivo conforme descrito em [Aplicaç
|
||||
No arquivo `main.py` você tem sua aplicação **FastAPI**:
|
||||
|
||||
|
||||
{* ../../docs_src/app_testing/app_a_py39/main.py *}
|
||||
{* ../../docs_src/app_testing/app_a_py310/main.py *}
|
||||
|
||||
### Arquivo de teste { #testing-file }
|
||||
|
||||
@@ -92,7 +92,7 @@ Então você poderia ter um arquivo `test_main.py` com seus testes. Ele poderia
|
||||
|
||||
Como esse arquivo está no mesmo pacote, você pode usar importações relativas para importar o objeto `app` do módulo `main` (`main.py`):
|
||||
|
||||
{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
|
||||
{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *}
|
||||
|
||||
...e ter o código para os testes como antes.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Ambientes Virtuais { #virtual-environments }
|
||||
|
||||
Ao trabalhar em projetos Python, você provavelmente deve usar um **ambiente virtual** (ou um mecanismo similar) para isolar os pacotes que você instala para cada projeto.
|
||||
Ao trabalhar em projetos Python, você provavelmente deveria usar um **ambiente virtual** (ou um mecanismo similar) para isolar os pacotes que você instala para cada projeto.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
@@ -53,7 +53,7 @@ $ cd awesome-project
|
||||
|
||||
## Crie um ambiente virtual { #create-a-virtual-environment }
|
||||
|
||||
Ao começar a trabalhar em um projeto Python **pela primeira vez**, crie um ambiente virtual **<abbr title="existem outras opções, esta é uma diretriz simples">dentro do seu projeto</abbr>**.
|
||||
Ao começar a trabalhar em um projeto Python **pela primeira vez**, crie um ambiente virtual **<dfn title="existem outras opções, esta é uma diretriz simples">dentro do seu projeto</dfn>**.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
@@ -166,7 +166,7 @@ $ source .venv/Scripts/activate
|
||||
|
||||
Toda vez que você instalar um **novo pacote** naquele ambiente, **ative** o ambiente novamente.
|
||||
|
||||
Isso garante que, se você usar um **programa de terminal (<abbr title="Command Line Interface – Interface de Linha de Comando">CLI</abbr>)** instalado por esse pacote, você usará aquele do seu ambiente virtual e não qualquer outro que possa ser instalado globalmente, provavelmente com uma versão diferente do que você precisa.
|
||||
Isso garante que, se você usar um **programa de terminal (<abbr title="command line interface - interface de linha de comando">CLI</abbr>)** instalado por esse pacote, você usará aquele do seu ambiente virtual e não qualquer outro que possa ser instalado globalmente, provavelmente com uma versão diferente do que você precisa.
|
||||
|
||||
///
|
||||
|
||||
@@ -176,7 +176,7 @@ Verifique se o ambiente virtual está ativo (o comando anterior funcionou).
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Isso é **opcional**, mas é uma boa maneira de **verificar** se tudo está funcionando conforme o esperado e se você está usando o ambiente virtual intendido.
|
||||
Isso é **opcional**, mas é uma boa maneira de **verificar** se tudo está funcionando conforme o esperado e se você está usando o ambiente virtual pretendido.
|
||||
|
||||
///
|
||||
|
||||
@@ -220,7 +220,7 @@ Se você usar <a href="https://github.com/astral-sh/uv" class="external-link" ta
|
||||
|
||||
///
|
||||
|
||||
Se você estiver usando `pip` para instalar pacotes (ele vem por padrão com o Python), você deve **atualizá-lo** para a versão mais recente.
|
||||
Se você estiver usando `pip` para instalar pacotes (ele vem por padrão com o Python), você deveria **atualizá-lo** para a versão mais recente.
|
||||
|
||||
Muitos erros exóticos durante a instalação de um pacote são resolvidos apenas atualizando o `pip` primeiro.
|
||||
|
||||
@@ -835,7 +835,7 @@ $ source .venv/bin/activate
|
||||
// Agora, quando você executar o python, ele encontrará o pacote sirius instalado neste ambiente virtual ✨
|
||||
$ python main.py
|
||||
|
||||
Eu juro solenemente 🐺
|
||||
I solemnly swear 🐺
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user