Saltar al contenido

Parámetros de Consulta

Cuando declaras otros parámetros de función que no son parte de los parámetros de ruta, se interpretan automáticamente 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]

La consulta 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 consulta son:

  • skip: con un valor de 0
  • limit: con un valor de 10

Como son parte de la URL, son "naturalmente" cadenas.

Pero cuando los declaras con tipos de Python (en el ejemplo de arriba, como int), se convierten a ese tipo y se validan contra él.

Todos los mismos procesos que aplican a los parámetros de ruta también aplican a los parámetros de consulta:

  • Soporte del editor (obviamente)
  • "Análisis" de datos
  • Validación de datos
  • Documentación automática

Valores por defecto

Como los parámetros de consulta no son una parte fija de una ruta, pueden ser opcionales y pueden tener valores por defecto.

En el ejemplo de arriba tienen valores por defecto de skip=0 y limit=10.

Así que, yendo 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 estableciste en la URL
  • limit=10: porque ese era el valor por defecto

Parámetros opcionales

De la misma manera, puedes declarar parámetros de consulta 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}

En este caso, el parámetro de función q será opcional, y será None por defecto.

Consejo

También notarás que FastAPI es lo suficientemente inteligente para notar que el parámetro de ruta item_id es un parámetro de ruta y q no lo es, así que, es un parámetro de consulta.

Conversión de tipo de parámetros de consulta

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

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 de mayúsculas/minúsculas (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 como False.

Múltiples parámetros de ruta y de consulta

Puedes declarar múltiples parámetros de ruta y de consulta al mismo tiempo, FastAPI sabe cuál es cuál.

Y no tienes que declararlos en ningún 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

Parámetros de consulta obligatorios

Cuando declaras un valor por defecto para parámetros que no son de ruta (por ahora, solo hemos visto parámetros de consulta), entonces no es obligatorio.

Si no quieres añadir un valor específico sino solo hacerlo opcional, establece el valor por defecto como None.

Pero cuando quieres hacer que un parámetro de consulta sea obligatorio, puedes simplemente no declarar 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 consulta needy es un parámetro de consulta obligatorio de tipo str.

Si abres en tu navegador una URL como:

http://127.0.0.1:8000/items/foo-item

...sin añadir el parámetro obligatorio needy, verás un error como:

{
  "detail": [
    {
      "type": "missing",
      "loc": [
        "query",
        "needy"
      ],
      "msg": "Field required",
      "input": null
    }
  ]
}

Como needy es un parámetro obligatorio, 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 obligatorios, algunos con un valor por defecto, y algunos completamente 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

En este caso, hay 3 parámetros de consulta:

  • needy, un str obligatorio.
  • skip, un int con un valor por defecto de 0.
  • limit, un int opcional.

Consejo

También podrías usar Enums de la misma manera que con los Parámetros de Ruta.