committed by
GitHub
8 changed files with 289 additions and 17 deletions
@ -62,7 +62,10 @@ jobs: |
|||||
env: |
env: |
||||
PROJECT_NAME: fastapitiangolo |
PROJECT_NAME: fastapitiangolo |
||||
BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }} |
BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }} |
||||
uses: cloudflare/wrangler-action@v3 |
# TODO: Use v3 when it's fixed, probably in v3.11 |
||||
|
# https://github.com/cloudflare/wrangler-action/issues/307 |
||||
|
uses: cloudflare/[email protected] |
||||
|
# uses: cloudflare/wrangler-action@v3 |
||||
with: |
with: |
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} |
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} |
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} |
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} |
||||
|
@ -0,0 +1,258 @@ |
|||||
|
# Esquemas OpenAPI Separados para Entrada e Saída ou Não |
||||
|
|
||||
|
Ao usar **Pydantic v2**, o OpenAPI gerado é um pouco mais exato e **correto** do que antes. 😎 |
||||
|
|
||||
|
Inclusive, em alguns casos, ele terá até **dois JSON Schemas** no OpenAPI para o mesmo modelo Pydantic, para entrada e saída, dependendo se eles possuem **valores padrão**. |
||||
|
|
||||
|
Vamos ver como isso funciona e como alterar se for necessário. |
||||
|
|
||||
|
## Modelos Pydantic para Entrada e Saída |
||||
|
|
||||
|
Digamos que você tenha um modelo Pydantic com valores padrão, como este: |
||||
|
|
||||
|
//// tab | Python 3.10+ |
||||
|
|
||||
|
```Python hl_lines="7" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-7]!} |
||||
|
|
||||
|
# Code below omitted 👇 |
||||
|
``` |
||||
|
|
||||
|
<details> |
||||
|
<summary>👀 Visualização completa do arquivo</summary> |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!} |
||||
|
``` |
||||
|
|
||||
|
</details> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.9+ |
||||
|
|
||||
|
```Python hl_lines="9" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-9]!} |
||||
|
|
||||
|
# Code below omitted 👇 |
||||
|
``` |
||||
|
|
||||
|
<details> |
||||
|
<summary>👀 Visualização completa do arquivo</summary> |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!} |
||||
|
``` |
||||
|
|
||||
|
</details> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ |
||||
|
|
||||
|
```Python hl_lines="9" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-9]!} |
||||
|
|
||||
|
# Code below omitted 👇 |
||||
|
``` |
||||
|
|
||||
|
<details> |
||||
|
<summary>👀 Visualização completa do arquivo</summary> |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
</details> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
### Modelo para Entrada |
||||
|
|
||||
|
Se você usar esse modelo como entrada, como aqui: |
||||
|
|
||||
|
//// tab | Python 3.10+ |
||||
|
|
||||
|
```Python hl_lines="14" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-15]!} |
||||
|
|
||||
|
# Code below omitted 👇 |
||||
|
``` |
||||
|
|
||||
|
<details> |
||||
|
<summary>👀 Visualização completa do arquivo</summary> |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!} |
||||
|
``` |
||||
|
|
||||
|
</details> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.9+ |
||||
|
|
||||
|
```Python hl_lines="16" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-17]!} |
||||
|
|
||||
|
# Code below omitted 👇 |
||||
|
``` |
||||
|
|
||||
|
<details> |
||||
|
<summary>👀 Visualização completa do arquivo</summary> |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!} |
||||
|
``` |
||||
|
|
||||
|
</details> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ |
||||
|
|
||||
|
```Python hl_lines="16" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-17]!} |
||||
|
|
||||
|
# Code below omitted 👇 |
||||
|
``` |
||||
|
|
||||
|
<details> |
||||
|
<summary>👀 Visualização completa do arquivo</summary> |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
</details> |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
... então o campo `description` não será obrigatório. Porque ele tem um valor padrão de `None`. |
||||
|
|
||||
|
### Modelo de Entrada na Documentação |
||||
|
|
||||
|
Você pode confirmar que na documentação, o campo `description` não tem um **asterisco vermelho**, não é marcado como obrigatório: |
||||
|
|
||||
|
<div class="screenshot"> |
||||
|
<img src="/img/tutorial/separate-openapi-schemas/image01.png"> |
||||
|
</div> |
||||
|
|
||||
|
### Modelo para Saída |
||||
|
|
||||
|
Mas se você usar o mesmo modelo como saída, como aqui: |
||||
|
|
||||
|
//// tab | Python 3.10+ |
||||
|
|
||||
|
```Python hl_lines="19" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.9+ |
||||
|
|
||||
|
```Python hl_lines="21" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ |
||||
|
|
||||
|
```Python hl_lines="21" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
... então, como `description` tem um valor padrão, se você **não retornar nada** para esse campo, ele ainda terá o **valor padrão**. |
||||
|
|
||||
|
### Modelo para Dados de Resposta de Saída |
||||
|
|
||||
|
Se você interagir com a documentação e verificar a resposta, mesmo que o código não tenha adicionado nada em um dos campos `description`, a resposta JSON contém o valor padrão (`null`): |
||||
|
|
||||
|
<div class="screenshot"> |
||||
|
<img src="/img/tutorial/separate-openapi-schemas/image02.png"> |
||||
|
</div> |
||||
|
|
||||
|
Isso significa que ele **sempre terá um valor**, só que às vezes o valor pode ser `None` (ou `null` em termos de JSON). |
||||
|
|
||||
|
Isso quer dizer que, os clientes que usam sua API não precisam verificar se o valor existe ou não, eles podem **assumir que o campo sempre estará lá**, mas que em alguns casos terá o valor padrão de `None`. |
||||
|
|
||||
|
A maneira de descrever isso no OpenAPI é marcar esse campo como **obrigatório**, porque ele sempre estará lá. |
||||
|
|
||||
|
Por causa disso, o JSON Schema para um modelo pode ser diferente dependendo se ele é usado para **entrada ou saída**: |
||||
|
|
||||
|
* para **entrada**, o `description` **não será obrigatório** |
||||
|
* para **saída**, ele será **obrigatório** (e possivelmente `None`, ou em termos de JSON, `null`) |
||||
|
|
||||
|
### Modelo para Saída na Documentação |
||||
|
|
||||
|
Você pode verificar o modelo de saída na documentação também, ambos `name` e `description` são marcados como **obrigatórios** com um **asterisco vermelho**: |
||||
|
|
||||
|
<div class="screenshot"> |
||||
|
<img src="/img/tutorial/separate-openapi-schemas/image03.png"> |
||||
|
</div> |
||||
|
|
||||
|
### Modelo para Entrada e Saída na Documentação |
||||
|
|
||||
|
E se você verificar todos os Schemas disponíveis (JSON Schemas) no OpenAPI, verá que há dois, um `Item-Input` e um `Item-Output`. |
||||
|
|
||||
|
Para `Item-Input`, `description` **não é obrigatório**, não tem um asterisco vermelho. |
||||
|
|
||||
|
Mas para `Item-Output`, `description` **é obrigatório**, tem um asterisco vermelho. |
||||
|
|
||||
|
<div class="screenshot"> |
||||
|
<img src="/img/tutorial/separate-openapi-schemas/image04.png"> |
||||
|
</div> |
||||
|
|
||||
|
Com esse recurso do **Pydantic v2**, sua documentação da API fica mais **precisa**, e se você tiver clientes e SDKs gerados automaticamente, eles serão mais precisos também, proporcionando uma melhor **experiência para desenvolvedores** e consistência. 🎉 |
||||
|
|
||||
|
## Não Separe Schemas |
||||
|
|
||||
|
Agora, há alguns casos em que você pode querer ter o **mesmo esquema para entrada e saída**. |
||||
|
|
||||
|
Provavelmente, o principal caso de uso para isso é se você já tem algum código de cliente/SDK gerado automaticamente e não quer atualizar todo o código de cliente/SDK gerado ainda, você provavelmente vai querer fazer isso em algum momento, mas talvez não agora. |
||||
|
|
||||
|
Nesse caso, você pode desativar esse recurso no **FastAPI**, com o parâmetro `separate_input_output_schemas=False`. |
||||
|
|
||||
|
/// info | Informação |
||||
|
|
||||
|
O suporte para `separate_input_output_schemas` foi adicionado no FastAPI `0.102.0`. 🤓 |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
//// tab | Python 3.10+ |
||||
|
|
||||
|
```Python hl_lines="10" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial002_py310.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.9+ |
||||
|
|
||||
|
```Python hl_lines="12" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial002_py39.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ |
||||
|
|
||||
|
```Python hl_lines="12" |
||||
|
{!> ../../docs_src/separate_openapi_schemas/tutorial002.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
### Mesmo Esquema para Modelos de Entrada e Saída na Documentação |
||||
|
|
||||
|
E agora haverá um único esquema para entrada e saída para o modelo, apenas `Item`, e `description` **não será obrigatório**: |
||||
|
|
||||
|
<div class="screenshot"> |
||||
|
<img src="/img/tutorial/separate-openapi-schemas/image05.png"> |
||||
|
</div> |
||||
|
|
||||
|
Esse é o mesmo comportamento do Pydantic v1. 🤓 |
@ -1,13 +1,13 @@ |
|||||
# 使用指南 - 範例集 |
# 使用指南 - 範例集 |
||||
|
|
||||
在這裡,你將會看到 **不同主題** 的範例或「如何使用」的指南。 |
在這裡,你將會看到**不同主題**的範例或「如何使用」的指南。 |
||||
|
|
||||
大多數這些想法都是 **獨立** 的,在大多數情況下,你只需要研究那些直接適用於 **你的專案** 的東西。 |
大多數這些想法都是**獨立**的,在大多數情況下,你只需要研究那些直接適用於**你的專案**的東西。 |
||||
|
|
||||
如果有些東西看起來很有趣且對你的專案很有用的話再去讀它,否則你可能可以跳過它們。 |
如果有些東西看起來很有趣且對你的專案很有用的話再去讀它,否則你可能可以跳過它們。 |
||||
|
|
||||
/// tip |
/// tip |
||||
|
|
||||
如果你想要以結構化的方式 **學習 FastAPI**(推薦),請前往[教學 - 使用者指南](../tutorial/index.md){.internal-link target=_blank}逐章閱讀。 |
如果你想要以結構化的方式**學習 FastAPI**(推薦),請前往[教學 - 使用者指南](../tutorial/index.md){.internal-link target=_blank}逐章閱讀。 |
||||
|
|
||||
/// |
/// |
||||
|
Loading…
Reference in new issue