Ir para o conteúdo

Modelos de Parâmetros de Consulta

AI coding agents

Use the official FastAPI skill for your installed version. Install it from your project directory:

uvx library-skills

See Develop with AI.

🌐 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.

Versão em inglês

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. 😎

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:

from typing import Annotated, Literal

from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()


class FilterParams(BaseModel):
    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    order_by: Literal["created_at", "updated_at"] = "created_at"
    tags: list[str] = []


@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
    return filter_query
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from typing import Literal

from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()


class FilterParams(BaseModel):
    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    order_by: Literal["created_at", "updated_at"] = "created_at"
    tags: list[str] = []


@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
    return filter_query

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

Você pode ver os parâmetros de consulta na IU da documentação em /docs:

Restrinja Parâmetros de Consulta Extras

Em alguns casos especiais (provavelmente não muito comuns), você pode querer restringir os parâmetros de consulta que deseja receber.

Você pode usar a configuração do modelo Pydantic para forbid qualquer campo extra:

from typing import Annotated, Literal

from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()


class FilterParams(BaseModel):
    model_config = {"extra": "forbid"}

    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    order_by: Literal["created_at", "updated_at"] = "created_at"
    tags: list[str] = []


@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
    return filter_query
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from typing import Literal

from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()


class FilterParams(BaseModel):
    model_config = {"extra": "forbid"}

    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    order_by: Literal["created_at", "updated_at"] = "created_at"
    tags: list[str] = []


@app.get("/items/")
async def read_items(filter_query: FilterParams = Query()):
    return filter_query

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:

https://example.com/items/?limit=10&tool=plumbus

Eles receberão um retorno de erro informando-os que o parâmetro de consulta tool não é permitido:

{
    "detail": [
        {
            "type": "extra_forbidden",
            "loc": ["query", "tool"],
            "msg": "Extra inputs are not permitted",
            "input": "plumbus"
        }
    ]
}

Combine Modelos de Parâmetros

Você pode declarar vários modelos de parâmetros de consulta e combiná-los com parâmetros de consulta individuais ou dependências.

from typing import Annotated

from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()


class Pagination(BaseModel):
    limit: int = Field(10, ge=1)
    offset: int = Field(0, ge=0)


class Filters(BaseModel):
    tags: list[str] = []


@app.get("/items/")
def read_items(
    pagination: Annotated[Pagination, Query()],
    filters: Annotated[Filters, Query()],
    search: str | None = None,
):
    return {"pagination": pagination, "filters": filters, "search": search}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()


class Pagination(BaseModel):
    limit: int = Field(10, ge=1)
    offset: int = Field(0, ge=0)


class Filters(BaseModel):
    tags: list[str] = []


@app.get("/items/")
def read_items(
    pagination: Pagination = Query(),
    filters: Filters = Query(),
    search: str | None = None,
):
    return {"pagination": pagination, "filters": filters, "search": search}

Os parâmetros da requisição permanecem no mesmo nível.

https://example.com/items/?limit=5&offset=10&tags=red&tags=blue&search=shirt

Não há chaves pagination ou filters na string de consulta. Cada modelo valida os parâmetros de consulta de forma independente, com seus próprios valores padrão, validadores de campo e de modelo. O mesmo se aplica quando os modelos ou parâmetros individuais são declarados em dependências.

Se os modelos compartilham um nome ou alias de parâmetro, cada modelo valida esse parâmetro da requisição de forma independente. Use nomes ou aliases distintos para valores independentes. O OpenAPI lista um parâmetro compartilhado apenas uma vez, assim como faz com parâmetros compartilhados com dependências, portanto as declarações compartilhadas deveriam descrever o mesmo tipo e as mesmas restrições.

A configuração extra de cada modelo se aplica a todos os parâmetros de consulta, incluindo os declarados em outros modelos ou dependências. Com extra="forbid", qualquer parâmetro fora desse modelo é rejeitado. Com extra="allow", esses parâmetros são incluídos como extras do modelo.

Isso também funciona para modelos Header e Cookie.

Modelos Opcionais de Parâmetros de Consulta

Declare um modelo de parâmetros de consulta com | None e um valor padrão de None para tornar o grupo opcional.

from datetime import date
from typing import Annotated

from fastapi import FastAPI, Query
from pydantic import BaseModel

app = FastAPI()


class DateRange(BaseModel):
    start: date
    end: date


@app.get("/items/")
async def read_items(
    limit: int = 10,
    date_range: Annotated[DateRange | None, Query()] = None,
):
    return {"limit": limit, "date_range": date_range}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from datetime import date

from fastapi import FastAPI, Query
from pydantic import BaseModel

app = FastAPI()


class DateRange(BaseModel):
    start: date
    end: date


@app.get("/items/")
async def read_items(
    limit: int = 10,
    date_range: DateRange | None = Query(default=None),
):
    return {"limit": limit, "date_range": date_range}

Se nem start nem end forem enviados, date_range será None. Se qualquer um deles for enviado, o FastAPI validará o modelo e exigirá ambos os campos.

Usar | None sem um valor padrão ainda torna o parâmetro obrigatório.

Parâmetros extras seguem a configuração extra do modelo. Extras ignorados não fazem com que o modelo seja considerado presente.

O OpenAPI lista os campos do grupo individualmente e os marca como opcionais.

Você também pode declarar modelos de parâmetros de cabeçalho e modelos de parâmetros de cookie opcionais.

Resumo

Você pode utilizar modelos Pydantic para declarar parâmetros de consulta no FastAPI. 😎

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. 🤫