DĂ©pendances¶
đ Traduction par IA et humains
Cette traduction a Ă©tĂ© rĂ©alisĂ©e par une IA guidĂ©e par des humains. đ€
Elle peut contenir des erreurs d'interprĂ©tation du sens original, ou paraĂźtre peu naturelle, etc. đ€
Vous pouvez améliorer cette traduction en nous aidant à mieux guider le LLM d'IA.
FastAPI dispose dâun systĂšme dâInjection de dĂ©pendances trĂšs puissant mais intuitif.
Il est conçu pour ĂȘtre trĂšs simple Ă utiliser, et pour faciliter lâintĂ©gration dâautres composants Ă FastAPI pour nâimporte quel dĂ©veloppeur.
Quâest-ce que « lâinjection de dĂ©pendances »¶
Lâ« injection de dĂ©pendances » signifie, en programmation, quâil existe un moyen pour votre code (dans ce cas, vos fonctions de chemins dâaccĂšs) de dĂ©clarer ce dont il a besoin pour fonctionner et utiliser : « dĂ©pendances ».
Ensuite, ce systÚme (dans ce cas FastAPI) se charge de faire tout le nécessaire pour fournir à votre code ces dépendances requises (« injecter » les dépendances).
Câest trĂšs utile lorsque vous avez besoin de :
- Avoir de la logique partagĂ©e (la mĂȘme logique de code encore et encore).
- Partager des connexions à la base de données.
- Imposer la sĂ©curitĂ©, lâauthentification, des exigences de rĂŽles, etc.
- Et bien dâautres choses ...
Tout cela, en minimisant la répétition de code.
Premiers pas¶
Voyons un exemple trĂšs simple. Il sera tellement simple quâil nâest pas trĂšs utile, pour lâinstant.
Mais de cette façon nous pouvons nous concentrer sur le fonctionnement du systĂšme dâinjection de dĂ©pendances.
CrĂ©er une dĂ©pendance, ou « dependable »¶
Concentrons-nous dâabord sur la dĂ©pendance.
Câest simplement une fonction qui peut prendre tous les mĂȘmes paramĂštres quâune fonction de chemin dâaccĂšs peut prendre :
from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
return commons
@app.get("/users/")
async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
return commons
đ€ Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
Câest tout.
2 lignes.
Et elle a la mĂȘme forme et structure que toutes vos fonctions de chemins dâaccĂšs.
Vous pouvez la considĂ©rer comme une fonction de chemin dâaccĂšs sans le « dĂ©corateur » (sans le @app.get("/some-path")).
Et elle peut retourner tout ce que vous voulez.
Dans ce cas, cette dépendance attend :
- Un paramĂštre de requĂȘte optionnel
qqui est unestr. - Un paramĂštre de requĂȘte optionnel
skipqui est unint, et vaut0par dĂ©faut. - Un paramĂštre de requĂȘte optionnel
limitqui est unint, et vaut100par défaut.
Puis elle retourne simplement un dict contenant ces valeurs.
Info
FastAPI a ajouté la prise en charge de 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.
Vous devez vous assurer de mettre Ă niveau la version de FastAPI vers au moins la 0.95.1 avant dâutiliser Annotated.
Importer Depends¶
from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
return commons
@app.get("/users/")
async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
return commons
đ€ Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
DĂ©clarer la dĂ©pendance, dans le « dependant »¶
De la mĂȘme maniĂšre que vous utilisez Body, Query, etc. avec les paramĂštres de votre fonction de chemin dâaccĂšs, utilisez Depends avec un nouveau paramĂštre :
from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
return commons
@app.get("/users/")
async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
return commons
đ€ Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
MĂȘme si vous utilisez Depends dans les paramĂštres de votre fonction de la mĂȘme façon que Body, Query, etc., Depends fonctionne un peu diffĂ©remment.
Vous ne donnez Ă Depends quâun seul paramĂštre.
Ce paramĂštre doit ĂȘtre quelque chose comme une fonction.
Vous ne lâappelez pas directement (nâajoutez pas de parenthĂšses Ă la fin), vous le passez simplement en paramĂštre Ă Depends().
Et cette fonction prend des paramĂštres de la mĂȘme maniĂšre que les fonctions de chemins dâaccĂšs.
Astuce
Vous verrez quelles autres « choses », en plus des fonctions, peuvent ĂȘtre utilisĂ©es comme dĂ©pendances dans le prochain chapitre.
Chaque fois quâune nouvelle requĂȘte arrive, FastAPI se charge de :
- Appeler votre fonction de dépendance (« dependable ») avec les bons paramÚtres.
- Récupérer le résultat de votre fonction.
- Affecter ce rĂ©sultat au paramĂštre dans votre fonction de chemin dâaccĂšs.
graph TB
common_parameters(["common_parameters"])
read_items["/items/"]
read_users["/users/"]
common_parameters --> read_items
common_parameters --> read_users
De cette façon vous Ă©crivez le code partagĂ© une seule fois et FastAPI se charge de lâappeler pour vos chemins dâaccĂšs.
Vérifications
Notez que vous nâavez pas Ă crĂ©er une classe spĂ©ciale et Ă la passer quelque part Ă FastAPI pour lâ« enregistrer » ou quoi que ce soit de similaire.
Vous la passez simplement Ă Depends et FastAPI sait faire le reste.
Partager des dĂ©pendances Annotated¶
Dans les exemples ci-dessus, vous voyez quâil y a un tout petit peu de duplication de code.
Lorsque vous devez utiliser la dĂ©pendance common_parameters(), vous devez Ă©crire tout le paramĂštre avec lâannotation de type et Depends() :
commons: Annotated[dict, Depends(common_parameters)]
Mais comme nous utilisons Annotated, nous pouvons stocker cette valeur Annotated dans une variable et lâutiliser Ă plusieurs endroits :
from typing import Annotated
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
CommonsDep = Annotated[dict, Depends(common_parameters)]
@app.get("/items/")
async def read_items(commons: CommonsDep):
return commons
@app.get("/users/")
async def read_users(commons: CommonsDep):
return commons
Astuce
Câest simplement du Python standard, cela sâappelle un « alias de type », ce nâest en fait pas spĂ©cifique Ă FastAPI.
Mais comme FastAPI est basĂ© sur les standards Python, y compris Annotated, vous pouvez utiliser cette astuce dans votre code. đ
Les dĂ©pendances continueront de fonctionner comme prĂ©vu, et la meilleure partie est que lâinformation de type sera conservĂ©e, ce qui signifie que votre Ă©diteur pourra continuer Ă vous fournir lâautocomplĂ©tion, des erreurs en ligne, etc. Idem pour dâautres outils comme mypy.
Cela sera particuliĂšrement utile lorsque vous lâutiliserez dans une grande base de code oĂč vous utilisez les mĂȘmes dĂ©pendances encore et encore dans de nombreux chemins dâaccĂšs.
Utiliser async ou non¶
Comme les dĂ©pendances seront aussi appelĂ©es par FastAPI (tout comme vos fonctions de chemins dâaccĂšs), les mĂȘmes rĂšgles sâappliquent lors de la dĂ©finition de vos fonctions.
Vous pouvez utiliser async def ou un def normal.
Et vous pouvez dĂ©clarer des dĂ©pendances avec async def Ă lâintĂ©rieur de fonctions de chemins dâaccĂšs def normales, ou des dĂ©pendances def Ă lâintĂ©rieur de fonctions de chemins dâaccĂšs async def, etc.
Peu importe. FastAPI saura quoi faire.
Remarque
Si vous ne savez pas, consultez la section Async : « Pressé ? » à propos de async et await dans la documentation.
IntĂ©grer Ă OpenAPI¶
Toutes les dĂ©clarations de requĂȘte, validations et exigences de vos dĂ©pendances (et sous-dĂ©pendances) seront intĂ©grĂ©es dans le mĂȘme schĂ©ma OpenAPI.
Ainsi, la documentation interactive contiendra aussi toutes les informations issues de ces dépendances :

