De la misma manera que puedes declarar más validaciones y metadatos para los parámetros de consulta con Query, puedes declarar el mismo tipo de validaciones y metadatos para los parámetros de ruta con Path.
Primero, importa Path de fastapi, e importa Annotated:
fromtypingimportAnnotatedfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get")],q:Annotated[str|None,Query(alias="item-query")]=None,):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
Consejo
Preferible usar la versión con Annotated si es posible.
fromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:int=Path(title="The ID of the item to get"),q:str|None=Query(default=None,alias="item-query"),):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Nota
FastAPI añadió soporte para Annotated (y empezó a recomendarlo) en la versión 0.95.0.
Si tienes una versión anterior, obtendrías errores al intentar usar Annotated.
Puedes declarar todos los mismos parámetros que para Query.
Por ejemplo, para declarar un valor de metadatos title para el parámetro de ruta item_id puedes escribir:
fromtypingimportAnnotatedfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get")],q:Annotated[str|None,Query(alias="item-query")]=None,):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
Consejo
Preferible usar la versión con Annotated si es posible.
fromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:int=Path(title="The ID of the item to get"),q:str|None=Query(default=None,alias="item-query"),):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Nota
Un parámetro de ruta siempre es obligatorio ya que tiene que ser parte de la ruta. Incluso si lo declaras con None o le asignas un valor por defecto, no afectaría nada, seguiría siendo siempre obligatorio.
Esto probablemente no sea tan importante o necesario si usas Annotated.
Digamos que quieres declarar el parámetro de consulta q como un str obligatorio.
Y no necesitas declarar nada más para ese parámetro, así que en realidad no necesitas usar Query.
Pero aún necesitas usar Path para el parámetro de ruta item_id. Y no quieres usar Annotated por alguna razón.
Python se quejará si pones un valor con un "default" antes de un valor que no tiene un "default".
Pero puedes reordenarlos, y tener el valor sin un valor por defecto (el parámetro de consulta q) primero.
No importa para FastAPI. Detectará los parámetros por sus nombres, tipos y declaraciones por defecto (Query, Path, etc), no le importa el orden.
Así que, puedes declarar tu función como:
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(q:str,item_id:int=Path(title="The ID of the item to get")):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(q:str,item_id:Annotated[int,Path(title="The ID of the item to get")]):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Pero ten en cuenta que si usas Annotated, no tendrás este problema, no importará ya que no estás usando los valores por defecto de los parámetros de la función para Query() o Path().
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(q:str,item_id:Annotated[int,Path(title="The ID of the item to get")]):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
Consejo
Preferible usar la versión con Annotated si es posible.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(q:str,item_id:int=Path(title="The ID of the item to get")):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Esto probablemente no sea tan importante o necesario si usas Annotated.
Aquí hay un pequeño truco que puede ser útil, pero no lo necesitarás a menudo.
Si quieres:
declarar el parámetro de consulta q sin un Query ni ningún valor por defecto
declarar el parámetro de ruta item_id usando Path
tenerlos en un orden diferente
no usar Annotated
...Python tiene una pequeña sintaxis especial para eso.
Pasa *, como primer parámetro de la función.
Python no hará nada con ese *, pero sabrá que todos los parámetros siguientes deben ser llamados como argumentos de palabra clave (pares clave-valor), también conocidos como kwargs. Incluso si no tienen un valor por defecto.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get"),q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get")],q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Ten en cuenta que si usas Annotated, como no estás usando los valores por defecto de los parámetros de la función, no tendrás este problema, y probablemente no necesitarás usar *.
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get")],q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
Consejo
Preferible usar la versión con Annotated si es posible.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get"),q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Con Query y Path (y otros que verás más adelante) puedes declarar restricciones numéricas.
Aquí, con ge=1, item_id deberá ser un número entero "greater than or equal" (mayor o igual) a 1.
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get",ge=1)],q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
Consejo
Preferible usar la versión con Annotated si es posible.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get",ge=1),q:str):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Validaciones numéricas: mayor que y menor o igual¶
Lo mismo aplica para:
gt: greater than (mayor que)
le: less than or equal (menor o igual)
fromtypingimportAnnotatedfromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(item_id:Annotated[int,Path(title="The ID of the item to get",gt=0,le=1000)],q:str,):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
🤓 Otras versiones y variantes
Consejo
Preferible usar la versión con Annotated si es posible.
fromfastapiimportFastAPI,Pathapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get",gt=0,le=1000),q:str,):results={"item_id":item_id}ifq:results.update({"q":q})returnresults
Validaciones numéricas: floats, mayor que y menor que¶
Las validaciones numéricas también funcionan para valores float.
Aquí es donde se vuelve importante poder declarar gt y no solo ge. Ya que con él puedes requerir, por ejemplo, que un valor sea mayor que 0, incluso si es menor que 1.
Así que, 0.5 sería un valor válido. Pero 0.0 o 0 no lo serían.
Y lo mismo para lt.
fromtypingimportAnnotatedfromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:Annotated[int,Path(title="The ID of the item to get",ge=0,le=1000)],q:str,size:Annotated[float,Query(gt=0,lt=10.5)],):results={"item_id":item_id}ifq:results.update({"q":q})ifsize:results.update({"size":size})returnresults
🤓 Otras versiones y variantes
Consejo
Preferible usar la versión con Annotated si es posible.
fromfastapiimportFastAPI,Path,Queryapp=FastAPI()@app.get("/items/{item_id}")asyncdefread_items(*,item_id:int=Path(title="The ID of the item to get",ge=0,le=1000),q:str,size:float=Query(gt=0,lt=10.5),):results={"item_id":item_id}ifq:results.update({"q":q})ifsize:results.update({"size":size})returnresults