Paramètres de chemin et validations numériques¶
De la même façon que vous pouvez déclarer plus de validations et de métadonnées pour les paramètres de requête avec Query
, vous pouvez déclarer le même type de validations et de métadonnées pour les paramètres de chemin avec Path
.
Importer Path¶
Tout d'abord, importez Path
de fastapi
, et importez Annotated
:
from typing import Annotated
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")],
q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")],
q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: int = Path(title="The ID of the item to get"),
q: Union[str, None] = Query(default=None, alias="item-query"),
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Info
FastAPI a ajouté le support pour Annotated
(et a commencé à le recommander) dans la version 0.95.0.
Si vous avez une version plus ancienne, vous obtiendrez des erreurs en essayant d'utiliser Annotated
.
Assurez-vous de Mettre à jour la version de FastAPI à la version 0.95.1 à minima avant d'utiliser Annotated
.
Déclarer des métadonnées¶
Vous pouvez déclarer les mêmes paramètres que pour Query
.
Par exemple, pour déclarer une valeur de métadonnée title
pour le paramètre de chemin item_id
, vous pouvez écrire :
from typing import Annotated
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")],
q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")],
q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: int = Path(title="The ID of the item to get"),
q: Union[str, None] = Query(default=None, alias="item-query"),
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Note
Un paramètre de chemin est toujours requis car il doit faire partie du chemin. Même si vous l'avez déclaré avec None
ou défini une valeur par défaut, cela ne changerait rien, il serait toujours requis.
Ordonnez les paramètres comme vous le souhaitez¶
Tip
Ce n'est probablement pas aussi important ou nécessaire si vous utilisez Annotated
.
Disons que vous voulez déclarer le paramètre de requête q
comme un str
requis.
Et vous n'avez pas besoin de déclarer autre chose pour ce paramètre, donc vous n'avez pas vraiment besoin d'utiliser Query
.
Mais vous avez toujours besoin d'utiliser Path
pour le paramètre de chemin item_id
. Et vous ne voulez pas utiliser Annotated
pour une raison quelconque.
Python se plaindra si vous mettez une valeur avec une "défaut" avant une valeur qui n'a pas de "défaut".
Mais vous pouvez les réorganiser, et avoir la valeur sans défaut (le paramètre de requête q
) en premier.
Cela n'a pas d'importance pour FastAPI. Il détectera les paramètres par leurs noms, types et déclarations par défaut (Query
, Path
, etc), il ne se soucie pas de l'ordre.
Ainsi, vous pouvez déclarer votre fonction comme suit :
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
from fastapi import FastAPI, Path
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Mais gardez à l'esprit que si vous utilisez Annotated
, vous n'aurez pas ce problème, cela n'aura pas d'importance car vous n'utilisez pas les valeurs par défaut des paramètres de fonction pour Query()
ou Path()
.
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Ordonnez les paramètres comme vous le souhaitez (astuces)¶
Tip
Ce n'est probablement pas aussi important ou nécessaire si vous utilisez Annotated
.
Voici une petite astuce qui peut être pratique, mais vous n'en aurez pas souvent besoin.
Si vous voulez :
- déclarer le paramètre de requête
q
sansQuery
ni valeur par défaut - déclarer le paramètre de chemin
item_id
en utilisantPath
- les avoir dans un ordre différent
- ne pas utiliser
Annotated
...Python a une petite syntaxe spéciale pour cela.
Passez *
, comme premier paramètre de la fonction.
Python ne fera rien avec ce *
, mais il saura que tous les paramètres suivants doivent être appelés comme arguments "mots-clés" (paires clé-valeur), également connus sous le nom de kwargs
. Même s'ils n'ont pas de valeur par défaut.
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
from fastapi import FastAPI, Path
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Avec Annotated
¶
Gardez à l'esprit que si vous utilisez Annotated
, comme vous n'utilisez pas les valeurs par défaut des paramètres de fonction, vous n'aurez pas ce problème, et vous n'aurez probablement pas besoin d'utiliser *
.
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Validations numériques : supérieur ou égal¶
Avec Query
et Path
(et d'autres que vous verrez plus tard) vous pouvez déclarer des contraintes numériques.
Ici, avec ge=1
, item_id
devra être un nombre entier "g
reater than or e
qual" à 1
.
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
*, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Validations numériques : supérieur ou égal et inférieur ou égal¶
La même chose s'applique pour :
gt
:g
reatert
hanle
:l
ess than ore
qual
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
*, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Validations numériques : supérieur et inférieur ou égal¶
La même chose s'applique pour :
gt
:g
reatert
hanle
:l
ess than ore
qual
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
*,
item_id: int = Path(title="The ID of the item to get", gt=0, le=1000),
q: str,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
Validations numériques : flottants, supérieur et inférieur¶
Les validations numériques fonctionnent également pour les valeurs float
.
C'est ici qu'il devient important de pouvoir déclarer gt
et pas seulement ge
. Avec cela, vous pouvez exiger, par exemple, qu'une valeur doit être supérieure à 0
, même si elle est inférieure à 1
.
Ainsi, 0.5
serait une valeur valide. Mais 0.0
ou 0
ne le serait pas.
Et la même chose pour lt
.
from typing import Annotated
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
if size:
results.update({"size": size})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
if size:
results.update({"size": size})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_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}
if q:
results.update({"q": q})
if size:
results.update({"size": size})
return results
Pour résumer¶
Avec Query
, Path
(et d'autres que vous verrez plus tard) vous pouvez déclarer des métadonnées et des validations de chaînes de la même manière qu'avec les Paramètres de requête et validations de chaînes.
Et vous pouvez également déclarer des validations numériques :
gt
:g
reatert
hange
:g
reater than ore
quallt
:l
esst
hanle
:l
ess than ore
qual
Info
Query
, Path
, et d'autres classes que vous verrez plus tard sont des sous-classes d'une classe commune Param
.
Tous partagent les mêmes paramètres pour des validations supplémentaires et des métadonnées que vous avez vu précédemment.
Détails techniques
Lorsque vous importez Query
, Path
et d'autres de fastapi
, ce sont en fait des fonctions.
Ces dernières, lorsqu'elles sont appelées, renvoient des instances de classes du même nom.
Ainsi, vous importez Query
, qui est une fonction. Et lorsque vous l'appelez, elle renvoie une instance d'une classe également nommée Query
.
Ces fonctions sont là (au lieu d'utiliser simplement les classes directement) pour que votre éditeur ne marque pas d'erreurs sur leurs types.
De cette façon, vous pouvez utiliser votre éditeur et vos outils de codage habituels sans avoir à ajouter des configurations personnalisées pour ignorer ces erreurs.