diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml
index 439084434..6a7e6143e 100644
--- a/.github/workflows/issue-manager.yml
+++ b/.github/workflows/issue-manager.yml
@@ -39,5 +39,9 @@ jobs:
"waiting": {
"delay": 2628000,
"message": "As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR."
+ },
+ "invalid": {
+ "delay": 0,
+ "message": "This was marked as invalid and will be closed now. If this is an error, please provide additional details."
}
}
diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml
index e44584cf1..11176bed8 100644
--- a/.github/workflows/label-approved.yml
+++ b/.github/workflows/label-approved.yml
@@ -20,7 +20,9 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- - uses: docker://tiangolo/label-approved:0.0.4
+ - uses: actions/checkout@v4
+ - name: Set up Python
+ uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Setup uv
diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml
index e9aa1093f..daff8e244 100644
--- a/.github/workflows/smokeshow.yml
+++ b/.github/workflows/smokeshow.yml
@@ -21,6 +21,7 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
+ - uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.9'
diff --git a/docs/en/data/members.yml b/docs/en/data/members.yml
index 0069f8c75..a3a6b912d 100644
--- a/docs/en/data/members.yml
+++ b/docs/en/data/members.yml
@@ -11,6 +11,9 @@ members:
- login: svlandeg
avatar_url: https://avatars.githubusercontent.com/u/8796347
url: https://github.com/svlandeg
+- login: YuriiMotov
+ avatar_url: https://avatars.githubusercontent.com/u/109919500
+ url: https://github.com/YuriiMotov
- login: estebanx64
avatar_url: https://avatars.githubusercontent.com/u/10840422
url: https://github.com/estebanx64
diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md
index 30f98970a..ebdf8820c 100644
--- a/docs/en/docs/release-notes.md
+++ b/docs/en/docs/release-notes.md
@@ -7,8 +7,24 @@ hide:
## Latest Changes
+### Translations
+
+* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/deployment/cloud.md`. PR [#12440](https://github.com/fastapi/fastapi/pull/12440) by [@codingjenny](https://github.com/codingjenny).
+* 🌐 Update Portuguese translation for `docs/pt/docs/python-types.md`. PR [#12428](https://github.com/fastapi/fastapi/pull/12428) by [@ceb10n](https://github.com/ceb10n).
+* 🌐 Add Russian translation for `docs/ru/docs/environment-variables.md`. PR [#12436](https://github.com/fastapi/fastapi/pull/12436) by [@wisderfin](https://github.com/wisderfin).
+* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/resources/index.md`. PR [#12443](https://github.com/fastapi/fastapi/pull/12443) by [@codingjenny](https://github.com/codingjenny).
+* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/about/index.md`. PR [#12438](https://github.com/fastapi/fastapi/pull/12438) by [@codingjenny](https://github.com/codingjenny).
+* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/query-param-models.md`. PR [#12414](https://github.com/fastapi/fastapi/pull/12414) by [@ceb10n](https://github.com/ceb10n).
+* 🌐 Remove Portuguese translation for `docs/pt/docs/deployment.md`. PR [#12427](https://github.com/fastapi/fastapi/pull/12427) by [@ceb10n](https://github.com/ceb10n).
+* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-updates.md`. PR [#12381](https://github.com/fastapi/fastapi/pull/12381) by [@andersonrocha0](https://github.com/andersonrocha0).
+* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/response-cookies.md`. PR [#12417](https://github.com/fastapi/fastapi/pull/12417) by [@Paulofalcao2002](https://github.com/Paulofalcao2002).
+
### Internal
+* 👷 Update issue manager workflow . PR [#12457](https://github.com/fastapi/fastapi/pull/12457) by [@alejsdev](https://github.com/alejsdev).
+* 🔧 Update team, include YuriiMotov 🚀. PR [#12453](https://github.com/fastapi/fastapi/pull/12453) by [@tiangolo](https://github.com/tiangolo).
+* 👷 Refactor label-approved, make it an internal script instead of an external GitHub Action. PR [#12280](https://github.com/fastapi/fastapi/pull/12280) by [@tiangolo](https://github.com/tiangolo).
+* 👷 Fix smokeshow, checkout files on CI. PR [#12434](https://github.com/fastapi/fastapi/pull/12434) by [@tiangolo](https://github.com/tiangolo).
* 👷 Use uv in CI. PR [#12281](https://github.com/fastapi/fastapi/pull/12281) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Update httpx requirement from <0.25.0,>=0.23.0 to >=0.23.0,<0.28.0. PR [#11509](https://github.com/fastapi/fastapi/pull/11509) by [@dependabot[bot]](https://github.com/apps/dependabot).
diff --git a/docs/pt/docs/advanced/response-cookies.md b/docs/pt/docs/advanced/response-cookies.md
new file mode 100644
index 000000000..d0821b5b2
--- /dev/null
+++ b/docs/pt/docs/advanced/response-cookies.md
@@ -0,0 +1,55 @@
+# Cookies de Resposta
+
+## Usando um parâmetro `Response`
+
+Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota*.
+
+E então você pode definir cookies nesse objeto de resposta *temporário*.
+
+```Python hl_lines="1 8-9"
+{!../../docs_src/response_cookies/tutorial002.py!}
+```
+
+Em seguida, você pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc).
+
+E se você declarou um `response_model`, ele ainda será usado para filtrar e converter o objeto que você retornou.
+
+**FastAPI** usará essa resposta *temporária* para extrair os cookies (também os cabeçalhos e código de status) e os colocará na resposta final que contém o valor que você retornou, filtrado por qualquer `response_model`.
+
+Você também pode declarar o parâmetro `Response` em dependências e definir cookies (e cabeçalhos) nelas.
+
+## Retornando uma `Response` diretamente
+
+Você também pode criar cookies ao retornar uma `Response` diretamente no seu código.
+
+Para fazer isso, você pode criar uma resposta como descrito em [Retornando uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}.
+
+Então, defina os cookies nela e a retorne:
+
+```Python hl_lines="10-12"
+{!../../docs_src/response_cookies/tutorial001.py!}
+```
+
+/// tip | Dica
+
+Lembre-se de que se você retornar uma resposta diretamente em vez de usar o parâmetro `Response`, FastAPI a retornará diretamente.
+
+Portanto, você terá que garantir que seus dados sejam do tipo correto. E.g. será compatível com JSON se você estiver retornando um `JSONResponse`.
+
+E também que você não esteja enviando nenhum dado que deveria ter sido filtrado por um `response_model`.
+
+///
+
+### Mais informações
+
+/// note | "Detalhes Técnicos"
+
+Você também poderia usar `from starlette.responses import Response` ou `from starlette.responses import JSONResponse`.
+
+**FastAPI** fornece as mesmas `starlette.responses` em `fastapi.responses` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria das respostas disponíveis vem diretamente do Starlette.
+
+E como o `Response` pode ser usado frequentemente para definir cabeçalhos e cookies, o **FastAPI** também o fornece em `fastapi.Response`.
+
+///
+
+Para ver todos os parâmetros e opções disponíveis, verifique a documentação no Starlette.
diff --git a/docs/pt/docs/deployment.md b/docs/pt/docs/deployment.md
deleted file mode 100644
index 6874a2529..000000000
--- a/docs/pt/docs/deployment.md
+++ /dev/null
@@ -1,414 +0,0 @@
-# Implantação
-
-Implantar uma aplicação **FastAPI** é relativamente fácil.
-
-Existem vários modos de realizar o _deploy_ dependendo de seu caso de uso específico e as ferramentas que você utiliza.
-
-Você verá mais sobre alguns modos de fazer o _deploy_ nas próximas seções.
-
-## Versões do FastAPI
-
-**FastAPI** já está sendo utilizado em produção em muitas aplicações e sistemas. E a cobertura de teste é mantida a 100%. Mas seu desenvolvimento continua andando rapidamente.
-
-Novos recursos são adicionados frequentemente, _bugs_ são corrigidos regularmente, e o código está continuamente melhorando.
-
-É por isso que as versões atuais estão ainda no `0.x.x`, isso reflete que cada versão poderia ter potencialmente alterações que podem quebrar. Isso segue as convenções de Versionamento Semântico.
-
-Você pode criar aplicações para produção com **FastAPI** bem agora (e você provavelmente já faça isso por um tempo), você tem que ter certeza de utilizar uma versão que funcione corretamente com o resto do seu código.
-
-### Anote sua versão `fastapi`
-
-A primeira coisa que você deve fazer é "fixar" a versão do **FastAPI** que está utilizando para a última versão específica que você sabe que funciona corretamente para a sua aplicação.
-
-Por exemplo, vamos dizer que você esteja utilizando a versão `0.45.0` no seu _app_.
-
-Se você usa um arquivo `requirements.txt`, dá para especificar a versão assim:
-
-```txt
-fastapi==0.45.0
-```
-
-isso significa que você pode usar exatamente a versão `0.45.0`.
-
-Ou você poderia fixar assim:
-
-```txt
-fastapi>=0.45.0,<0.46.0
-```
-
-o que significa que você pode usar as versões `0.45.0` ou acima, mas menor que `0.46.0`. Por exemplo, a versão `0.45.2` poderia ser aceita.
-
-Se você usa qualquer outra ferramenta para gerenciar suas instalações, como Poetry, Pipenv ou outro, todos terão um modo que você possa usar para definir versões específicas para seus pacotes.
-
-### Versões disponíveis
-
-Você pode ver as versões disponíveis (por exemplo, para verificar qual é a versão atual) nas [Notas de Lançamento](release-notes.md){.internal-link target=_blank}.
-
-### Sobre as versões
-
-Seguindo as convenções do Versionamento Semântico, qualquer versão abaixo de `1.0.0` pode potencialmente adicionar mudanças que quebrem.
-
-FastAPI também segue a convenção que qualquer versão de _"PATCH"_ seja para ajustes de _bugs_ e mudanças que não quebrem a aplicação.
-
-/// tip
-
-O _"PATCH"_ é o último número, por exemplo, em `0.2.3`, a versão do _PATCH_ é `3`.
-
-///
-
-Então, você poderia ser capaz de fixar para uma versão como:
-
-```txt
-fastapi>=0.45.0,<0.46.0
-```
-
-Mudanças que quebram e novos recursos são adicionados em versões _"MINOR"_.
-
-/// tip
-
-O _"MINOR"_ é o número do meio, por exemplo, em `0.2.3`, a versão _MINOR_ é `2`.
-
-///
-
-### Atualizando as versões FastAPI
-
-Você pode adicionar testes em sua aplicação.
-
-Com o **FastAPI** é muito fácil (graças ao Starlette), verifique a documentação: [Testando](tutorial/testing.md){.internal-link target=_blank}
-
-Após você ter os testes, então você pode fazer o _upgrade_ da versão **FastAPI** para uma mais recente, e ter certeza que todo seu código esteja funcionando corretamente rodando seus testes.
-
-Se tudo estiver funcionando, ou após você fazer as alterações necessárias, e todos seus testes estiverem passando, então você poderá fixar o `fastapi` para a versão mais recente.
-
-### Sobre Starlette
-
-Você não deve fixar a versão do `starlette`.
-
-Versões diferentes do **FastAPI** irão utilizar uma versão mais nova específica do Starlette.
-
-Então, você pode deixar que o **FastAPI** use a versão correta do Starlette.
-
-### Sobre Pydantic
-
-Pydantic inclui os testes para **FastAPI** em seus próprios testes, então novas versões do Pydantic (acima de `1.0.0`) são sempre compatíveis com FastAPI.
-
-Você pode fixar o Pydantic para qualquer versão acima de `1.0.0` e abaixo de `2.0.0` que funcionará.
-
-Por exemplo:
-
-```txt
-pydantic>=1.2.0,<2.0.0
-```
-
-## Docker
-
-Nessa seção você verá instruções e _links_ para guias de saber como:
-
-* Fazer uma imagem/container da sua aplicação **FastAPI** com máxima performance. Em aproximadamente **5 min**.
-* (Opcionalmente) entender o que você, como desenvolvedor, precisa saber sobre HTTPS.
-* Inicializar um _cluster_ Docker Swarm Mode com HTTPS automático, mesmo em um simples servidor de $5 dólares/mês. Em aproximadamente **20 min**.
-* Gere e implante uma aplicação **FastAPI** completa, usando seu _cluster_ Docker Swarm, com HTTPS etc. Em aproxiamadamente **10 min**.
-
-Você pode usar **Docker** para implantação. Ele tem várias vantagens como segurança, replicabilidade, desenvolvimento simplificado etc.
-
-Se você está usando Docker, você pode utilizar a imagem Docker oficial:
-
-### tiangolo/uvicorn-gunicorn-fastapi
-
-Essa imagem tem um mecanismo incluído de "auto-ajuste", para que você possa apenas adicionar seu código e ter uma alta performance automaticamente. E sem fazer sacrifícios.
-
-Mas você pode ainda mudar e atualizar todas as configurações com variáveis de ambiente ou arquivos de configuração.
-
-/// tip
-
-Para ver todas as configurações e opções, vá para a página da imagem do Docker: tiangolo/uvicorn-gunicorn-fastapi.
-
-///
-
-### Crie um `Dockerfile`
-
-* Vá para o diretório de seu projeto.
-* Crie um `Dockerfile` com:
-
-```Dockerfile
-FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
-
-COPY ./app /app
-```
-
-#### Grandes aplicações
-
-Se você seguiu a seção sobre criação de [Grandes Aplicações com Múltiplos Arquivos](tutorial/bigger-applications.md){.internal-link target=_blank}, seu `Dockerfile` poderia parecer como:
-
-```Dockerfile
-FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
-
-COPY ./app /app/app
-```
-
-#### Raspberry Pi e outras arquiteturas
-
-Se você estiver rodando Docker em um Raspberry Pi (que possui um processador ARM) ou qualquer outra arquitetura, você pode criar um `Dockerfile` do zero, baseado em uma imagem base Python (que é multi-arquitetural) e utilizar Uvicorn sozinho.
-
-Nesse caso, seu `Dockerfile` poderia parecer assim:
-
-```Dockerfile
-FROM python:3.7
-
-RUN pip install fastapi uvicorn
-
-EXPOSE 80
-
-COPY ./app /app
-
-CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
-```
-
-### Crie o código **FastAPI**
-
-* Crie um diretório `app` e entre nele.
-* Crie um arquivo `main.py` com:
-
-```Python
-from fastapi import FastAPI
-
-app = FastAPI()
-
-
-@app.get("/")
-def read_root():
- return {"Hello": "World"}
-
-
-@app.get("/items/{item_id}")
-def read_item(item_id: int, q: str = None):
- return {"item_id": item_id, "q": q}
-```
-
-* Você deve ter uma estrutura de diretórios assim:
-
-```
-.
-├── app
-│ └── main.py
-└── Dockerfile
-```
-
-### Construa a imagem Docker
-
-* Vá para o diretório do projeto (onde seu `Dockerfile` está, contendo seu diretório `app`.
-* Construa sua imagem FastAPI:
-
-
-
-```console
-$ docker build -t myimage .
-
----> 100%
-```
-
-
-
-### Inicie o container Docker
-
-* Rode um container baseado em sua imagem:
-
-
-
-```console
-$ docker run -d --name mycontainer -p 80:80 myimage
-```
-
-
-
-Agora você tem um servidor FastAPI otimizado em um container Docker. Auto-ajustado para seu servidor atual (e número de núcleos de CPU).
-
-### Verifique
-
-Você deve ser capaz de verificar na URL de seu container Docker, por exemplo: http://192.168.99.100/items/5?q=somequery ou http://127.0.0.1/items/5?q=somequery (ou equivalente, usando seu _host_ Docker).
-
-Você verá algo como:
-
-```JSON
-{"item_id": 5, "q": "somequery"}
-```
-
-### API interativa de documetação
-
-Agora você pode ir para http://192.168.99.100/docs ou http://127.0.0.1/docs (ou equivalente, usando seu _host_ Docker).
-
-Você verá a API interativa de documentação (fornecida por Swagger UI):
-
-
-
-### APIs alternativas de documentação
-
-E você pode também ir para http://192.168.99.100/redoc ou http://127.0.0.1/redoc (ou equivalente, usando seu _host_ Docker).
-
-Você verá a documentação automática alternativa (fornecida por ReDoc):
-
-
-
-## HTTPS
-
-### Sobre HTTPS
-
-É fácil assumir que HTTPS seja algo que esteja apenas "habilitado" ou não.
-
-Mas ele é um pouquinho mais complexo do que isso.
-
-/// tip
-
-Se você está com pressa ou não se importa, continue na próxima seção com instruções passo a passo para configurar tudo.
-
-///
-
-Para aprender o básico de HTTPS, pela perspectiva de um consumidor, verifique https://howhttps.works/.
-
-Agora, pela perspectiva de um desenvolvedor, aqui estão algumas coisas para se ter em mente enquanto se pensa sobre HTTPS:
-
-* Para HTTPS, o servidor precisa ter "certificados" gerados por terceiros.
- * Esses certificados são na verdade adquiridos por terceiros, não "gerados".
-* Certificados tem um prazo de uso.
- * Eles expiram.
- * E então eles precisam ser renovados, adquiridos novamente por terceiros.
-* A encriptação da conexão acontece no nível TCP.
- * TCP é uma camada abaixo do HTTP.
- * Então, o controle de certificado e encriptação é feito antes do HTTP.
-* TCP não conhece nada sobre "domínios". Somente sobre endereços IP.
- * A informação sobre o domínio requisitado vai nos dados HTTP.
-* Os certificados HTTPS "certificam" um certo domínio, mas o protocolo e a encriptação acontecem no nível TCP, antes de saber qual domínio está sendo lidado.
-* Por padrão, isso significa que você pode ter somente um certificado HTTPS por endereço IP.
- * Não importa quão grande é seu servidor ou quão pequena cada aplicação que você tenha possar ser.
- * No entanto, existe uma solução para isso.
-* Existe uma extensão para o protocolo TLS (o que controla a encriptação no nível TCP, antes do HTTP) chamada SNI.
- * Essa extensão SNI permite um único servidor (com um único endereço IP) a ter vários certificados HTTPS e servir múltiplas aplicações/domínios HTTPS.
- * Para que isso funcione, um único componente (programa) rodando no servidor, ouvindo no endereço IP público, deve ter todos os certificados HTTPS no servidor.
-* Após obter uma conexão segura, o protocolo de comunicação ainda é HTTP.
- * O conteúdo está encriptado, mesmo embora ele esteja sendo enviado com o protocolo HTTP.
-
-É uma prática comum ter um servidor HTTP/programa rodando no servidor (a máquina, _host_ etc.) e gerenciar todas as partes HTTP: enviar as requisições HTTP decriptadas para a aplicação HTTP rodando no mesmo servidor (a aplicação **FastAPI**, nesse caso), pega a resposta HTTP da aplicação, encripta utilizando o certificado apropriado e enviando de volta para o cliente usando HTTPS. Esse servidor é frequentemente chamado TLS _Termination Proxy_.
-
-### Vamos encriptar
-
-Antes de encriptar, esses certificados HTTPS foram vendidos por terceiros de confiança.
-
-O processo para adquirir um desses certificados costumava ser chato, exigia muita papelada e eram bem caros.
-
-Mas então _Let's Encrypt_ foi criado.
-
-É um projeto da Fundação Linux.Ele fornece certificados HTTPS de graça. De um jeito automatizado. Esses certificados utilizam todos os padrões de segurança criptográfica, e tem vida curta (cerca de 3 meses), para que a segurança seja melhor devido ao seu curto período de vida.
-
-Os domínios são seguramente verificados e os certificados são gerados automaticamente. Isso também permite automatizar a renovação desses certificados.
-
-A idéia é automatizar a aquisição e renovação desses certificados, para que você possa ter um HTTPS seguro, grátis, para sempre.
-
-### Traefik
-
-Traefik é um _proxy_ reverso / _load balancer_ de alta performance. Ele pode fazer o trabalho do _"TLS Termination Proxy"_ (à parte de outros recursos).
-
-Ele tem integração com _Let's Encrypt_. Assim, ele pode controlar todas as partes HTTPS, incluindo a aquisição e renovação de certificados.
-
-Ele também tem integrações com Docker. Assim, você pode declarar seus domínios em cada configuração de aplicação e leitura dessas configurações, gerando os certificados HTTPS e servindo o HTTPS para sua aplicação automaticamente, sem exigir qualquer mudança em sua configuração.
-
----
-
-Com essas ferramentas e informações, continue com a próxima seção para combinar tudo.
-
-## _Cluster_ de Docker Swarm Mode com Traefik e HTTPS
-
-Você pode ter um _cluster_ de Docker Swarm Mode configurado em minutos (cerca de 20) com o Traefik controlando HTTPS (incluindo aquisição e renovação de certificados).
-
-Utilizando o Docker Swarm Mode, você pode iniciar com um _"cluster"_ de apenas uma máquina (que pode até ser um servidor por 5 dólares / mês) e então você pode aumentar conforme a necessidade adicionando mais servidores.
-
-Para configurar um _cluster_ Docker Swarm Mode com Traefik controlando HTTPS, siga essa orientação:
-
-### Docker Swarm Mode and Traefik for an HTTPS cluster
-
-### Faça o _deploy_ de uma aplicação FastAPI
-
-O jeito mais fácil de configurar tudo pode ser utilizando o [Gerador de Projetos **FastAPI**](project-generation.md){.internal-link target=_blank}.
-
-Ele é designado para ser integrado com esse _cluster_ Docker Swarm com Traefik e HTTPS descrito acima.
-
-Você pode gerar um projeto em cerca de 2 minutos.
-
-O projeto gerado tem instruções para fazer o _deploy_, fazendo isso leva outros 2 minutos.
-
-## Alternativamente, faça o _deploy_ **FastAPI** sem Docker
-
-Você pode fazer o _deploy_ do **FastAPI** diretamente sem o Docker também.
-
-Você apenas precisa instalar um servidor ASGI compatível como:
-
-//// tab | Uvicorn
-
-* Uvicorn, um servidor ASGI peso leve, construído sobre uvloop e httptools.
-
-
-
-```console
-$ pip install "uvicorn[standard]"
-
----> 100%
-```
-
-
-
-////
-
-//// tab | Hypercorn
-
-* Hypercorn, um servidor ASGI também compatível com HTTP/2.
-
-
-
-```console
-$ pip install hypercorn
-
----> 100%
-```
-
-
-
-...ou qualquer outro servidor ASGI.
-
-////
-
-E rode sua applicação do mesmo modo que você tem feito nos tutoriais, mas sem a opção `--reload`, por exemplo:
-
-//// tab | Uvicorn
-
-
-
-```console
-$ uvicorn main:app --host 0.0.0.0 --port 80
-
-INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
-```
-
-
-
-////
-
-//// tab | Hypercorn
-
-
-
-```console
-$ hypercorn main:app --bind 0.0.0.0:80
-
-Running on 0.0.0.0:8080 over http (CTRL + C to quit)
-```
-
-
-
-////
-
-Você deve querer configurar mais algumas ferramentas para ter certeza que ele seja reinicializado automaticamante se ele parar.
-
-Você também deve querer instalar Gunicorn e utilizar ele como um gerenciador para o Uvicorn, ou usar Hypercorn com múltiplos _workers_.
-
-Tenha certeza de ajustar o número de _workers_ etc.
-
-Mas se você estiver fazendo tudo isso, você pode apenas usar uma imagem Docker que fará isso automaticamente.
diff --git a/docs/pt/docs/python-types.md b/docs/pt/docs/python-types.md
index 05faa860c..a0938259f 100644
--- a/docs/pt/docs/python-types.md
+++ b/docs/pt/docs/python-types.md
@@ -1,18 +1,18 @@
# Introdução aos tipos Python
-**Python 3.6 +** tem suporte para "type hints" opcionais.
+O Python possui suporte para "dicas de tipo" ou "type hints" (também chamado de "anotações de tipo" ou "type annotations")
-Esses **"type hints"** são uma nova sintaxe (desde Python 3.6+) que permite declarar o tipo de uma variável.
+Esses **"type hints"** são uma sintaxe especial que permite declarar o tipo 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 Python. Ele cobre apenas o mínimo necessário para usá-los com o **FastAPI** ... que é realmente muito pouco.
+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.
Mas mesmo que você nunca use o **FastAPI**, você se beneficiaria de aprender um pouco sobre eles.
-/// note | "Nota"
+/// note | Nota
Se você é um especialista em Python e já sabe tudo sobre type hints, pule para o próximo capítulo.
@@ -35,8 +35,8 @@ John Doe
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 ()`.
-* Concatena com um espaço no meio.
+* Converte a primeira letra de cada uma em maiúsculas com `title()`.
+* Concatena com um espaço no meio.
```Python hl_lines="2"
{!../../docs_src/python_types/tutorial001.py!}
@@ -48,7 +48,7 @@ A função faz o seguinte:
Mas agora imagine que você estava escrevendo do zero.
-Em algum momento você teria iniciado a definição da função, já tinha os parâmetros prontos ...
+Em algum momento você teria iniciado a definição da função, já tinha os parâmetros prontos...
Mas então você deve chamar "esse método que converte a primeira letra em maiúscula".
@@ -96,37 +96,37 @@ Isso não é o mesmo que declarar valores padrão como seria com:
Estamos usando dois pontos (`:`), não é igual a (`=`).
-E adicionar type hints normalmente não muda o que acontece do que aconteceria sem elas.
+E adicionar type hints normalmente não muda o que acontece do que aconteceria sem eles.
Mas agora, imagine que você está novamente no meio da criação dessa função, mas com type hints.
-No mesmo ponto, você tenta acionar o preenchimento automático com o `Ctrl Space` e vê:
+No mesmo ponto, você tenta acionar o preenchimento automático com o `Ctrl+Space` e vê:
-Com isso, você pode rolar, vendo as opções, até encontrar o que "toca uma campainha":
+Com isso, você pode rolar, vendo as opções, até encontrar o que "soa familiar":
## Mais motivação
-Marque esta função, ela já possui type hints:
+Verifique esta função, ela já possui type hints:
```Python hl_lines="1"
{!../../docs_src/python_types/tutorial003.py!}
```
-Como o editor conhece os tipos de variáveis, você não apenas obtém a conclusão, mas também as verificações de erro:
+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:
-Agora você sabe que precisa corrigí-lo, converta `age` em uma string com `str (age)`:
+Agora você sabe que precisa corrigí-lo, converta `age` em uma string com `str(age)`:
```Python hl_lines="2"
{!../../docs_src/python_types/tutorial004.py!}
```
-## Tipos de declaração
+## Declarando Tipos
Você acabou de ver o local principal para declarar type hints. Como parâmetros de função.
@@ -151,39 +151,77 @@ Você pode usar, por exemplo:
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 declarar esses tipos e os tipos internos, você pode usar o módulo Python padrão `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.
-Ele existe especificamente para suportar esses type hints.
+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.
-#### `List`
+#### Versões mais recentes do Python
-Por exemplo, vamos definir uma variável para ser uma `lista` de `str`.
+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.
-Em `typing`, importe `List` (com um `L` maiúsculo):
+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.
+
+Se você pode escolher uma versão mais recente do Python para o seu projeto, você poderá aproveitar isso ao seu favor.
+
+Em todos os documentos existem exemplos compatíveis com cada versão do Python (quando existem diferenças).
+
+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
+
+Por exemplo, vamos definir uma variável para ser uma `list` de `str`.
+
+//// tab | Python 3.9+
+
+Declare uma variável com a mesma sintaxe com dois pontos (`:`)
+
+Como tipo, coloque `list`.
+
+Como a lista é o tipo que contém algum tipo interno, você coloca o tipo dentro de colchetes:
```Python hl_lines="1"
-{!../../docs_src/python_types/tutorial006.py!}
+{!> ../../docs_src/python_types/tutorial006_py39.py!}
```
-Declare a variável com a mesma sintaxe de dois pontos (`:`).
+////
-Como o tipo, coloque a `List`.
+//// tab | Python 3.8+
-Como a lista é um tipo que contém alguns tipos internos, você os coloca entre colchetes:
+De `typing`, importe `List` (com o `L` maiúsculo):
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial006.py!}
+```
+
+Declare uma variável com a mesma sintaxe com dois pontos (`:`)
+
+Como tipo, coloque o `List` que você importou de `typing`.
+
+Como a lista é o tipo que contém algum tipo interno, você coloca o tipo dentro de colchetes:
```Python hl_lines="4"
-{!../../docs_src/python_types/tutorial006.py!}
+{!> ../../docs_src/python_types/tutorial006.py!}
```
-/// tip | "Dica"
+////
+
+/// info | Informação
-Esses tipos internos entre colchetes são chamados de "parâmetros de tipo".
+Estes tipos internos dentro dos colchetes são chamados "parâmetros de tipo" (type parameters).
-Nesse caso, `str` é o parâmetro de tipo passado para `List`.
+Neste caso, `str` é o parâmetro de tipo passado para `List` (ou `list` no Python 3.9 ou superior).
///
-Isso significa que: "a variável `items` é uma `list`, e cada um dos itens desta lista é uma `str`".
+Isso significa: "a variável `items` é uma `list`, e cada um dos itens desta lista é uma `str`".
+
+/// tip | Dica
+
+Se você usa o Python 3.9 ou superior, você não precisa importar `List` de `typing`. Você pode utilizar o mesmo tipo `list` no lugar.
+
+///
Ao fazer isso, seu editor pode fornecer suporte mesmo durante o processamento de itens da lista:
@@ -195,20 +233,32 @@ Observe que a variável `item` é um dos elementos da lista `items`.
E, ainda assim, o editor sabe que é um `str` e fornece suporte para isso.
-#### `Tuple` e `Set`
+#### Tuple e Set
Você faria o mesmo para declarar `tuple`s e `set`s:
-```Python hl_lines="1 4"
-{!../../docs_src/python_types/tutorial007.py!}
+//// tab | Python 3.9+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial007_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial007.py!}
```
+////
+
Isso significa que:
* 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`.
-#### `Dict`
+#### Dict
Para definir um `dict`, você passa 2 parâmetros de tipo, separados por vírgulas.
@@ -216,38 +266,185 @@ O primeiro parâmetro de tipo é para as chaves do `dict`.
O segundo parâmetro de tipo é para os valores do `dict`:
-```Python hl_lines="1 4"
-{!../../docs_src/python_types/tutorial008.py!}
+//// tab | Python 3.9+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial008_py39.py!}
```
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial008.py!}
+```
+
+////
+
Isso significa que:
* A variável `prices` é um dict`:
* As chaves deste `dict` são do tipo `str` (digamos, o nome de cada item).
* Os valores deste `dict` são do tipo `float` (digamos, o preço de cada item).
-#### `Opcional`
+#### Union
-Você também pode usar o `Opcional` para declarar que uma variável tem um tipo, como `str`, mas que é "opcional", o que significa que também pode ser `None`:
+Você pode declarar que uma variável pode ser de qualquer um dentre **diversos 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.
+
+No Python 3.10 também existe uma **nova sintaxe** onde você pode colocar os possívels tipos separados por uma barra vertical (`|`).
+
+//// tab | Python 3.10+
+
+```Python hl_lines="1"
+{!> ../../docs_src/python_types/tutorial008b_py310.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial008b.py!}
+```
+
+////
+
+Em ambos os casos, isso significa que `item` poderia ser um `int` ou um `str`.
+
+
+#### Possívelmente `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.py!}
```
-O uso de `Opcional [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`.
+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"
+{!> ../../docs_src/python_types/tutorial009_py310.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009.py!}
+```
+
+////
+
+//// tab | Python 3.8+ alternative
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial009b.py!}
+```
+
+////
+
+#### Utilizando `Union` ou `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:
+
+```Python hl_lines="1 4"
+{!../../docs_src/python_types/tutorial009c.py!}
+```
+
+O paâ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 *opicional*) 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:
+
+```Python hl_lines="1 4"
+{!../../docs_src/python_types/tutorial009c_py310.py!}
+```
+
+E então você não precisará mais se preocupar com nomes como `Optional` e `Union`. 😎
#### Tipos genéricos
-Esses tipos que usam parâmetros de tipo entre colchetes, como:
+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 como no Python 3.8, do módulo `typing`:
+
+* `Union`
+* `Optional` (o mesmo que com o 3.8)
+* ...entro outros.
+
+No Python 3.10, como uma alternativa para a utilização dos genéricos `Union` e `Optional`, você pode usar a barra vertical (`|`) 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 o mesmo como no Python 3.8, do módulo `typing`:
+
+* `Union`
+* `Optional`
+* ...entro outros.
+
+////
+
+//// tab | Python 3.8+
* `List`
* `Tuple`
* `Set`
* `Dict`
-* `Opcional`
-* ...e outros.
+* `Union`
+* `Optional`
+* ...entro outros.
-são chamados **tipos genéricos** ou **genéricos**.
+////
### Classes como tipos
@@ -255,7 +452,7 @@ Você também pode declarar uma classe como o tipo de uma variável.
Digamos que você tenha uma classe `Person`, com um nome:
-```Python hl_lines="1 2 3"
+```Python hl_lines="1-3"
{!../../docs_src/python_types/tutorial010.py!}
```
@@ -269,9 +466,13 @@ E então, novamente, você recebe todo o suporte do editor:
+Perceba que isso significa que "`one_person` é uma **instância** da classe `Person`".
+
+Isso não significa que "`one_person` é a **classe** chamada `Person`".
+
## Modelos Pydantic
- Pydantic é uma biblioteca Python para executar a validação de dados.
+O Pydantic é uma biblioteca Python para executar a validação de dados.
Você declara a "forma" dos dados como classes com atributos.
@@ -283,21 +484,93 @@ E você recebe todo o suporte do editor com esse objeto resultante.
Retirado dos documentos oficiais dos Pydantic:
+//// tab | Python 3.10+
+
```Python
-{!../../docs_src/python_types/tutorial011.py!}
+{!> ../../docs_src/python_types/tutorial011_py310.py!}
```
-/// info | "Informação"
+////
+
+//// tab | Python 3.9+
+
+```Python
+{!> ../../docs_src/python_types/tutorial011_py39.py!}
+```
-Para saber mais sobre o Pydantic, verifique seus documentos .
+////
+
+//// tab | Python 3.8+
+
+```Python
+{!> ../../docs_src/python_types/tutorial011.py!}
+```
+
+////
+
+/// info | Informação
+
+Para saber mais sobre o Pydantic, verifique a sua documentação.
///
-**FastAPI** é todo baseado em Pydantic.
+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}.
-## Type hints em **FastAPI**
+/// 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 campos Opcionais Obrigatórios.
+
+///
+
+
+## Type Hints com Metadados de Anotações
+
+O Python possui uma funcionalidade que nos permite incluir **metadados adicionais** nos type hints utilizando `Annotated`.
+
+//// tab | Python 3.9+
+
+No Python 3.9, `Annotated` é parte da biblioteca padrão, então você pode importá-lo de `typing`.
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial013_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+Em versões abaixo do Python 3.9, você importa `Annotated` de `typing_extensions`.
+
+Ele já estará instalado com o **FastAPI**.
+
+```Python hl_lines="1 4"
+{!> ../../docs_src/python_types/tutorial013.py!}
+```
+
+////
+
+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.
+
+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.
+
+Por hora, você precisa apenas saber que o `Annotated` existe, e que ele é Python padrão. 😎
+
+Mais tarde você verá o quão **poderoso** ele pode ser.
+
+/// tip | Dica
+
+O fato de que isso é **Python padrão** significa que você ainda obtém a **melhor experiência de desenvolvedor possível** no seu editor, com as ferramentas que você utiliza para analisar e refatorar o seu código, etc. ✨
+
+E também que o seu código será muito compatível com diversas outras ferramentas e bibliotecas Python. 🚀
+
+///
+
+
+## Type hints no **FastAPI**
O **FastAPI** aproveita esses type hints para fazer várias coisas.
@@ -306,20 +579,20 @@ Com o **FastAPI**, você declara parâmetros com type hints e obtém:
* **Suporte ao editor**.
* **Verificações de tipo**.
-... e **FastAPI** usa as mesmas declarações para:
+... e o **FastAPI** usa as mesmas declarações para:
-* **Definir requisitos**: dos parâmetros do caminho da solicitação, parâmetros da consulta, cabeçalhos, corpos, dependências, etc.
+* **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:
- * A geração de **erros automáticos** retornou ao cliente quando os dados são inválidos.
-* **Documente** a API usando OpenAPI:
+ * 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.
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}.
O importante é que, usando tipos padrão de Python, em um único local (em vez de adicionar mais classes, decoradores, etc.), o **FastAPI** fará muito trabalho para você.
-/// info | "Informação"
+/// info | Informação
Se você já passou por todo o tutorial e voltou para ver mais sobre os tipos, um bom recurso é a "cheat sheet" do `mypy` .
diff --git a/docs/pt/docs/tutorial/body-updates.md b/docs/pt/docs/tutorial/body-updates.md
new file mode 100644
index 000000000..1a0455c1c
--- /dev/null
+++ b/docs/pt/docs/tutorial/body-updates.md
@@ -0,0 +1,204 @@
+# Corpo - Atualizações
+
+## Atualização de dados existentes com `PUT`
+
+Para atualizar um item, você pode usar a operação HTTP `PUT`.
+
+Você pode usar `jsonable_encoder` para converter os dados de entrada em dados que podem ser armazenados como JSON (por exemplo, com um banco de dados NoSQL). Por exemplo, convertendo `datetime` em `str`.
+
+//// tab | Python 3.10+
+
+```Python hl_lines="28-33"
+{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="30-35"
+{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="30-35"
+{!> ../../../docs_src/body_updates/tutorial001.py!}
+```
+
+////
+
+`PUT` é usado para receber dados que devem substituir os dados existentes.
+
+### Aviso sobre a substituição
+
+Isso significa que, se você quiser atualizar o item `bar` usando `PUT` com um corpo contendo:
+
+```Python
+{
+ "name": "Barz",
+ "price": 3,
+ "description": None,
+}
+```
+
+Como ele não inclui o atributo já armazenado `"tax": 20.2`, o modelo de entrada assumiria o valor padrão de `"tax": 10.5`.
+
+E os dados seriam salvos com esse "novo" `tax` de `10.5`.
+
+## Atualizações parciais com `PATCH`
+
+Você também pode usar a operação HTTP `PATCH` para *atualizar* parcialmente os dados.
+
+Isso significa que você pode enviar apenas os dados que deseja atualizar, deixando o restante intacto.
+
+/// note | Nota
+
+`PATCH` é menos comumente usado e conhecido do que `PUT`.
+
+E muitas equipes usam apenas `PUT`, mesmo para atualizações parciais.
+
+Você é **livre** para usá-los como preferir, **FastAPI** não impõe restrições.
+
+Mas este guia te dá uma ideia de como eles são destinados a serem usados.
+
+///
+
+### Usando o parâmetro `exclude_unset` do Pydantic
+
+Se você quiser receber atualizações parciais, é muito útil usar o parâmetro `exclude_unset` no método `.model_dump()` do modelo do Pydantic.
+
+Como `item.model_dump(exclude_unset=True)`.
+
+/// info | Informação
+
+No Pydantic v1, o método que era chamado `.dict()` e foi depreciado (mas ainda suportado) no Pydantic v2. Agora, deve-se usar o método `.model_dump()`.
+
+Os exemplos aqui usam `.dict()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` a partir do Pydantic v2.
+
+///
+
+Isso gera um `dict` com apenas os dados definidos ao criar o modelo `item`, excluindo os valores padrão.
+
+Então, você pode usar isso para gerar um `dict` com apenas os dados definidos (enviados na solicitação), omitindo valores padrão:
+
+//// tab | Python 3.10+
+
+```Python hl_lines="32"
+{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="34"
+{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="34"
+{!> ../../../docs_src/body_updates/tutorial002.py!}
+```
+
+////
+
+### Usando o parâmetro `update` do Pydantic
+
+Agora, você pode criar uma cópia do modelo existente usando `.model_copy()`, e passar o parâmetro `update` com um `dict` contendo os dados para atualizar.
+
+/// info | Informação
+
+No Pydantic v1, o método era chamado `.copy()`, ele foi depreciado (mas ainda suportado) no Pydantic v2, e renomeado para `.model_copy()`.
+
+Os exemplos aqui usam `.copy()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_copy()` com o Pydantic v2.
+
+///
+
+Como `stored_item_model.model_copy(update=update_data)`:
+
+//// tab | Python 3.10+
+
+```Python hl_lines="33"
+{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="35"
+{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="35"
+{!> ../../../docs_src/body_updates/tutorial002.py!}
+```
+
+////
+
+### Recapitulando as atualizações parciais
+
+Resumindo, para aplicar atualizações parciais você pode:
+
+* (Opcionalmente) usar `PATCH` em vez de `PUT`.
+* Recuperar os dados armazenados.
+* Colocar esses dados em um modelo do Pydantic.
+* Gerar um `dict` sem valores padrão a partir do modelo de entrada (usando `exclude_unset`).
+ * Dessa forma, você pode atualizar apenas os valores definidos pelo usuário, em vez de substituir os valores já armazenados com valores padrão em seu modelo.
+* Criar uma cópia do modelo armazenado, atualizando seus atributos com as atualizações parciais recebidas (usando o parâmetro `update`).
+* Converter o modelo copiado em algo que possa ser armazenado no seu banco de dados (por exemplo, usando o `jsonable_encoder`).
+ * Isso é comparável ao uso do método `.model_dump()`, mas garante (e converte) os valores para tipos de dados que possam ser convertidos em JSON, por exemplo, `datetime` para `str`.
+* Salvar os dados no seu banco de dados.
+* Retornar o modelo atualizado.
+
+//// tab | Python 3.10+
+
+```Python hl_lines="28-35"
+{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="30-37"
+{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="30-37"
+{!> ../../../docs_src/body_updates/tutorial002.py!}
+```
+
+////
+
+/// tip | Dica
+
+Você pode realmente usar essa mesma técnica com uma operação HTTP `PUT`.
+
+Mas o exemplo aqui usa `PATCH` porque foi criado para esses casos de uso.
+
+///
+
+/// note | Nota
+
+Observe que o modelo de entrada ainda é validado.
+
+Portanto, se você quiser receber atualizações parciais que possam omitir todos os atributos, precisará ter um modelo com todos os atributos marcados como opcionais (com valores padrão ou `None`).
+
+Para distinguir os modelos com todos os valores opcionais para **atualizações** e modelos com valores obrigatórios para **criação**, você pode usar as ideias descritas em [Modelos Adicionais](extra-models.md){.internal-link target=_blank}.
+
+///
diff --git a/docs/pt/docs/tutorial/query-param-models.md b/docs/pt/docs/tutorial/query-param-models.md
new file mode 100644
index 000000000..854183fb4
--- /dev/null
+++ b/docs/pt/docs/tutorial/query-param-models.md
@@ -0,0 +1,197 @@
+# Modelos de Parâmetros de Consulta
+
+Se você possui um grupo de **parâmetros de consultas** que são relacionados, você pode criar um **modelo Pydantic** para declará-los.
+
+Isso permitiria que você **reutilizasse o modelo** em **diversos lugares**, e também declarasse validações e metadados de todos os parâmetros de uma única vez. 😎
+
+/// note | Nota
+
+Isso é suportado desde o FastAPI versão `0.115.0`. 🤓
+
+///
+
+## Parâmetros de Consulta com um Modelo Pydantic
+
+Declare os **parâmetros de consulta** que você precisa em um **modelo Pydantic**, e então declare o parâmetro como `Query`:
+
+//// tab | Python 3.10+
+
+```Python hl_lines="9-13 17"
+{!> ../../docs_src/query_param_models/tutorial001_an_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="8-12 16"
+{!> ../../docs_src/query_param_models/tutorial001_an_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="10-14 18"
+{!> ../../docs_src/query_param_models/tutorial001_an.py!}
+```
+
+////
+
+//// tab | Python 3.10+ non-Annotated
+
+/// tip | Dica
+
+Prefira utilizar a versão `Annotated` se possível.
+
+///
+
+```Python hl_lines="9-13 17"
+{!> ../../docs_src/query_param_models/tutorial001_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+ non-Annotated
+
+/// tip | Dica
+
+Prefira utilizar a versão `Annotated` se possível.
+
+///
+
+```Python hl_lines="8-12 16"
+{!> ../../docs_src/query_param_models/tutorial001_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+ non-Annotated
+
+/// tip | Dica
+
+Prefira utilizar a versão `Annotated` se possível.
+
+///
+
+```Python hl_lines="9-13 17"
+{!> ../../docs_src/query_param_models/tutorial001_py310.py!}
+```
+
+////
+
+O **FastAPI** **extrairá** os dados para **cada campo** dos **parâmetros de consulta** presentes na requisição, e fornecerá o modelo Pydantic que você definiu.
+
+
+## Verifique os Documentos
+
+Você pode ver os parâmetros de consulta nos documentos de IU em `/docs`:
+
+
+

+
+
+## Restrinja Parâmetros de Consulta Extras
+
+Em alguns casos especiais (provavelmente não muito comuns), você queira **restrinjir** os parâmetros de consulta que deseja receber.
+
+Você pode usar a configuração do modelo Pydantic para `forbid` (proibir) qualquer campo `extra`:
+
+//// tab | Python 3.10+
+
+```Python hl_lines="10"
+{!> ../../docs_src/query_param_models/tutorial002_an_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+
+
+```Python hl_lines="9"
+{!> ../../docs_src/query_param_models/tutorial002_an_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+
+
+```Python hl_lines="11"
+{!> ../../docs_src/query_param_models/tutorial002_an.py!}
+```
+
+////
+
+//// tab | Python 3.10+ non-Annotated
+
+/// tip | Dica
+
+Prefira utilizar a versão `Annotated` se possível.
+
+///
+
+```Python hl_lines="10"
+{!> ../../docs_src/query_param_models/tutorial002_py310.py!}
+```
+
+////
+
+//// tab | Python 3.9+ non-Annotated
+
+/// tip | Dica
+
+Prefira utilizar a versão `Annotated` se possível.
+
+///
+
+```Python hl_lines="9"
+{!> ../../docs_src/query_param_models/tutorial002_py39.py!}
+```
+
+////
+
+//// tab | Python 3.8+ non-Annotated
+
+/// tip | Dica
+
+Prefira utilizar a versão `Annotated` se possível.
+
+///
+
+```Python hl_lines="11"
+{!> ../../docs_src/query_param_models/tutorial002.py!}
+```
+
+////
+
+Caso um cliente tente enviar alguns dados **extras** nos **parâmetros de consulta**, eles receberão um retorno de **erro**.
+
+Por exemplo, se o cliente tentar enviar um parâmetro de consulta `tool` com o valor `plumbus`, como:
+
+```http
+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:
+
+```json
+{
+ "detail": [
+ {
+ "type": "extra_forbidden",
+ "loc": ["query", "tool"],
+ "msg": "Extra inputs are not permitted",
+ "input": "plumbus"
+ }
+ ]
+}
+```
+
+## Resumo
+
+Você pode utilizar **modelos Pydantic** para declarar **parâmetros de consulta** no **FastAPI**. 😎
+
+/// tip | Dica
+
+Alerta de spoiler: você também pode utilizar modelos Pydantic para declarar cookies e cabeçalhos, mas você irá ler sobre isso mais a frente no tutorial. 🤫
+
+///
diff --git a/docs/ru/docs/environment-variables.md b/docs/ru/docs/environment-variables.md
new file mode 100644
index 000000000..a6c7b0c77
--- /dev/null
+++ b/docs/ru/docs/environment-variables.md
@@ -0,0 +1,297 @@
+# Переменные окружения
+
+/// tip
+
+Если вы уже знаете, что такое «переменные окружения» и как их использовать, можете пропустить это.
+
+///
+
+Переменная окружения (также известная как «**env var**») - это переменная, которая живет **вне** кода Python, в **операционной системе**, и может быть прочитана вашим кодом Python (или другими программами).
+
+Переменные окружения могут быть полезны для работы с **настройками** приложений, как часть **установки** Python и т.д.
+
+## Создание и использование переменных окружения
+
+Можно **создавать** и использовать переменные окружения в **оболочке (терминале)**, не прибегая к помощи Python:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// Вы можете создать переменную окружения MY_NAME с помощью
+$ export MY_NAME="Wade Wilson"
+
+// Затем её можно использовать в других программах, например
+$ echo "Hello $MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// Создайте переменную окружения MY_NAME
+$ $Env:MY_NAME = "Wade Wilson"
+
+// Используйте её с другими программами, например
+$ echo "Hello $Env:MY_NAME"
+
+Hello Wade Wilson
+```
+
+
+
+////
+
+## Чтение переменных окружения в python
+
+Так же существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**.
+
+Например, у вас есть файл `main.py`:
+
+```Python hl_lines="3"
+import os
+
+name = os.getenv("MY_NAME", "World")
+print(f"Hello {name} from Python")
+```
+
+/// tip
+
+Второй аргумент `os.getenv()` - это возвращаемое по умолчанию значение.
+
+Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `«World»` в качестве значения по умолчанию.
+///
+
+Затем можно запустить эту программу на Python:
+
+//// tab | Linux, macOS, Windows Bash
+
+
+
+```console
+// Здесь мы еще не устанавливаем переменную окружения
+$ python main.py
+
+// Поскольку мы не задали переменную окружения, мы получим значение по умолчанию
+
+Hello World from Python
+
+// Но если мы сначала создадим переменную окружения
+$ export MY_NAME="Wade Wilson"
+
+// А затем снова запустим программу
+$ python main.py
+
+// Теперь она прочитает переменную окружения
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+//// tab | Windows PowerShell
+
+
+
+```console
+// Здесь мы еще не устанавливаем переменную окружения
+$ python main.py
+
+// Поскольку мы не задали переменную окружения, мы получим значение по умолчанию
+
+Hello World from Python
+
+// Но если мы сначала создадим переменную окружения
+$ $Env:MY_NAME = "Wade Wilson"
+
+// А затем снова запустим программу
+$ python main.py
+
+// Теперь она может прочитать переменную окружения
+
+Hello Wade Wilson from Python
+```
+
+
+
+////
+
+Поскольку переменные окружения могут быть установлены вне кода, но могут быть прочитаны кодом, и их не нужно хранить (фиксировать в `git`) вместе с остальными файлами, их принято использовать для конфигураций или **настроек**.
+
+Вы также можете создать переменную окружения только для **конкретного вызова программы**, которая будет доступна только для этой программы и только на время ее выполнения.
+
+Для этого создайте её непосредственно перед самой программой, в той же строке:
+
+
+
+```console
+// Создайте переменную окружения MY_NAME в строке для этого вызова программы
+$ MY_NAME="Wade Wilson" python main.py
+
+// Теперь она может прочитать переменную окружения
+
+Hello Wade Wilson from Python
+
+// После этого переменная окружения больше не существует
+$ python main.py
+
+Hello World from Python
+```
+
+
+
+/// tip
+
+Подробнее об этом можно прочитать на сайте The Twelve-Factor App: Config.
+
+///
+
+## Типизация и Валидация
+
+Эти переменные окружения могут работать только с **текстовыми строками**, поскольку они являются внешними по отношению к Python и должны быть совместимы с другими программами и остальной системой (и даже с различными операционными системами, такими как Linux, Windows, macOS).
+
+Это означает, что **любое значение**, считанное в Python из переменной окружения, **будет `str`**, и любое преобразование к другому типу или любая проверка должны быть выполнены в коде.
+
+Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенное руководство пользователя - Настройки и переменные среды](./advanced/settings.md){.internal-link target=_blank}.
+
+## Переменная окружения `PATH`
+
+Существует **специальная** переменная окружения **`PATH`**, которая используется операционными системами (Linux, macOS, Windows) для поиска программ для запуска.
+
+Значение переменной `PATH` - это длинная строка, состоящая из каталогов, разделенных двоеточием `:` в Linux и macOS, и точкой с запятой `;` в Windows.
+
+Например, переменная окружения `PATH` может выглядеть следующим образом:
+
+//// tab | Linux, macOS
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+```
+
+Это означает, что система должна искать программы в каталогах:
+
+* `/usr/local/bin`
+* `/usr/bin`
+* `/bin`
+* `/usr/sbin`
+* `/sbin`
+
+////
+
+//// tab | Windows
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
+```
+
+Это означает, что система должна искать программы в каталогах:
+
+* `C:\Program Files\Python312\Scripts`
+* `C:\Program Files\Python312`
+* `C:\Windows\System32`
+
+////
+
+Когда вы вводите **команду** в терминале, операционная система **ищет** программу в **каждой из тех директорий**, которые перечислены в переменной окружения `PATH`.
+
+Например, когда вы вводите `python` в терминале, операционная система ищет программу под названием `python` в **первой директории** в этом списке.
+
+Если она ее находит, то **использует ее**. В противном случае она продолжает искать в **других каталогах**.
+
+### Установка Python и обновление `PATH`
+
+При установке Python вас могут спросить, нужно ли обновить переменную окружения `PATH`.
+
+//// tab | Linux, macOS
+
+Допустим, вы устанавливаете Python, и он оказывается в каталоге `/opt/custompython/bin`.
+
+Если вы скажете «да», чтобы обновить переменную окружения `PATH`, то программа установки добавит `/opt/custompython/bin` в переменную окружения `PATH`.
+
+Это может выглядеть следующим образом:
+
+```plaintext
+/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
+```
+
+Таким образом, когда вы набираете `python` в терминале, система найдет программу Python в `/opt/custompython/bin` (последний каталог) и использует ее.
+
+////
+
+//// tab | Windows
+
+Допустим, вы устанавливаете Python, и он оказывается в каталоге `C:\opt\custompython\bin`.
+
+Если вы согласитесь обновить переменную окружения `PATH`, то программа установки добавит `C:\opt\custompython\bin` в переменную окружения `PATH`.
+
+```plaintext
+C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
+```
+
+Таким образом, когда вы набираете `python` в терминале, система найдет программу Python в `C:\opt\custompython\bin` (последний каталог) и использует ее.
+
+////
+
+Итак, если вы напечатаете:
+
+
+
+```console
+$ python
+```
+
+
+
+//// tab | Linux, macOS
+
+Система **найдет** программу `python` в `/opt/custompython/bin` и запустит ее.
+
+Это примерно эквивалентно набору текста:
+
+
+
+```console
+$ /opt/custompython/bin/python
+```
+
+
+
+////
+
+//// tab | Windows
+
+Система **найдет** программу `python` в каталоге `C:\opt\custompython\bin\python` и запустит ее.
+
+Это примерно эквивалентно набору текста:
+
+
+
+```console
+$ C:\opt\custompython\bin\python
+```
+
+
+
+////
+
+Эта информация будет полезна при изучении [Виртуальных окружений](virtual-environments.md){.internal-link target=_blank}.
+
+## Вывод
+
+Благодаря этому вы должны иметь базовое представление о том, что такое **переменные окружения** и как использовать их в Python.
+
+Подробнее о них вы также можете прочитать в статье о переменных окружения на википедии.
+
+Во многих случаях не всегда очевидно, как переменные окружения могут быть полезны и применимы. Но они постоянно появляются в различных сценариях разработки, поэтому знать о них полезно.
+
+Например, эта информация понадобится вам в следующем разделе, посвященном [Виртуальным окружениям](virtual-environments.md).
diff --git a/docs/zh-hant/docs/about/index.md b/docs/zh-hant/docs/about/index.md
new file mode 100644
index 000000000..5dcee68f2
--- /dev/null
+++ b/docs/zh-hant/docs/about/index.md
@@ -0,0 +1,3 @@
+# 關於 FastAPI
+
+關於 FastAPI、其設計、靈感來源等更多資訊。 🤓
diff --git a/docs/zh-hant/docs/deployment/cloud.md b/docs/zh-hant/docs/deployment/cloud.md
new file mode 100644
index 000000000..5d645b6c2
--- /dev/null
+++ b/docs/zh-hant/docs/deployment/cloud.md
@@ -0,0 +1,17 @@
+# 在雲端部署 FastAPI
+
+你幾乎可以使用 **任何雲端供應商** 來部署你的 FastAPI 應用程式。
+
+在大多數情況下,主要的雲端供應商都有部署 FastAPI 的指南。
+
+## 雲端供應商 - 贊助商
+
+一些雲端供應商 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨,這確保了 FastAPI 及其 **生態系統** 持續健康地 **發展**。
+
+這也展現了他們對 FastAPI 和其 **社群**(包括你)的真正承諾,他們不僅希望為你提供 **優質的服務**,還希望確保你擁有一個 **良好且健康的框架**:FastAPI。🙇
+
+你可能會想嘗試他們的服務,以下有他們的指南:
+
+* Platform.sh
+* Porter
+* Coherence
diff --git a/docs/zh-hant/docs/resources/index.md b/docs/zh-hant/docs/resources/index.md
new file mode 100644
index 000000000..f4c70a3a0
--- /dev/null
+++ b/docs/zh-hant/docs/resources/index.md
@@ -0,0 +1,3 @@
+# 資源
+
+額外的資源、外部連結、文章等。 ✈️
diff --git a/scripts/label_approved.py b/scripts/label_approved.py
new file mode 100644
index 000000000..271444504
--- /dev/null
+++ b/scripts/label_approved.py
@@ -0,0 +1,60 @@
+import logging
+from typing import Literal
+
+from github import Github
+from github.PullRequestReview import PullRequestReview
+from pydantic import BaseModel, SecretStr
+from pydantic_settings import BaseSettings
+
+
+class LabelSettings(BaseModel):
+ await_label: str | None = None
+ number: int
+
+
+default_config = {"approved-2": LabelSettings(await_label="awaiting-review", number=2)}
+
+
+class Settings(BaseSettings):
+ github_repository: str
+ token: SecretStr
+ debug: bool | None = False
+ config: dict[str, LabelSettings] | Literal[""] = default_config
+
+
+settings = Settings()
+if settings.debug:
+ logging.basicConfig(level=logging.DEBUG)
+else:
+ logging.basicConfig(level=logging.INFO)
+logging.debug(f"Using config: {settings.json()}")
+g = Github(settings.token.get_secret_value())
+repo = g.get_repo(settings.github_repository)
+for pr in repo.get_pulls(state="open"):
+ logging.info(f"Checking PR: #{pr.number}")
+ pr_labels = list(pr.get_labels())
+ pr_label_by_name = {label.name: label for label in pr_labels}
+ reviews = list(pr.get_reviews())
+ review_by_user: dict[str, PullRequestReview] = {}
+ for review in reviews:
+ if review.user.login in review_by_user:
+ stored_review = review_by_user[review.user.login]
+ if review.submitted_at >= stored_review.submitted_at:
+ review_by_user[review.user.login] = review
+ else:
+ review_by_user[review.user.login] = review
+ approved_reviews = [
+ review for review in review_by_user.values() if review.state == "APPROVED"
+ ]
+ config = settings.config or default_config
+ for approved_label, conf in config.items():
+ logging.debug(f"Processing config: {conf.json()}")
+ if conf.await_label is None or (conf.await_label in pr_label_by_name):
+ logging.debug(f"Processable PR: {pr.number}")
+ if len(approved_reviews) >= conf.number:
+ logging.info(f"Adding label to PR: {pr.number}")
+ pr.add_to_labels(approved_label)
+ if conf.await_label:
+ logging.info(f"Removing label from PR: {pr.number}")
+ pr.remove_from_labels(conf.await_label)
+logging.info("Finished")