Utilisation simple¶
Si vous y regardez de prĂšs, les fonctions de chemins dâaccĂšs sont dĂ©clarĂ©es pour ĂȘtre utilisĂ©es chaque fois quâun « chemin » et une « opĂ©ration » correspondent, puis FastAPI se charge dâappeler la fonction avec les bons paramĂštres, en extrayant les donnĂ©es de la requĂȘte.
En réalité, tous (ou la plupart) des frameworks web fonctionnent de cette maniÚre.
Vous nâappelez jamais ces fonctions directement. Elles sont appelĂ©es par votre framework (dans ce cas, FastAPI).
Avec le systĂšme dâinjection de dĂ©pendances, vous pouvez aussi indiquer Ă FastAPI que votre fonction de chemin dâaccĂšs « dĂ©pend » Ă©galement dâautre chose qui doit ĂȘtre exĂ©cutĂ© avant votre fonction de chemin dâaccĂšs, et FastAPI se chargera de lâexĂ©cuter et dâ« injecter » les rĂ©sultats.
Dâautres termes courants pour cette mĂȘme idĂ©e « dâinjection de dĂ©pendances » sont :
- ressources
- fournisseurs
- services
- injectables
- composants
Plug-ins FastAPI¶
Les intĂ©grations et « plug-ins » peuvent ĂȘtre construits en utilisant le systĂšme dâinjection de dĂ©pendances. Mais en rĂ©alitĂ©, il nây a pas besoin de crĂ©er des « plug-ins », car en utilisant des dĂ©pendances il est possible de dĂ©clarer un nombre infini dâintĂ©grations et dâinteractions qui deviennent disponibles pour vos fonctions de chemins dâaccĂšs.
Et les dĂ©pendances peuvent ĂȘtre créées de maniĂšre trĂšs simple et intuitive, ce qui vous permet dâimporter juste les packages Python dont vous avez besoin, et de les intĂ©grer Ă vos fonctions dâAPI en quelques lignes de code, littĂ©ralement.
Vous verrez des exemples de cela dans les prochains chapitres, à propos des bases de données relationnelles et NoSQL, de la sécurité, etc.
CompatibilitĂ© FastAPI¶
La simplicitĂ© du systĂšme dâinjection de dĂ©pendances rend FastAPI compatible avec :
- toutes les bases de données relationnelles
- les bases de données NoSQL
- les packages externes
- les API externes
- les systĂšmes dâauthentification et dâautorisation
- les systĂšmes de supervision dâusage dâAPI
- les systĂšmes dâinjection de donnĂ©es de rĂ©ponse
- etc.
Simple et puissant¶
Bien que le systĂšme hiĂ©rarchique dâinjection de dĂ©pendances soit trĂšs simple Ă dĂ©finir et Ă utiliser, il reste trĂšs puissant.
Vous pouvez définir des dépendances qui, à leur tour, peuvent définir leurs propres dépendances.
Au final, un arbre hiĂ©rarchique de dĂ©pendances est construit, et le systĂšme dâinjection de dĂ©pendances se charge de rĂ©soudre toutes ces dĂ©pendances pour vous (et leurs sous-dĂ©pendances) et de fournir (injecter) les rĂ©sultats Ă chaque Ă©tape.
Par exemple, supposons que vous ayez 4 endpoints dâAPI (chemins dâaccĂšs) :
/items/public//items/private//users/{user_id}/activate/items/pro/
alors vous pourriez ajouter diffĂ©rentes exigences dâautorisations pour chacun dâeux uniquement avec des dĂ©pendances et des sous-dĂ©pendances :
graph TB
current_user(["current_user"])
active_user(["active_user"])
admin_user(["admin_user"])
paying_user(["paying_user"])
public["/items/public/"]
private["/items/private/"]
activate_user["/users/{user_id}/activate"]
pro_items["/items/pro/"]
current_user --> active_user
active_user --> admin_user
active_user --> paying_user
current_user --> public
active_user --> private
admin_user --> activate_user
paying_user --> pro_items
IntĂ©grer Ă OpenAPI¶
Toutes ces dĂ©pendances, tout en dĂ©clarant leurs exigences, ajoutent Ă©galement des paramĂštres, des validations, etc. Ă vos chemins dâaccĂšs.
FastAPI se chargera dâajouter le tout au schĂ©ma OpenAPI, afin que cela apparaisse dans les systĂšmes de documentation interactive.