Parámetros de Query¶
Cuando declaras otros parámetros de función que no son parte de los parámetros de path, son automáticamente interpretados como parámetros de "query".
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]
La query es el conjunto de pares clave-valor que van después del ?
en una URL, separados por caracteres &
.
Por ejemplo, en la URL:
http://127.0.0.1:8000/items/?skip=0&limit=10
...los parámetros de query son:
skip
: con un valor de0
limit
: con un valor de10
Como son parte de la URL, son "naturalmente" strings.
Pero cuando los declaras con tipos de Python (en el ejemplo anterior, como int
), son convertidos a ese tipo y validados respecto a él.
Todo el mismo proceso que se aplica para los parámetros de path también se aplica para los parámetros de query:
- Soporte del editor (obviamente)
- "Parsing" de datos
- Validación de datos
- Documentación automática
Valores por defecto¶
Como los parámetros de query no son una parte fija de un path, pueden ser opcionales y pueden tener valores por defecto.
En el ejemplo anterior, tienen valores por defecto de skip=0
y limit=10
.
Entonces, ir a la URL:
http://127.0.0.1:8000/items/
sería lo mismo que ir a:
http://127.0.0.1:8000/items/?skip=0&limit=10
Pero si vas a, por ejemplo:
http://127.0.0.1:8000/items/?skip=20
Los valores de los parámetros en tu función serán:
skip=20
: porque lo configuraste en la URLlimit=10
: porque ese era el valor por defecto
Parámetros opcionales¶
De la misma manera, puedes declarar parámetros de query opcionales, estableciendo su valor por defecto en 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}
🤓 Other versions and variants
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}
Revisa
Además, nota que FastAPI es lo suficientemente inteligente para notar que el parámetro de path item_id
es un parámetro de path y q
no lo es, por lo tanto, es un parámetro de query.
Conversión de tipos en parámetros de query¶
También puedes declarar tipos bool
, y serán 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
🤓 Other versions and variants
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
En este caso, si vas a:
http://127.0.0.1:8000/items/foo?short=1
o
http://127.0.0.1:8000/items/foo?short=True
o
http://127.0.0.1:8000/items/foo?short=true
o
http://127.0.0.1:8000/items/foo?short=on
o
http://127.0.0.1:8000/items/foo?short=yes
o cualquier otra variación (mayúsculas, primera letra en mayúscula, etc.), tu función verá el parámetro short
con un valor bool
de True
. De lo contrario, será False
.
Múltiples parámetros de path y de query¶
Puedes declarar múltiples parámetros de path y de query al mismo tiempo, FastAPI sabe cuál es cuál.
Y no tienes que declararlos en un orden específico.
Serán detectados por nombre:
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
🤓 Other versions and variants
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 query requeridos¶
Cuando declaras un valor por defecto para parámetros que no son de path (por ahora, solo hemos visto parámetros de query), entonces no es requerido.
Si no quieres agregar un valor específico pero solo hacer que sea opcional, establece el valor por defecto como None
.
Pero cuando quieres hacer un parámetro de query requerido, simplemente no declares ningún valor por defecto:
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
Aquí el parámetro de query needy
es un parámetro de query requerido de tipo str
.
Si abres en tu navegador una URL como:
http://127.0.0.1:8000/items/foo-item
...sin agregar el parámetro requerido needy
, verás un error como:
{
"detail": [
{
"type": "missing",
"loc": [
"query",
"needy"
],
"msg": "Field required",
"input": null,
"url": "https://errors.pydantic.dev/2.1/v/missing"
}
]
}
Como needy
es un parámetro requerido, necesitarías establecerlo en la URL:
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
...esto funcionaría:
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
Y por supuesto, puedes definir algunos parámetros como requeridos, algunos con un valor por defecto, y algunos enteramente opcionales:
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
🤓 Other versions and variants
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
En este caso, hay 3 parámetros de query:
needy
, unstr
requerido.skip
, unint
con un valor por defecto de0
.limit
, unint
opcional.
Consejo
También podrías usar Enum
s de la misma manera que con Parámetros de Path.