Parâmetros de consulta e validações de texto¶
O FastAPI permite que você declare informações adicionais e validações aos seus parâmetros.
Vamos utilizar essa aplicação como exemplo:
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
O parâmetro de consulta q
é do tipo Union[str, None]
, o que significa que é do tipo str
mas que também pode ser None
, e de fato, o valor padrão é None
, então o FastAPI saberá que não é obrigatório.
Observação
O FastAPI saberá que o valor de q
não é obrigatório por causa do valor padrão = None
.
O Union
em Union[str, None]
não é usado pelo FastAPI, mas permitirá que seu editor lhe dê um melhor suporte e detecte erros.
Validação adicional¶
Nós iremos forçar que mesmo o parâmetro q
seja opcional, sempre que informado, seu tamanho não exceda 50 caracteres.
Importe Query
¶
Para isso, primeiro importe Query
de fastapi
:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Use Query
como o valor padrão¶
Agora utilize-o como valor padrão do seu parâmetro, definindo o parâmetro max_length
para 50:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Note que substituímos o valor padrão de None
para Query(default=None)
, o primeiro parâmetro de Query
serve para o mesmo propósito: definir o valor padrão do parâmetro.
Então:
q: Union[str, None] = Query(default=None)
...Torna o parâmetro opcional, da mesma maneira que:
q: Union[str, None] = None
Mas o declara explicitamente como um parâmetro de consulta.
Informação
Tenha em mente que o FastAPI se preocupa com a parte:
= None
Ou com:
= Query(default=None)
E irá utilizar o None
para detectar que o parâmetro de consulta não é obrigatório.
O Union
é apenas para permitir que seu editor de texto lhe dê um melhor suporte.
Então, podemos passar mais parâmetros para Query
. Neste caso, o parâmetro max_length
que se aplica a textos:
q: str = Query(default=None, max_length=50)
Isso irá validar os dados, mostrar um erro claro quando os dados forem inválidos, e documentar o parâmetro na operação de rota do esquema OpenAPI..
Adicionando mais validações¶
Você também pode incluir um parâmetro min_length
:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Adicionando expressões regulares¶
Você pode definir uma expressão regular que combine com um padrão esperado pelo parâmetro:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None, min_length=3, max_length=50, pattern="^fixedquery$"
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Essa expressão regular específica verifica se o valor recebido no parâmetro:
^
: Inicia com os seguintes caracteres, ou seja, não contém caracteres anteriores.fixedquery
: contém o valor exatofixedquery
.$
: termina aqui, não contém nenhum caractere apósfixedquery
.
Se você se sente perdido com todo esse assunto de "expressão regular", não se preocupe. Esse é um assunto complicado para a maioria das pessoas. Você ainda pode fazer muitas coisas sem utilizar expressões regulares.
Mas assim que você precisar e já tiver aprendido sobre, saiba que você poderá usá-las diretamente no FastAPI.
Valores padrão¶
Da mesma maneira que você utiliza None
como o primeiro argumento para ser utilizado como um valor padrão, você pode usar outros valores.
Vamos dizer que você queira que o parâmetro de consulta q
tenha um min_length
de 3
, e um valor padrão de "fixedquery"
, então declararíamos assim:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(default="fixedquery", min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Observação
O parâmetro torna-se opcional quando possui um valor padrão.
Torne-o obrigatório¶
Quando você não necessita de validações ou de metadados adicionais, podemos fazer com que o parâmetro de consulta q
seja obrigatório por não declarar um valor padrão, dessa forma:
q: str
em vez desta:
q: Union[str, None] = None
Mas agora nós o estamos declarando como Query
, conforme abaixo:
q: Union[str, None] = Query(default=None, min_length=3)
Então, quando você precisa declarar um parâmetro obrigatório utilizando o Query
, você pode utilizar ...
como o primeiro argumento:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Informação
Se você nunca viu os ...
antes: é um valor único especial, faz parte do Python e é chamado "Ellipsis".
Dessa forma o FastAPI saberá que o parâmetro é obrigatório.
Lista de parâmetros de consulta / múltiplos valores¶
Quando você declara explicitamente um parâmetro com Query
você pode declará-lo para receber uma lista de valores, ou podemos dizer, que irá receber mais de um valor.
Por exemplo, para declarar que o parâmetro q
pode aparecer diversas vezes na URL, você escreveria:
from typing import List, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
query_items = {"q": q}
return query_items
Então, com uma URL assim:
http://localhost:8000/items/?q=foo&q=bar
você receberá os múltiplos parâmetros de consulta q
com os valores (foo
e bar
) em uma lista (list
) Python dentro da função de operação de rota, no parâmetro da função q
.
Assim, a resposta para essa URL seria:
{
"q": [
"foo",
"bar"
]
}
Dica
Para declarar um parâmetro de consulta com o tipo list
, como no exemplo acima, você precisa usar explicitamente o Query
, caso contrário será interpretado como um corpo da requisição.
A documentação interativa da API irá atualizar de acordo, permitindo múltiplos valores:
Lista de parâmetros de consulta / múltiplos valores por padrão¶
E você também pode definir uma lista (list
) de valores padrão caso nenhum seja informado:
from typing import List
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: List[str] = Query(default=["foo", "bar"])):
query_items = {"q": q}
return query_items
Se você for até:
http://localhost:8000/items/
O valor padrão de q
será: ["foo", "bar"]
e sua resposta será:
{
"q": [
"foo",
"bar"
]
}
Usando list
¶
Você também pode utilizar o tipo list
diretamente em vez de List[str]
:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: list = Query(default=[])):
query_items = {"q": q}
return query_items
Observação
Tenha em mente que neste caso, o FastAPI não irá validar os conteúdos da lista.
Por exemplo, um List[int]
iria validar (e documentar) que os contéudos da lista são números inteiros. Mas apenas list
não.
Declarando mais metadados¶
Você pode adicionar mais informações sobre o parâmetro.
Essa informações serão inclusas no esquema do OpenAPI e utilizado pela documentação interativa e ferramentas externas.
Observação
Tenha em mente que cada ferramenta oferece diferentes níveis de suporte ao OpenAPI.
Algumas delas não exibem todas as informações extras que declaramos, ainda que na maioria dos casos, esses recursos estão planejados para desenvolvimento.
Você pode adicionar um title
:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(default=None, title="Query string", min_length=3),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
E uma description
:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None,
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Apelidos (alias) de parâmetros¶
Imagine que você queira que um parâmetro tenha o nome item-query
.
Desta maneira:
http://127.0.0.1:8000/items/?item-query=foobaritems
Mas o nome item-query
não é um nome de váriavel válido no Python.
O que mais se aproxima é item_query
.
Mas ainda você precisa que o nome seja exatamente item-query
...
Então você pode declarar um alias
, e esse apelido (alias) que será utilizado para encontrar o valor do parâmetro:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Parâmetros descontinuados¶
Agora vamos dizer que você não queria mais utilizar um parâmetro.
Você tem que deixá-lo ativo por um tempo, já que existem clientes o utilizando. Mas você quer que a documentação deixe claro que este parâmetro será descontinuado.
Então você passa o parâmetro deprecated=True
para Query
:
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None,
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Na documentação aparecerá assim:
Recapitulando¶
Você pode adicionar validações e metadados adicionais aos seus parâmetros.
Validações genéricas e metadados:
alias
title
description
deprecated
Validações específicas para textos:
min_length
max_length
regex
Nesses exemplos você viu como declarar validações em valores do tipo str
.
Leia os próximos capítulos para ver como declarar validação de outros tipos, como números.