Parâmetros de Consulta¶
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".
from fastapi import FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
return fake_items_db[skip : skip + limit]
A consulta é o conjunto de pares chave-valor que vai depois de ?
na URL, separado pelo caractere &
.
Por exemplo, na URL:
http://127.0.0.1:8000/items/?skip=0&limit=10
...os parâmetros da consulta são:
skip
: com o valor0
limit
: com o valor10
Como eles são parte da URL, eles são "naturalmente" strings.
Mas quando você declara eles com os tipos do Python (no exemplo acima, como int
), eles são convertidos para aquele tipo e validados em relação a ele.
Todo o processo que era aplicado para parâmetros de rota também é aplicado para parâmetros de consulta:
- Suporte do editor (obviamente)
- "Parsing" de dados
- Validação de dados
- Documentação automática
Valores padrão¶
Como os parâmetros de consulta não são uma parte fixa da rota, eles podem ser opcionais e podem ter valores padrão.
No exemplo acima eles tem valores padrão de skip=0
e limit=10
.
Então, se você for até a URL:
http://127.0.0.1:8000/items/
Seria o mesmo que ir para:
http://127.0.0.1:8000/items/?skip=0&limit=10
Mas, se por exemplo você for para:
http://127.0.0.1:8000/items/?skip=20
Os valores dos parâmetros na sua função serão:
skip=20
: Por que você definiu isso na URLlimit=10
: Por que esse era o valor padrão
Parâmetros opcionais¶
Da mesma forma, você pode declarar parâmetros de consulta opcionais, definindo o valor padrão para None
:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None):
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None):
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
Nesse caso, o parâmetro da função q
será opcional, e None
será o padrão.
Verificar
Você também pode notar que o FastAPI é esperto o suficiente para perceber que o parâmetro da rota item_id
é um parâmetro da rota, e q
não é, portanto, q
é o parâmetro de consulta.
Conversão dos tipos de parâmetros de consulta¶
Você também pode declarar tipos bool
, e eles serão convertidos:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None, short: bool = False):
item = {"item_id": item_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None, short: bool = False):
item = {"item_id": item_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item
Nesse caso, se você for para:
http://127.0.0.1:8000/items/foo?short=1
ou
http://127.0.0.1:8000/items/foo?short=True
ou
http://127.0.0.1:8000/items/foo?short=true
ou
http://127.0.0.1:8000/items/foo?short=on
ou
http://127.0.0.1:8000/items/foo?short=yes
ou qualquer outra variação (tudo em maiúscula, primeira letra em maiúscula, etc), a sua função vai ver o parâmetro short
com um valor bool
de True
. Caso contrário False
.
Múltiplos parâmetros de rota e consulta¶
Você pode declarar múltiplos parâmetros de rota e parâmetros de consulta ao mesmo tempo, o FastAPI vai saber o quê é o quê.
E você não precisa declarar eles em nenhuma ordem específica.
Eles serão detectados pelo nome:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
user_id: int, item_id: str, q: str | None = None, short: bool = False
):
item = {"item_id": item_id, "owner_id": user_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False
):
item = {"item_id": item_id, "owner_id": user_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item
Parâmetros de consulta obrigatórios¶
Quando você declara um valor padrão para parâmetros que não são de rota (até agora, nós vimos apenas parâmetros de consulta), então eles não são obrigatórios.
Caso você não queira adicionar um valor específico mas queira apenas torná-lo opcional, defina o valor padrão como None
.
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.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
item = {"item_id": item_id, "needy": needy}
return item
Aqui o parâmetro de consulta needy
é um valor obrigatório, do tipo str
.
Se você abrir no seu navegador a URL:
http://127.0.0.1:8000/items/foo-item
... sem adicionar o parâmetro obrigatório needy
, você verá um erro como:
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
Como needy
é um parâmetro obrigatório, você precisaria defini-lo na URL:
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
...isso deve funcionar:
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
E claro, você pode definir alguns parâmetros como obrigatórios, alguns possuindo um valor padrão, e outros sendo totalmente opcionais:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_user_item(
item_id: str, needy: str, skip: int = 0, limit: int | None = None
):
item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
return item
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_user_item(
item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None
):
item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
return item
Nesse caso, existem 3 parâmetros de consulta:
needy
, umstr
obrigatório.skip
, umint
com o valor padrão0
.limit
, umint
opcional.
Dica
Você também poderia usar Enum
da mesma forma que com Path Parameters.