diff --git a/docs/fr/docs/advanced/advanced-python-types.md b/docs/fr/docs/advanced/advanced-python-types.md index 3e2d9453b6..a5dfdd7716 100644 --- a/docs/fr/docs/advanced/advanced-python-types.md +++ b/docs/fr/docs/advanced/advanced-python-types.md @@ -13,17 +13,17 @@ from typing import Union def say_hi(name: Union[str, None]): - print(f"Hi {name}!") + print(f"Hi {name}!") ``` `typing` propose également un raccourci pour déclarer que quelque chose peut être `None`, avec `Optional`. -Voici un conseil issu de mon point de vue très subjectif : +Voici un conseil issu de mon point de vue très **subjectif** : - 🚨 Évitez d'utiliser `Optional[SomeType]` - À la place ✨ **utilisez `Union[SomeType, None]`** ✨. -Les deux sont équivalents et, en interne, identiques, mais je recommande `Union` plutôt que `Optional` parce que le mot « optional » semble impliquer que la valeur est facultative, alors qu'il signifie en réalité « elle peut être `None` », même si elle n'est pas facultative et reste requise. +Les deux sont équivalents et, en interne, identiques, mais je recommande `Union` plutôt que `Optional` parce que le mot « **optional** » semble impliquer que la valeur est facultative, alors qu'il signifie en réalité « elle peut être `None` », même si elle n'est pas facultative et reste requise. Je pense que `Union[SomeType, None]` est plus explicite quant à sa signification. @@ -39,13 +39,13 @@ def say_hi(name: Optional[str]): print(f"Hey {name}!") ``` -Le paramètre `name` est défini comme `Optional[str]`, mais il n'est pas facultatif, vous ne pouvez pas appeler la fonction sans le paramètre : +Le paramètre `name` est défini comme `Optional[str]`, mais il **n'est pas facultatif**, vous ne pouvez pas appeler la fonction sans le paramètre : ```Python say_hi() # Oh non, cela lève une erreur ! 😱 ``` -Le paramètre `name` est toujours requis (pas facultatif) car il n'a pas de valeur par défaut. En revanche, `name` accepte `None` comme valeur : +Le paramètre `name` est **toujours requis** (pas *facultatif*) car il n'a pas de valeur par défaut. En revanche, `name` accepte `None` comme valeur : ```Python say_hi(name=None) # Ceci fonctionne, None est valide 🎉 diff --git a/docs/fr/docs/advanced/async-tests.md b/docs/fr/docs/advanced/async-tests.md index 13c0aeacce..cc2345b0f0 100644 --- a/docs/fr/docs/advanced/async-tests.md +++ b/docs/fr/docs/advanced/async-tests.md @@ -38,7 +38,7 @@ Le fichier `test_main.py` contiendrait les tests pour `main.py`, il pourrait mai {* ../../docs_src/async_tests/app_a_py310/test_main.py *} -## Exécuter { #run-it } +## Exécutez-le { #run-it } Vous pouvez lancer vos tests comme d'habitude via : @@ -71,7 +71,7 @@ Nous pouvons ensuite créer un `AsyncClient` avec l'application et lui envoyer d C'est l'équivalent de : ```Python -response = client.get('/') +response = client.get("/") ``` ... que nous utilisions pour faire nos requêtes avec le `TestClient`. diff --git a/docs/fr/docs/advanced/behind-a-proxy.md b/docs/fr/docs/advanced/behind-a-proxy.md index d178990f0a..db0fbbd14b 100644 --- a/docs/fr/docs/advanced/behind-a-proxy.md +++ b/docs/fr/docs/advanced/behind-a-proxy.md @@ -8,7 +8,7 @@ Ces proxies peuvent gérer les certificats HTTPS et d'autres aspects. Un **proxy** placé devant votre application définit normalement certains en-têtes à la volée avant d'envoyer les requêtes à votre **serveur**, afin d'indiquer au serveur que la requête a été **transférée** par le proxy, en lui donnant l'URL d'origine (publique), y compris le domaine, le fait qu'elle utilise HTTPS, etc. -Le programme **serveur** (par exemple **Uvicorn** via **FastAPI CLI**) est capable d'interpréter ces en‑têtes, puis de transmettre ces informations à votre application. +Le **serveur** démarré par `fastapi run` est capable d'interpréter ces en‑têtes, puis de transmettre ces informations à votre application. Mais, par sécurité, comme le serveur ne sait pas qu'il se trouve derrière un proxy de confiance, il n'interprétera pas ces en‑têtes. @@ -22,7 +22,7 @@ Les en-têtes du proxy sont : /// -### Activer les en-têtes transférés par le proxy { #enable-proxy-forwarded-headers } +### Activez les en-têtes transférés par le proxy { #enable-proxy-forwarded-headers } Vous pouvez démarrer FastAPI CLI avec l'*option de CLI* `--forwarded-allow-ips` et fournir les adresses IP à considérer comme fiables pour lire ces en‑têtes transférés. @@ -34,8 +34,6 @@ Si votre **serveur** est derrière un **proxy** de confiance et que seul le prox ```console $ uv run fastapi run --forwarded-allow-ips="*" - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -101,7 +99,7 @@ Lorsque **FastAPI CLI** est configurée avec `--forwarded-allow-ips`, elle fait Vous pouvez avoir un proxy qui ajoute un préfixe de chemin à votre application. -Dans ces cas, vous pouvez utiliser `root_path` pour configurer votre application. +Dans ces cas, vous pouvez configurer le serveur avec `fastapi run --root-path`. Le `root_path` est un mécanisme fourni par la spécification ASGI (sur laquelle FastAPI est construit, via Starlette). @@ -117,7 +115,7 @@ Même si tout votre code est écrit en supposant qu'il n'y a que `/app`. {* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} -Et le proxy **« stripping »** le **préfixe de chemin** à la volée avant de transmettre la requête au serveur de l'application (probablement Uvicorn via FastAPI CLI), en gardant votre application convaincue qu'elle est servie à `/app`, afin que vous n'ayez pas à mettre à jour tout votre code pour inclure le préfixe `/api/v1`. +Et le proxy **« supprimerait »** le **préfixe de chemin** à la volée avant de transmettre la requête au serveur, en gardant votre application convaincue qu'elle est servie à `/app`, afin que vous n'ayez pas à mettre à jour tout votre code pour inclure le préfixe `/api/v1`. Jusqu'ici, tout fonctionnerait normalement. @@ -161,7 +159,7 @@ L'interface de documents doit également indiquer dans le schéma OpenAPI que ce } ``` -Dans cet exemple, le « Proxy » pourrait être quelque chose comme **Traefik**. Et le serveur serait quelque chose comme FastAPI CLI avec **Uvicorn**, exécutant votre application FastAPI. +Dans cet exemple, le « Proxy » pourrait être quelque chose comme **Traefik**. Et `fastapi run` démarrerait le serveur exécutant votre application FastAPI. ### Fournir le `root_path` { #providing-the-root-path } @@ -171,14 +169,10 @@ Pour y parvenir, vous pouvez utiliser l'option de ligne de commande `--root-path ```console $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` -Si vous utilisez Hypercorn, il dispose également de l'option `--root-path`. - /// note | Détails techniques La spécification ASGI définit un `root_path` pour ce cas d'usage. @@ -195,14 +189,12 @@ Ici, nous l'incluons dans le message uniquement à des fins de démonstration. {* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} -Ensuite, si vous démarrez Uvicorn avec : +Ensuite, si vous démarrez le serveur avec :
```console $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
@@ -216,30 +208,11 @@ La réponse sera semblable à : } ``` -### Définir le `root_path` dans l'application FastAPI { #setting-the-root-path-in-the-fastapi-app } +/// warning | Paramètre `root_path` déprécié -Autrement, si vous n'avez pas la possibilité de fournir une option de ligne de commande comme `--root-path` ou équivalent, vous pouvez définir le paramètre `root_path` lors de la création de votre application FastAPI : +Dans FastAPI 0.145.0 et les versions antérieures, `root_path` pouvait également être configuré dans `FastAPI()`. Ce paramètre est désormais déprécié, car son comportement n'était pas cohérent avec la configuration du serveur. Utilisez plutôt `fastapi run --root-path /api/v1`. -{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} - -Passer le `root_path` à `FastAPI` équivaut à passer l'option de ligne de commande `--root-path` à Uvicorn ou Hypercorn. - -### À propos de `root_path` { #about-root-path } - -Gardez à l'esprit que le serveur (Uvicorn) n'utilisera ce `root_path` que pour le transmettre à l'application. - -Mais si vous allez avec votre navigateur sur [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), vous verrez la réponse normale : - -```JSON -{ - "message": "Hello World", - "root_path": "/api/v1" -} -``` - -Donc, il ne s'attendra pas à être accessible à `http://127.0.0.1:8000/api/v1/app`. - -Uvicorn s'attendra à ce que le proxy accède à Uvicorn sur `http://127.0.0.1:8000/app`, et ce sera ensuite la responsabilité du proxy d'ajouter le préfixe supplémentaire `/api/v1` au‑dessus. +/// ## À propos des proxies avec un préfixe de chemin supprimé { #about-proxies-with-a-stripped-path-prefix } @@ -247,7 +220,7 @@ Gardez à l'esprit qu'un proxy avec préfixe de chemin supprimé n'est qu'une de Dans de nombreux cas, la valeur par défaut sera probablement que le proxy n'a pas de préfixe de chemin supprimé. -Dans un cas comme celui‑ci (sans préfixe de chemin supprimé), le proxy écoutera sur quelque chose comme `https://myawesomeapp.com`, puis si le navigateur va sur `https://myawesomeapp.com/api/v1/app` et que votre serveur (par ex. Uvicorn) écoute sur `http://127.0.0.1:8000`, le proxy (sans préfixe de chemin supprimé) accédera à Uvicorn au même chemin : `http://127.0.0.1:8000/api/v1/app`. +Dans un cas comme celui‑ci (sans préfixe de chemin supprimé), le proxy écoutera sur quelque chose comme `https://myawesomeapp.com`, puis si le navigateur va sur `https://myawesomeapp.com/api/v1/app` et que votre serveur écoute sur `http://127.0.0.1:8000`, le proxy (sans préfixe de chemin supprimé) accédera au serveur au même chemin : `http://127.0.0.1:8000/api/v1/app`. ## Tester localement avec Traefik { #testing-locally-with-traefik } @@ -302,7 +275,7 @@ Créez maintenant cet autre fichier `routes.toml` : Ce fichier configure Traefik pour utiliser le préfixe de chemin `/api/v1`. -Puis Traefik redirigera ses requêtes vers votre Uvicorn tournant sur `http://127.0.0.1:8000`. +Puis Traefik transmettra ses requêtes à votre serveur tournant sur `http://127.0.0.1:8000`. Démarrez maintenant Traefik : @@ -322,15 +295,13 @@ Et démarrez maintenant votre application, en utilisant l'option `--root-path` : ```console $ uv run fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` -### Vérifier les réponses { #check-the-responses } +### Vérifiez les réponses { #check-the-responses } -Maintenant, si vous allez à l'URL avec le port pour Uvicorn : [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), vous verrez la réponse normale : +Maintenant, si vous allez à l'URL avec le port pour le serveur : [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), vous verrez la réponse normale : ```JSON { @@ -360,15 +331,15 @@ mais cette fois à l'URL avec le préfixe fourni par le proxy : `/api/v1`. Bien sûr, l'idée ici est que tout le monde accède à l'application via le proxy ; la version avec le préfixe de chemin `/api/v1` est donc la « correcte ». -Et la version sans préfixe de chemin (`http://127.0.0.1:8000/app`), fournie directement par Uvicorn, serait exclusivement destinée au _proxy_ (Traefik) pour y accéder. +Et la version sans préfixe de chemin (`http://127.0.0.1:8000/app`), fournie directement par le serveur, serait exclusivement destinée au _proxy_ (Traefik) pour y accéder. -Cela montre comment le Proxy (Traefik) utilise le préfixe de chemin et comment le serveur (Uvicorn) utilise le `root_path` fourni par l'option `--root-path`. +Cela montre comment le Proxy (Traefik) utilise le préfixe de chemin et comment le serveur utilise le `root_path` fourni par l'option `--root-path`. -### Vérifier l'interface de documentation { #check-the-docs-ui } +### Vérifiez l'interface de documentation { #check-the-docs-ui } Mais voici la partie intéressante. ✨ -La manière « officielle » d'accéder à l'application serait via le proxy avec le préfixe de chemin que nous avons défini. Donc, comme on s'y attend, si vous essayez l'interface de documentation servie directement par Uvicorn, sans le préfixe de chemin dans l'URL, cela ne fonctionne pas, car elle s'attend à être accédée via le proxy. +La manière « officielle » d'accéder à l'application serait via le proxy avec le préfixe de chemin que nous avons défini. Donc, comme on s'y attend, si vous essayez l'interface de documentation servie directement par le serveur, sans le préfixe de chemin dans l'URL, cela ne fonctionne pas, car elle s'attend à être accédée via le proxy. Vous pouvez le vérifier sur [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) : @@ -394,11 +365,11 @@ Ceci est un cas d'utilisation plus avancé. N'hésitez pas à l'ignorer. Par défaut, **FastAPI** créera un `server` dans le schéma OpenAPI avec l'URL correspondant au `root_path`. -Mais vous pouvez aussi fournir d'autres `servers` alternatifs, par exemple si vous voulez que la même interface de documents interagisse avec un environnement de staging et un environnement de production. +Mais vous pouvez aussi fournir d'autres `servers` alternatifs, par exemple si vous voulez que *la même* interface de documents interagisse avec un environnement de staging et un environnement de production. Si vous passez une liste personnalisée de `servers` et qu'il y a un `root_path` (parce que votre API vit derrière un proxy), **FastAPI** insérera un « server » avec ce `root_path` au début de la liste. -Par exemple : +Par exemple, en utilisant la même configuration de serveur `fastapi run --root-path /api/v1` : {* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} @@ -451,11 +422,11 @@ Si vous ne spécifiez pas le paramètre `servers` et que `root_path` est égal /// -### Désactiver le serveur automatique issu de `root_path` { #disable-automatic-server-from-root-path } +### Désactivez le serveur automatique issu de `root_path` { #disable-automatic-server-from-root-path } Si vous ne voulez pas que **FastAPI** inclue un serveur automatique utilisant le `root_path`, vous pouvez utiliser le paramètre `root_path_in_servers=False` : -{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[8] *} et il ne l'inclura alors pas dans le schéma OpenAPI. diff --git a/docs/fr/docs/advanced/security/http-basic-auth.md b/docs/fr/docs/advanced/security/http-basic-auth.md index 97e9df6ce5..7f936f121a 100644 --- a/docs/fr/docs/advanced/security/http-basic-auth.md +++ b/docs/fr/docs/advanced/security/http-basic-auth.md @@ -15,8 +15,8 @@ Ensuite, lorsque vous saisissez ce nom d'utilisateur et ce mot de passe, le navi ## Authentification HTTP Basic simple { #simple-http-basic-auth } - Importer `HTTPBasic` et `HTTPBasicCredentials`. -- Créer un « schéma de sécurité » en utilisant `HTTPBasic`. -- Utiliser ce `security` avec une dépendance dans votre chemin d'accès. +- Créer un « schéma `security` » en utilisant `HTTPBasic`. +- Utiliser ce `security` avec une dépendance dans votre *chemin d'accès*. - Cela renvoie un objet de type `HTTPBasicCredentials` : - Il contient le `username` et le `password` envoyés. @@ -38,14 +38,16 @@ Pour cela, utilisez le module standard Python [`secrets`](https://docs.python.or Pour gérer cela, nous convertissons d'abord `username` et `password` en `bytes` en les encodant en UTF-8. -Nous pouvons ensuite utiliser `secrets.compare_digest()` pour vérifier que `credentials.username` est « stanleyjobson » et que `credentials.password` est « swordfish ». +Nous pouvons ensuite utiliser `secrets.compare_digest()` pour vérifier que `credentials.username` est `"stanleyjobson"` et que `credentials.password` est `"swordfish"`. {* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} -Cela serait équivalent à : +Cela serait similaire à : ```Python -if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): +if not (credentials.username == "stanleyjobson") or not ( + credentials.password == "swordfish" +): # Renvoyer une erreur ... ``` @@ -82,7 +84,7 @@ Python devra comparer tout `stanleyjobso` dans `stanleyjobsox` et `stanleyjobson #### Le temps de réponse aide les attaquants { #the-time-to-answer-helps-the-attackers } -À ce stade, en remarquant que le serveur a mis quelques microsecondes de plus à envoyer la réponse « Nom d'utilisateur ou mot de passe incorrect », les attaquants sauront qu'ils ont trouvé quelque chose de juste : certaines des premières lettres étaient correctes. +À ce stade, en remarquant que le serveur a mis quelques microsecondes de plus à envoyer la réponse « Nom d'utilisateur ou mot de passe incorrect », les attaquants sauront qu'ils ont trouvé _quelque chose_ de juste : certaines des premières lettres étaient correctes. Ils peuvent alors réessayer en sachant que c'est probablement quelque chose de plus proche de `stanleyjobsox` que de `johndoe`. diff --git a/docs/fr/docs/advanced/templates.md b/docs/fr/docs/advanced/templates.md index 59332d6cfa..6f259c2762 100644 --- a/docs/fr/docs/advanced/templates.md +++ b/docs/fr/docs/advanced/templates.md @@ -1,3 +1,7 @@ +--- +render_macros: false +--- + # Templates { #templates } Vous pouvez utiliser n'importe quel moteur de templates avec **FastAPI**. @@ -63,14 +67,10 @@ Vous pouvez ensuite écrire un template dans `templates/item.html`, par exemple Dans le HTML qui contient : -{% raw %} - ```jinja Item ID: {{ id }} ``` -{% endraw %} - ... il affichera l’`id` récupéré à partir du `dict` « context » que vous avez passé : ```Python @@ -89,22 +89,48 @@ Vous pouvez aussi utiliser `url_for()` dans le template ; elle prend en paramèt Ainsi, la section suivante : -{% raw %} - ```jinja ``` -{% endraw %} - ... générera un lien vers la même URL que celle gérée par la *fonction de chemin d'accès* `read_item(id=id)`. -Par exemple, avec un ID de `42`, cela rendrait : +`url_for()` renvoie une URL absolue, comprenant le schéma et l'hôte, basée sur la requête actuelle. + +Par exemple, si votre application est servie à l'adresse `https://example.com`, avec un ID de `42`, cela rendrait : + +```html + +``` + +### Chemins d'URL dans les templates { #url-paths-in-templates } + +Pour les liens vers le même site, vous pouvez utiliser l'attribut `.path` pour obtenir uniquement le chemin de l'URL, par exemple, dans `templates/item_path.html` : + +```jinja hl_lines="4 7" +{!../../docs_src/templates/templates/item_path.html!} +``` + +Passez le nom du template à `TemplateResponse` : + +{* ../../docs_src/templates/tutorial002_py310.py ln[14:18] hl[17] *} + +Avec le même exemple, le lien vers l'élément donnerait : ```html ``` +Le `/` initial rend ce chemin relatif à la racine du site actuel. + +L'attribut `.path` exclut le schéma, l'hôte, les paramètres de requête et le fragment. Utilisez l'URL complète pour les liens vers un autre hôte. + +/// tip | Astuce + +Si votre application est derrière un proxy, configurez les en-têtes transférés et `root_path` comme décrit dans [Derrière un proxy](behind-a-proxy.md). + +/// + ## Templates et fichiers statiques { #templates-and-static-files } Vous pouvez aussi utiliser `url_for()` dans le template, par exemple avec les `StaticFiles` que vous avez montés avec `name="static"`. @@ -123,4 +149,4 @@ Et comme vous utilisez `StaticFiles`, ce fichier CSS est servi automatiquement p ## En savoir plus { #more-details } -Pour plus de détails, y compris sur la façon de tester des templates, consultez [la documentation de Starlette sur les templates](https://starlette.dev/templates/). +Pour plus de détails, y compris sur la façon de tester des templates, consultez [les documents de Starlette sur les templates](https://starlette.dev/templates/). diff --git a/docs/fr/docs/async.md b/docs/fr/docs/async.md index ccd1760725..92230cad13 100644 --- a/docs/fr/docs/async.md +++ b/docs/fr/docs/async.md @@ -15,7 +15,7 @@ results = await some_library() Alors, déclarez vos *fonctions de chemin d'accès* avec `async def` comme ceci : ```Python hl_lines="2" -@app.get('/') +@app.get("/") async def read_results(): results = await some_library() return results @@ -32,7 +32,7 @@ Vous pouvez uniquement utiliser `await` dans les fonctions créées avec `async Si vous utilisez une bibliothèque externe qui communique avec quelque chose (une base de données, une API, le système de fichiers, etc.) et qui ne supporte pas l'utilisation d'`await` (ce qui est actuellement le cas pour la majorité des bibliothèques de base de données), alors déclarez vos *fonctions de chemin d'accès* normalement, avec le classique `def`, comme ceci : ```Python hl_lines="2" -@app.get('/') +@app.get("/") def results(): results = some_library() return results @@ -189,7 +189,7 @@ Vous attendez, debout devant le comptoir 🕙, afin que personne d'autre ne pren Vous et votre crush étant occupés à ne laisser personne passer devant vous et prendre vos burgers au moment où ils arriveront, vous ne pouvez pas prêter attention à votre crush. 😞 -C'est du travail « synchrone », vous être « synchronisés » avec le caissier/cuisinier 👨‍🍳. Vous devez attendre 🕙 et être présent au moment exact où le caissier/cuisinier 👨‍🍳 finira les burgers et vous les donnera, sinon quelqu'un d'autre risque de vous les prendre. +C'est du travail « synchrone », vous êtes « synchronisés » avec le caissier/cuisinier 👨‍🍳. Vous devez attendre 🕙 et être présent au moment exact où le caissier/cuisinier 👨‍🍳 finira les burgers et vous les donnera, sinon quelqu'un d'autre risque de vous les prendre. @@ -343,7 +343,7 @@ burgers = get_burgers(2) Donc, si vous utilisez une bibliothèque qui vous indique que vous pouvez l'appeler avec `await`, vous devez créer les *fonctions de chemin d'accès* qui l'utilisent avec `async def`, comme dans : ```Python hl_lines="2-3" -@app.get('/burgers') +@app.get("/burgers") async def read_burgers(): burgers = await get_burgers(2) return burgers @@ -361,7 +361,7 @@ Si vous utilisez **FastAPI**, pas besoin de vous en inquiéter, car cette « pre Mais si vous souhaitez utiliser `async` / `await` sans FastAPI, vous pouvez également le faire. -### Écrire votre propre code async { #write-your-own-async-code } +### Écrivez votre propre code async { #write-your-own-async-code } Starlette (et **FastAPI**) s’appuie sur [AnyIO](https://anyio.readthedocs.io/en/stable/), ce qui le rend compatible à la fois avec la bibliothèque standard [asyncio](https://docs.python.org/3/library/asyncio-task.html) de Python et avec [Trio](https://trio.readthedocs.io/en/stable/). diff --git a/docs/fr/docs/features.md b/docs/fr/docs/features.md index f63783b78c..5321e64018 100644 --- a/docs/fr/docs/features.md +++ b/docs/fr/docs/features.md @@ -36,6 +36,7 @@ from datetime import date from pydantic import BaseModel + # Déclarez une variable comme étant une str # et profitez de l'aide de l'éditeur dans cette fonction def main(user_id: str): @@ -99,7 +100,7 @@ Fini de taper des noms de clés erronés, de faire des allers-retours entre les Des **valeurs par défaut** sensées pour tout, avec des configurations optionnelles partout. Tous les paramètres peuvent être ajustés finement pour faire ce dont vous avez besoin et définir l'API dont vous avez besoin. -Mais par défaut, tout **« just works »**. +Mais par défaut, tout **« fonctionne tout simplement »**. ### Validation { #validation } diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 352568afec..e43e2d7e9a 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -213,7 +213,7 @@ def read_item(item_id: int, q: str | None = None): ```
-Ou utilisez async def... +Ou utilisez async def ... Si votre code utilise `async` / `await`, utilisez `async def` : @@ -235,7 +235,7 @@ async def read_item(item_id: int, q: str | None = None): **Remarque** : -Si vous ne savez pas, consultez la section « Vous êtes pressés ? » à propos de [`async` et `await` dans les documents](https://fastapi.tiangolo.com/fr/async/#in-a-hurry). +Si vous ne savez pas, consultez la section _« Vous êtes pressés ? »_ à propos de [`async` et `await` dans les documents](https://fastapi.tiangolo.com/fr/async/#in-a-hurry).
@@ -271,13 +271,13 @@ INFO: Application startup complete.
-À propos de la commande fastapi dev... +À propos de la commande fastapi dev ... La commande `fastapi dev` lit automatiquement votre fichier `main.py`, détecte l'application **FastAPI** qu'il contient et lance un serveur avec [Uvicorn](https://uvicorn.dev). Par défaut, `fastapi dev` démarre avec le rechargement automatique activé pour le développement local. -Vous pouvez en savoir plus dans la [documentation de la CLI FastAPI](https://fastapi.tiangolo.com/fr/fastapi-cli/). +Vous pouvez en savoir plus dans les [documents de la CLI FastAPI](https://fastapi.tiangolo.com/fr/fastapi-cli/).
@@ -544,9 +544,9 @@ Utilisées par Pydantic : Utilisées par Starlette : -* [`httpx`](https://www.python-httpx.org) - Obligatoire si vous souhaitez utiliser le `TestClient`. +* [`httpx2`](https://pydantic.dev/docs/httpx2/) (ou `httpx`) - Utilisé par le `TestClient`. * [`jinja2`](https://jinja.palletsprojects.com) - Obligatoire si vous souhaitez utiliser la configuration de template par défaut. -* [`python-multipart`](https://github.com/Kludex/python-multipart) - Obligatoire si vous souhaitez prendre en charge l’« parsing » de formulaires avec `request.form()`. +* [`python-multipart`](https://github.com/Kludex/python-multipart) - Obligatoire si vous souhaitez prendre en charge le « parsing » de formulaires avec `request.form()`. Utilisées par FastAPI : diff --git a/docs/fr/docs/tutorial/bigger-applications.md b/docs/fr/docs/tutorial/bigger-applications.md index afe224dea6..1ff75338b1 100644 --- a/docs/fr/docs/tutorial/bigger-applications.md +++ b/docs/fr/docs/tutorial/bigger-applications.md @@ -95,7 +95,7 @@ Utilisez-le de la même manière que vous utiliseriez la classe `FastAPI` : {* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} -Vous pouvez considérer `APIRouter` comme une « mini `FastAPI` ». +Vous pouvez considérer `APIRouter` comme une classe « mini `FastAPI` ». Toutes les mêmes options sont prises en charge. @@ -155,8 +155,7 @@ Comme le chemin de chaque *chemin d'accès* doit commencer par `/`, comme dans : ```Python hl_lines="1" @router.get("/{item_id}") -async def read_item(item_id: str): - ... +async def read_item(item_id: str): ... ``` ... le préfixe ne doit pas inclure un `/` final. @@ -186,7 +185,7 @@ Le résultat final est que les chemins d'item sont désormais : * Tous ces *chemins d'accès* auront la liste des `dependencies` évaluées/exécutées avant eux. * Si vous déclarez également des dépendances dans un *chemin d'accès* spécifique, **elles seront aussi exécutées**. * Les dépendances du routeur sont exécutées en premier, puis les [`dependencies` dans le décorateur](dependencies/dependencies-in-path-operation-decorators.md), puis les dépendances des paramètres normaux. - * Vous pouvez également ajouter des [`Security` dependencies avec des `scopes`](../advanced/security/oauth2-scopes.md). + * Vous pouvez également ajouter des [dépendances `Security` avec des `scopes`](../advanced/security/oauth2-scopes.md). /// tip | Astuce @@ -226,8 +225,8 @@ from .dependencies import get_token_header signifierait : -* En partant du même package dans lequel vit ce module (le fichier `app/routers/items.py`) (le répertoire `app/routers/`)... -* trouver le module `dependencies` (un fichier imaginaire `app/routers/dependencies.py`)... +* En partant du même package dans lequel vit ce module (le fichier `app/routers/items.py`) (le répertoire `app/routers/`) ... +* trouver le module `dependencies` (un fichier imaginaire `app/routers/dependencies.py`) ... * et en importer la fonction `get_token_header`. Mais ce fichier n'existe pas, nos dépendances sont dans un fichier `app/dependencies.py`. @@ -246,9 +245,9 @@ from ..dependencies import get_token_header veulent dire : -* En partant du même package dans lequel vit ce module (le fichier `app/routers/items.py`) (le répertoire `app/routers/`)... -* aller au package parent (le répertoire `app/`)... -* et là, trouver le module `dependencies` (le fichier `app/dependencies.py`)... +* En partant du même package dans lequel vit ce module (le fichier `app/routers/items.py`) (le répertoire `app/routers/`) ... +* aller au package parent (le répertoire `app/`) ... +* et là, trouver le module `dependencies` (le fichier `app/dependencies.py`) ... * et en importer la fonction `get_token_header`. Cela fonctionne correctement ! 🎉 @@ -263,10 +262,10 @@ from ...dependencies import get_token_header cela voudrait dire : -* En partant du même package dans lequel vit ce module (le fichier `app/routers/items.py`) (le répertoire `app/routers/`)... -* aller au package parent (le répertoire `app/`)... -* puis aller au parent de ce package (il n'y a pas de package parent, `app` est le niveau supérieur 😱)... -* et là, trouver le module `dependencies` (le fichier `app/dependencies.py`)... +* En partant du même package dans lequel vit ce module (le fichier `app/routers/items.py`) (le répertoire `app/routers/`) ... +* aller au package parent (le répertoire `app/`) ... +* puis aller au parent de ce package (il n'y a pas de package parent, `app` est le niveau supérieur 😱) ... +* et là, trouver le module `dependencies` (le fichier `app/dependencies.py`) ... * et en importer la fonction `get_token_header`. Cela ferait référence à un package au-dessus de `app/`, avec son propre fichier `__init__.py`, etc. Mais nous n'avons pas cela. Donc, cela lèverait une erreur dans notre exemple. 🚨 @@ -325,9 +324,9 @@ from .routers import items, users signifie : -* En partant du même package dans lequel vit ce module (le fichier `app/main.py`) (le répertoire `app/`)... -* chercher le sous-package `routers` (le répertoire `app/routers/`)... -* et en importer le sous-module `items` (le fichier `app/routers/items.py`) et `users` (le fichier `app/routers/users.py`)... +* En partant du même package dans lequel vit ce module (le fichier `app/main.py`) (le répertoire `app/`) ... +* chercher le sous-package `routers` (le répertoire `app/routers/`) ... +* et en importer le sous-module `items` (le fichier `app/routers/items.py`) et `users` (le fichier `app/routers/users.py`) ... Le module `items` aura une variable `router` (`items.router`). C'est celle que nous avons créée dans le fichier `app/routers/items.py`, c'est un objet `APIRouter`. @@ -518,7 +517,7 @@ Vous verrez les documents d'API automatiques, incluant les chemins de tous les s ## Inclure le même routeur plusieurs fois avec des `prefix` différents { #include-the-same-router-multiple-times-with-different-prefix } -Vous pouvez aussi utiliser `.include_router()` plusieurs fois avec le même routeur en utilisant des préfixes différents. +Vous pouvez aussi utiliser `.include_router()` plusieurs fois avec le *même* routeur en utilisant des préfixes différents. Cela peut être utile, par exemple, pour exposer la même API sous des préfixes différents, p. ex. `/api/v1` et `/api/latest`. diff --git a/docs/fr/docs/tutorial/body-fields.md b/docs/fr/docs/tutorial/body-fields.md index 9830292c90..f1104b6ee8 100644 --- a/docs/fr/docs/tutorial/body-fields.md +++ b/docs/fr/docs/tutorial/body-fields.md @@ -1,6 +1,6 @@ # Corps - Champs { #body-fields } -De la même manière que vous pouvez déclarer des validations supplémentaires et des métadonnées dans les paramètres d'une fonction de chemin d'accès avec `Query`, `Path` et `Body`, vous pouvez déclarer des validations et des métadonnées à l'intérieur des modèles Pydantic en utilisant `Field` de Pydantic. +De la même manière que vous pouvez déclarer des validations supplémentaires et des métadonnées dans les paramètres d'une *fonction de chemin d'accès* avec `Query`, `Path` et `Body`, vous pouvez déclarer des validations et des métadonnées à l'intérieur des modèles Pydantic en utilisant `Field` de Pydantic. ## Importer `Field` { #import-field } @@ -37,19 +37,19 @@ Rappelez-vous que lorsque vous importez `Query`, `Path` et d'autres depuis `fast /// tip | Astuce -Remarquez comment chaque attribut de modèle avec un type, une valeur par défaut et `Field` a la même structure qu'un paramètre de fonction de chemin d'accès, avec `Field` au lieu de `Path`, `Query` et `Body`. +Remarquez comment chaque attribut de modèle avec un type, une valeur par défaut et `Field` a la même structure qu'un paramètre de *fonction de chemin d'accès*, avec `Field` au lieu de `Path`, `Query` et `Body`. /// ## Ajouter des informations supplémentaires { #add-extra-information } -Vous pouvez déclarer des informations supplémentaires dans `Field`, `Query`, `Body`, etc. Elles seront incluses dans le JSON Schema généré. +Vous pouvez déclarer des informations supplémentaires avec `json_schema_extra` dans `Field`, `Query`, `Body`, etc. Elles seront incluses dans le JSON Schema généré. Vous en apprendrez davantage sur l'ajout d'informations supplémentaires plus loin dans les documents, lorsque vous apprendrez à déclarer des exemples. /// warning | Alertes -Les clés supplémentaires passées à `Field` seront également présentes dans le schéma OpenAPI résultant pour votre application. +Les clés supplémentaires passées dans `json_schema_extra` seront également présentes dans le schéma OpenAPI résultant pour votre application. Comme ces clés ne font pas nécessairement partie de la spécification OpenAPI, certains outils OpenAPI, par exemple [le validateur OpenAPI](https://validator.swagger.io/), peuvent ne pas fonctionner avec votre schéma généré. /// @@ -58,4 +58,4 @@ Comme ces clés ne font pas nécessairement partie de la spécification OpenAPI, Vous pouvez utiliser `Field` de Pydantic pour déclarer des validations supplémentaires et des métadonnées pour les attributs de modèle. -Vous pouvez également utiliser des arguments nommés supplémentaires pour transmettre des métadonnées JSON Schema additionnelles. +Vous pouvez également utiliser `json_schema_extra` pour transmettre des métadonnées JSON Schema additionnelles. diff --git a/docs/fr/docs/tutorial/cookie-param-models.md b/docs/fr/docs/tutorial/cookie-param-models.md index 2b8edbab7e..9ace15287a 100644 --- a/docs/fr/docs/tutorial/cookie-param-models.md +++ b/docs/fr/docs/tutorial/cookie-param-models.md @@ -24,9 +24,9 @@ Déclarez les paramètres de **cookie** dont vous avez besoin dans un **modèle **FastAPI** va **extraire** les données pour **chaque champ** à partir des **cookies** reçus dans la requête et vous fournir le modèle Pydantic que vous avez défini. -## Consulter la documentation { #check-the-docs } +## Consultez les documents { #check-the-docs } -Vous pouvez voir les cookies définis dans l'interface de la documentation à `/docs` : +Vous pouvez voir les cookies définis dans l'interface des documents à `/docs` :
@@ -36,9 +36,9 @@ Vous pouvez voir les cookies définis dans l'interface de la documentation à `/ Gardez à l'esprit que, comme les **navigateurs gèrent les cookies** de manière particulière et en arrière-plan, ils **n'autorisent pas** facilement **JavaScript** à y accéder. -Si vous allez dans **l'interface de la documentation de l'API** à `/docs`, vous pourrez voir la **documentation** des cookies pour vos *chemins d'accès*. +Si vous allez dans **l'interface des documents de l'API** à `/docs`, vous pourrez voir la **documentation** des cookies pour vos *chemins d'accès*. -Mais même si vous **remplissez les données** et cliquez sur « Execute », comme l'interface de la documentation fonctionne avec **JavaScript**, les cookies ne seront pas envoyés et vous verrez un **message d'erreur** comme si vous n'aviez saisi aucune valeur. +Mais même si vous **remplissez les données** et cliquez sur « Execute », comme l'interface des documents fonctionne avec **JavaScript**, les cookies ne seront pas envoyés et vous verrez un **message d'erreur** comme si vous n'aviez saisi aucune valeur. /// @@ -54,9 +54,9 @@ Vous pouvez utiliser la configuration du modèle de Pydantic pour `forbid` tout Si un client tente d'envoyer des **cookies supplémentaires**, il recevra une **réponse d'erreur**. -Pauvres bannières de cookies, avec tous leurs efforts pour obtenir votre consentement pour que l'API pour le rejeter. 🍪 +Pauvres bannières de cookies, avec tous leurs efforts pour obtenir votre consentement pour que l'API le rejette. 🍪 -Par exemple, si le client tente d'envoyer un cookie `santa_tracker` avec la valeur `good-list-please`, il recevra une **réponse d'erreur** lui indiquant que le `santa_tracker` le cookie n'est pas autorisé : +Par exemple, si le client tente d'envoyer un cookie `santa_tracker` avec la valeur `good-list-please`, il recevra une **réponse d'erreur** lui indiquant que le cookie `santa_tracker` n'est pas autorisé : ```json { @@ -71,6 +71,22 @@ Par exemple, si le client tente d'envoyer un cookie `santa_tracker` avec la vale } ``` +## Combiner des modèles de paramètres { #combine-parameter-models } + +Vous pouvez combiner plusieurs modèles de paramètres de cookies avec des paramètres de cookies individuels et des dépendances. Chaque modèle est extrait et validé indépendamment, comme expliqué pour les [modèles de paramètres de requête](query-param-models.md#combine-parameter-models). + +La configuration `extra` de chaque modèle s'applique à tous les paramètres de cookies, y compris ceux déclarés dans d'autres modèles ou dépendances. Avec `extra="forbid"`, tout cookie en dehors de ce modèle est rejeté. Avec `extra="allow"`, ces cookies sont inclus comme champs supplémentaires du modèle. + +## Modèles de paramètres de cookies optionnels { #optional-cookie-parameter-models } + +Déclarez un modèle de paramètres de cookies avec `| None` et une valeur par défaut de `None` pour rendre le groupe optionnel. + +{* ../../docs_src/cookie_param_models/tutorial003_an_py310.py hl[15] *} + +Si ni `theme` ni `locale` ne sont envoyés, `preferences` vaut `None`. Si l'un des deux est envoyé, FastAPI valide le modèle et exige les deux champs. + +Les mêmes règles concernant les valeurs par défaut, les champs supplémentaires et OpenAPI s'appliquent que pour les [modèles de paramètres de requête optionnels](query-param-models.md#optional-query-parameter-models). + ## Récapitulatif { #summary } Vous pouvez utiliser des **modèles Pydantic** pour déclarer des **cookies** dans **FastAPI**. 😎 diff --git a/docs/fr/docs/tutorial/dependencies/sub-dependencies.md b/docs/fr/docs/tutorial/dependencies/sub-dependencies.md index c1ba81630d..47f31586a7 100644 --- a/docs/fr/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/fr/docs/tutorial/dependencies/sub-dependencies.md @@ -64,8 +64,10 @@ Dans un scénario avancé où vous savez que vous avez besoin que la dépendance //// tab | Python 3.10+ -```Python hl_lines="1" -async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): +```Python hl_lines="2" +async def needy_dependency( + fresh_value: Annotated[str, Depends(get_value, use_cache=False)], +): return {"fresh_value": fresh_value} ``` diff --git a/docs/fr/docs/tutorial/extra-models.md b/docs/fr/docs/tutorial/extra-models.md index 980e929ed5..1d1e169f97 100644 --- a/docs/fr/docs/tutorial/extra-models.md +++ b/docs/fr/docs/tutorial/extra-models.md @@ -54,10 +54,10 @@ nous obtiendrions un `dict` Python contenant : ```Python { - 'username': 'john', - 'password': 'secret', - 'email': 'john.doe@example.com', - 'full_name': None, + "username": "john", + "password": "secret", + "email": "john.doe@example.com", + "full_name": None, } ``` @@ -86,10 +86,10 @@ Ou plus exactement, en utilisant `user_dict` directement, quels que soient ses c ```Python UserInDB( - username = user_dict["username"], - password = user_dict["password"], - email = user_dict["email"], - full_name = user_dict["full_name"], + username=user_dict["username"], + password=user_dict["password"], + email=user_dict["email"], + full_name=user_dict["full_name"], ) ``` @@ -124,11 +124,11 @@ UserInDB(**user_in.model_dump(), hashed_password=hashed_password) ```Python UserInDB( - username = user_dict["username"], - password = user_dict["password"], - email = user_dict["email"], - full_name = user_dict["full_name"], - hashed_password = hashed_password, + username=user_dict["username"], + password=user_dict["password"], + email=user_dict["email"], + full_name=user_dict["full_name"], + hashed_password=hashed_password, ) ``` diff --git a/docs/fr/docs/tutorial/header-param-models.md b/docs/fr/docs/tutorial/header-param-models.md index 8fc1a3d366..d810a1c613 100644 --- a/docs/fr/docs/tutorial/header-param-models.md +++ b/docs/fr/docs/tutorial/header-param-models.md @@ -16,17 +16,17 @@ Déclarez les **paramètres d'en-tête** dont vous avez besoin dans un **modèle {* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} -**FastAPI** extrait les données de **chaque champ** depuis les **en-têtes** de la requête et vous fournit le modèle Pydantic que vous avez défini. +**FastAPI** **extrait** les données de **chaque champ** depuis les **en-têtes** de la requête et vous fournit le modèle Pydantic que vous avez défini. -## Consulter la documentation { #check-the-docs } +## Consultez les documents { #check-the-docs } -Vous pouvez voir les en-têtes requis dans l'interface de la documentation à `/docs` : +Vous pouvez voir les en-têtes requis dans l'interface des documents à `/docs` :
-## Interdire les en-têtes supplémentaires { #forbid-extra-headers } +## Interdisez les en-têtes supplémentaires { #forbid-extra-headers } Dans certains cas d'utilisation particuliers (probablement pas très courants), vous pourriez vouloir **restreindre** les en-têtes que vous souhaitez recevoir. @@ -51,11 +51,11 @@ Par exemple, si le client essaie d'envoyer un en-tête `tool` avec la valeur `pl } ``` -## Désactiver convert_underscores { #disable-convert-underscores } +## Désactivez la conversion des caractères de soulignement { #disable-convert-underscores } Comme pour les paramètres d'en-tête classiques, lorsque vous avez des caractères de soulignement dans les noms de paramètres, ils sont **automatiquement convertis en tirets**. -Par exemple, si vous avez un paramètre d'en-tête `save_data` dans le code, l'en-tête HTTP attendu sera `save-data`, et il apparaîtra ainsi dans la documentation. +Par exemple, si vous avez un paramètre d'en-tête `save_data` dans le code, l'en-tête HTTP attendu sera `save-data`, et il apparaîtra ainsi dans les documents. Si, pour une raison quelconque, vous devez désactiver cette conversion automatique, vous pouvez aussi le faire pour les modèles Pydantic de paramètres d'en-tête. @@ -67,6 +67,26 @@ Avant de définir `convert_underscores` à `False`, gardez à l'esprit que certa /// +## Combinez les modèles de paramètres { #combine-parameter-models } + +Vous pouvez combiner plusieurs modèles de paramètres d'en-tête avec des paramètres d'en-tête individuels et des dépendances. Chaque modèle est extrait et validé indépendamment, comme expliqué pour les [modèles de paramètres de requête](query-param-models.md#combine-parameter-models). + +La configuration `extra` de chaque modèle s'applique à tous les paramètres d'en-tête, y compris ceux déclarés dans d'autres modèles ou dépendances. Avec `extra="forbid"`, tout en-tête extérieur à ce modèle est rejeté. Avec `extra="allow"`, ces en-têtes sont inclus comme champs supplémentaires du modèle. + +Chaque modèle utilise son propre réglage `Header(convert_underscores=...)`, aussi bien lors de la lecture de la requête que lors de la génération d'OpenAPI. Les alias de champs explicites restent des noms d'en-tête littéraux. + +## Modèles de paramètres d'en-tête optionnels { #optional-header-parameter-models } + +Déclarez un modèle de paramètres d'en-tête avec `| None` et une valeur par défaut de `None` pour rendre le groupe optionnel. + +{* ../../docs_src/header_param_models/tutorial004_an_py310.py hl[15] *} + +Si ni `x-client-name` ni `x-client-version` n'est envoyé, `client` vaut `None`. Si l'un des deux est envoyé, FastAPI valide le modèle et exige les deux champs. + +Les mêmes règles concernant les valeurs par défaut, les champs supplémentaires et OpenAPI s'appliquent que pour les [modèles de paramètres de requête optionnels](query-param-models.md#optional-query-parameter-models). + +Les en-têtes tels que `Host` suivent également la configuration `extra` du modèle. Avec `extra="allow"`, ils rendent le modèle présent même si aucun des deux champs déclarés n'est fourni. + ## Résumé { #summary } Vous pouvez utiliser des **modèles Pydantic** pour déclarer des **en-têtes** dans **FastAPI**. 😎 diff --git a/docs/fr/docs/tutorial/path-params-numeric-validations.md b/docs/fr/docs/tutorial/path-params-numeric-validations.md index c308541a1e..dec0e4e3f4 100644 --- a/docs/fr/docs/tutorial/path-params-numeric-validations.md +++ b/docs/fr/docs/tutorial/path-params-numeric-validations.md @@ -28,7 +28,7 @@ Par exemple, pour déclarer une valeur de métadonnée `title` pour le paramètr /// note | Remarque -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. +Un paramètre de chemin est toujours requis car il doit faire partie du chemin de l'URL. Ajouter `None` à son type ne le rend pas optionnel. Un paramètre déclaré avec `Path` ne peut pas avoir de valeur par défaut. /// diff --git a/docs/fr/docs/tutorial/query-param-models.md b/docs/fr/docs/tutorial/query-param-models.md index b9bb1d1378..d9f7c306f6 100644 --- a/docs/fr/docs/tutorial/query-param-models.md +++ b/docs/fr/docs/tutorial/query-param-models.md @@ -1,8 +1,8 @@ # Modèles de paramètres de requête { #query-parameter-models } -Si vous avez un groupe de paramètres de requête liés, vous pouvez créer un modèle Pydantic pour les déclarer. +Si vous avez un groupe de **paramètres de requête** liés, vous pouvez créer un **modèle Pydantic** pour les déclarer. -Cela vous permet de réutiliser le modèle à plusieurs endroits et aussi de déclarer des validations et des métadonnées pour tous les paramètres en une seule fois. 😎 +Cela vous permet de **réutiliser le modèle** à **plusieurs endroits** et aussi de déclarer des validations et des métadonnées pour tous les paramètres en une seule fois. 😎 /// note | Remarque @@ -12,13 +12,13 @@ Pris en charge depuis FastAPI version `0.115.0`. 🤓 ## Déclarer des paramètres de requête avec un modèle Pydantic { #query-parameters-with-a-pydantic-model } -Déclarez les paramètres de requête dont vous avez besoin dans un modèle Pydantic, puis déclarez le paramètre en tant que `Query` : +Déclarez les **paramètres de requête** dont vous avez besoin dans un **modèle Pydantic**, puis déclarez le paramètre en tant que `Query` : {* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} -FastAPI extrait les données pour chaque champ à partir des paramètres de requête de la requête et vous fournit le modèle Pydantic que vous avez défini. +**FastAPI** **extrait** les données pour **chaque champ** à partir des **paramètres de requête** de la requête et vous fournit le modèle Pydantic que vous avez défini. -## Consulter les documents { #check-the-docs } +## Consultez les documents { #check-the-docs } Vous pouvez voir les paramètres de requête dans l'interface des documents à `/docs` : @@ -26,15 +26,15 @@ Vous pouvez voir les paramètres de requête dans l'interface des documents à `
-## Interdire des paramètres de requête supplémentaires { #forbid-extra-query-parameters } +## Interdisez des paramètres de requête supplémentaires { #forbid-extra-query-parameters } -Dans certains cas d'utilisation particuliers (probablement peu courants), vous pouvez vouloir restreindre les paramètres de requête que vous souhaitez recevoir. +Dans certains cas d'utilisation particuliers (probablement peu courants), vous pouvez vouloir **restreindre** les paramètres de requête que vous souhaitez recevoir. Vous pouvez utiliser la configuration du modèle Pydantic pour `forbid` tout champ `extra` : {* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} -Si un client tente d'envoyer des données supplémentaires dans les paramètres de requête, il recevra une réponse d'erreur. +Si un client tente d'envoyer des données **supplémentaires** dans les **paramètres de requête**, il recevra une réponse d'**erreur**. Par exemple, si le client tente d'envoyer un paramètre de requête `tool` avec la valeur `plumbus`, comme : @@ -42,7 +42,7 @@ Par exemple, si le client tente d'envoyer un paramètre de requête `tool` avec https://example.com/items/?limit=10&tool=plumbus ``` -Il recevra une réponse d'erreur lui indiquant que le paramètre de requête `tool` n'est pas autorisé : +Il recevra une réponse d'**erreur** lui indiquant que le paramètre de requête `tool` n'est pas autorisé : ```json { @@ -57,9 +57,45 @@ Il recevra une réponse d'erreur lui indiquant que le paramètre de requête `to } ``` +## Combinez des modèles de paramètres { #combine-parameter-models } + +Vous pouvez déclarer plusieurs modèles de paramètres de requête et les combiner avec des paramètres de requête individuels ou des dépendances. + +{* ../../docs_src/query_param_models/tutorial003_an_py310.py hl[9:15,20:22] *} + +Les paramètres de requête restent au même niveau. + +```http +https://example.com/items/?limit=5&offset=10&tags=red&tags=blue&search=shirt +``` + +Il n'y a pas de clés `pagination` ou `filters` dans la chaîne de requête. Chaque modèle valide les paramètres de requête indépendamment, avec ses propres valeurs par défaut, validateurs de champs et validateurs de modèle. Il en va de même lorsque les modèles ou les paramètres individuels sont déclarés dans des dépendances. + +Si des modèles partagent un nom de paramètre ou un alias, chaque modèle valide ce paramètre de requête indépendamment. Utilisez des noms ou des alias distincts pour des valeurs indépendantes. OpenAPI ne répertorie un paramètre partagé qu'une seule fois, comme pour les paramètres partagés avec des dépendances ; les déclarations partagées doivent donc décrire le même type et les mêmes contraintes. + +La configuration `extra` de chaque modèle s'applique à tous les paramètres de requête, y compris ceux déclarés dans d'autres modèles ou dépendances. Avec `extra="forbid"`, tout paramètre extérieur à ce modèle est rejeté. Avec `extra="allow"`, ces paramètres sont inclus en tant que champs supplémentaires du modèle. + +Cela fonctionne aussi pour les modèles `Header` et `Cookie`. + +## Modèles de paramètres de requête optionnels { #optional-query-parameter-models } + +Déclarez un modèle de paramètres de requête avec `| None` et une valeur par défaut de `None` pour rendre le groupe optionnel. + +{* ../../docs_src/query_param_models/tutorial004_an_py310.py hl[18] *} + +Si ni `start` ni `end` n'est envoyé, `date_range` vaut `None`. Si l'un des deux est envoyé, FastAPI valide le modèle et exige les deux champs. + +L'utilisation de `| None` sans valeur par défaut laisse le paramètre obligatoire. + +Les paramètres supplémentaires suivent la configuration `extra` du modèle. Les paramètres supplémentaires ignorés ne rendent pas le modèle présent. + +OpenAPI répertorie les champs du groupe individuellement et les marque comme optionnels. + +Vous pouvez aussi déclarer des [modèles de paramètres d'en-tête](header-param-models.md#optional-header-parameter-models) et des [modèles de paramètres de cookie](cookie-param-models.md#optional-cookie-parameter-models) optionnels. + ## Résumé { #summary } -Vous pouvez utiliser des modèles Pydantic pour déclarer des paramètres de requête dans FastAPI. 😎 +Vous pouvez utiliser des **modèles Pydantic** pour déclarer des **paramètres de requête** dans **FastAPI**. 😎 /// tip | Astuce diff --git a/docs/fr/docs/tutorial/query-params-str-validations.md b/docs/fr/docs/tutorial/query-params-str-validations.md index 0b36267910..7848289565 100644 --- a/docs/fr/docs/tutorial/query-params-str-validations.md +++ b/docs/fr/docs/tutorial/query-params-str-validations.md @@ -219,14 +219,22 @@ Donc, lorsque vous avez besoin de déclarer une valeur comme requise tout en uti {* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} -### Requis, peut valoir `None` { #required-can-be-none } +### Paramètres requis et `None` { #required-parameters-and-none } -Vous pouvez déclarer qu’un paramètre accepte `None`, mais qu’il est tout de même requis. Cela obligerait les clients à envoyer une valeur, même si la valeur est `None`. - -Pour ce faire, vous pouvez déclarer que `None` est un type valide tout en ne déclarant pas de valeur par défaut : +Le type `str | None` autorise `None` comme valeur Python, mais ne rend pas un paramètre de requête optionnel. Sans valeur par défaut, le paramètre reste requis : {* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} +Les valeurs des paramètres de requête arrivent sous forme de chaînes de caractères et n’ont pas de représentation intégrée de `None`. Envoyer `?q=None` ou `?q=null` envoie respectivement les chaînes `"None"` et `"null"`. Envoyer `?q=` envoie une chaîne vide, qui échoue à la validation `min_length=3` dans cet exemple. + +Pour permettre aux clients d’omettre `q` et d’utiliser `None` comme valeur, donnez-lui une valeur par défaut de `None` : + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +Les corps de requête JSON, contrairement aux paramètres de requête, peuvent contenir une valeur `null` explicite. + ## Liste de paramètres de requête / valeurs multiples { #query-parameter-list-multiple-values } Quand vous définissez un paramètre de requête explicitement avec `Query`, vous pouvez aussi déclarer qu’il reçoit une liste de valeurs, autrement dit, qu’il reçoit des valeurs multiples. diff --git a/docs/fr/docs/tutorial/query-params.md b/docs/fr/docs/tutorial/query-params.md index 629e1f91a3..4d1884b523 100644 --- a/docs/fr/docs/tutorial/query-params.md +++ b/docs/fr/docs/tutorial/query-params.md @@ -107,7 +107,13 @@ ou http://127.0.0.1:8000/items/foo?short=yes ``` -ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la première lettre en majuscule, etc.), votre fonction verra le paramètre `short` avec une valeur `bool` à `True`. Sinon la valeur sera à `False`. +ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la première lettre en majuscule, etc.), votre fonction verra le paramètre `short` avec une valeur `bool` à `True`. + +Les valeurs telles que `0`, `false`, `off` et `no` (y compris les variations de casse) sont converties en `False`. + +Si `short` est omis, **FastAPI** utilise sa valeur par défaut, qui est `False` dans cet exemple. + +Une valeur vide (`?short=`) ou une valeur non reconnue (par exemple, `?short=maybe`) produit une erreur de validation `422`. ## Multiples paramètres de chemin et de requête { #multiple-path-and-query-parameters } diff --git a/docs/fr/docs/tutorial/request-form-models.md b/docs/fr/docs/tutorial/request-form-models.md index bfa21b5102..8dcb5eca74 100644 --- a/docs/fr/docs/tutorial/request-form-models.md +++ b/docs/fr/docs/tutorial/request-form-models.md @@ -28,7 +28,9 @@ Vous avez simplement besoin de déclarer un **modèle Pydantic** avec les champs **FastAPI** va **extraire** les données pour **chaque champ** à partir des **données de formulaire** de la requête et vous fournir le modèle Pydantic que vous avez défini. -## Consulter les documents { #check-the-docs } +Pour les [cases à cocher HTML](request-forms.md#boolean-form-fields), déclarez des champs booléens avec une valeur par défaut de `False`. + +## Consultez les documents { #check-the-docs } Vous pouvez le vérifier dans l'interface des documents à `/docs` : @@ -73,6 +75,58 @@ Il recevra une réponse d'erreur lui indiquant que le champ `extra` n'est pas au } ``` +## Combiner des modèles de formulaire { #combine-form-models } + +Vous pouvez combiner plusieurs modèles de formulaire avec des paramètres `Form` individuels. + +{* ../../docs_src/request_form_models/tutorial003_an_py310.py hl[9:14,19:21] *} + +Le client envoie `name`, `tags` et `token` comme champs de formulaire. Chaque modèle valide les champs de formulaire indépendamment. + +La configuration `extra` de chaque modèle s'applique à tous les champs de formulaire, y compris les champs et les fichiers déclarés dans d'autres paramètres ou dépendances. Avec `extra="forbid"`, tout champ extérieur à ce modèle est rejeté. Avec `extra="allow"`, ces champs sont inclus comme données supplémentaires du modèle. + +Si plusieurs déclarations utilisent le même nom de champ de formulaire, chacune valide la valeur de ce champ. Utilisez des types et des contraintes compatibles pour les champs partagés afin que le schéma OpenAPI puisse les décrire de manière cohérente. + +## Modèles de formulaire optionnels { #optional-form-models } + +Déclarez un modèle de formulaire avec `| None` et une valeur par défaut de `None` pour rendre le groupe optionnel. + +{* ../../docs_src/request_form_models/tutorial005_an_py310.py hl[17] *} + +Si ni `name` ni `age` ne sont envoyés, `profile` vaut `None`. Si l'un des deux est envoyé, FastAPI valide le modèle et exige les deux champs. Une valeur vide soumise compte également comme un champ fourni. + +Utiliser `| None` sans valeur par défaut laisse le paramètre obligatoire. + +Les champs supplémentaires suivent la configuration `extra` du modèle. Les champs supplémentaires ignorés ne rendent pas le modèle présent. + +Un modèle optionnel ne contenant que des cases à cocher non cochées est omis. Envoyez une valeur telle que `enabled=false` pour le fournir explicitement. + +## Unions optionnelles de modèles de formulaire { #optional-unions-of-form-models } + +Vous pouvez également utiliser une union optionnelle de modèles. + +{* ../../docs_src/request_form_models/tutorial006_an_py310.py hl[9:16,21] *} + +Si aucun champ de formulaire n'est envoyé, `contact` vaut `None`. Envoyez `kind=person` avec `name`, ou `kind=company` avec `company_name`. Le discriminateur sélectionne le modèle à valider. + +## Combiner des unions de modèles de formulaire { #combine-unions-of-form-models } + +Vous pouvez combiner des unions avec d'autres modèles de formulaire, des paramètres `Form` individuels et des paramètres `File`. Chaque union est validée indépendamment. + +{* ../../docs_src/request_form_models/tutorial007_an_py310.py hl[31:35] *} + +Envoyez tous les champs dans le même formulaire. Par exemple, envoyez `contact_type=person`, `name=Rick`, `notification_type=email`, `email=rick@example.com` et `token=secret`. + +Omettez les champs de notification pour laisser `notification` à `None`. + +## Modèles de formulaire et fichiers { #form-models-and-files } + +Vous pouvez également combiner un modèle de formulaire avec des [paramètres de fichier](request-files.md). + +{* ../../docs_src/request_form_models/tutorial004_an_py310.py hl[14] *} + +Ici, le client envoie le champ `name` et le fichier `avatar` en utilisant `multipart/form-data`. + ## Résumer { #summary } Vous pouvez utiliser des modèles Pydantic pour déclarer des champs de formulaire dans FastAPI. 😎 diff --git a/docs/fr/docs/tutorial/request-forms.md b/docs/fr/docs/tutorial/request-forms.md index 77b056634a..775f91dc81 100644 --- a/docs/fr/docs/tutorial/request-forms.md +++ b/docs/fr/docs/tutorial/request-forms.md @@ -44,6 +44,14 @@ Pour déclarer des corps de formulaire, vous devez utiliser `Form` explicitement /// +## Champs de formulaire booléens { #boolean-form-fields } + +Les navigateurs omettent les cases à cocher non cochées lors de l'envoi des formulaires HTML. Déclarez un paramètre de formulaire booléen avec une valeur par défaut de `False` pour recevoir `False` lorsque la case n'est pas cochée : + +{* ../../docs_src/request_forms/tutorial002_an_py310.py hl[9] *} + +Une case cochée envoie sa valeur, qui est par défaut `"on"`. **FastAPI** accepte `"on"` comme `True`. + ## À propos des « champs de formulaire » { #about-form-fields } La manière dont les formulaires HTML (`
`) envoient les données au serveur utilise normalement un encodage « spécial » pour ces données, différent de JSON. @@ -56,13 +64,15 @@ Les données issues des formulaires sont normalement encodées avec le « type d Mais lorsque le formulaire inclut des fichiers, il est encodé en `multipart/form-data`. Vous lirez la gestion des fichiers dans le chapitre suivant. +Vous pouvez utiliser `Form(media_type="multipart/form-data")` pour décrire un formulaire multipart dans OpenAPI. Le définir sur un seul paramètre suffit lorsque vous combinez des paramètres ou des modèles de formulaire. + Si vous voulez en savoir plus sur ces encodages et les champs de formulaire, consultez les [documents web de la MDN pour `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// /// warning | Alertes -Vous pouvez déclarer plusieurs paramètres `Form` dans un chemin d'accès, mais vous ne pouvez pas aussi déclarer des champs `Body` que vous vous attendez à recevoir en JSON, car la requête aura le corps encodé en `application/x-www-form-urlencoded` au lieu de `application/json`. +Vous pouvez déclarer plusieurs paramètres `Form` dans un *chemin d'accès*, mais vous ne pouvez pas aussi déclarer des champs `Body` que vous vous attendez à recevoir en JSON, car la requête aura le corps encodé en `application/x-www-form-urlencoded` au lieu de `application/json`. Ce n'est pas une limitation de **FastAPI**, cela fait partie du protocole HTTP. diff --git a/docs/fr/docs/tutorial/response-model.md b/docs/fr/docs/tutorial/response-model.md index 3e306a7251..f54d7fa0c1 100644 --- a/docs/fr/docs/tutorial/response-model.md +++ b/docs/fr/docs/tutorial/response-model.md @@ -9,9 +9,9 @@ Vous pouvez utiliser des **annotations de type** de la même manière que pour l FastAPI utilisera ce type de retour pour : * **Valider** les données renvoyées. - * Si les données sont invalides (par exemple, il manque un champ), cela signifie que le code de *votre* application est défectueux, qu'il ne renvoie pas ce qu'il devrait, et un erreur serveur sera renvoyée au lieu de renvoyer des données incorrectes. De cette façon, vous et vos clients pouvez être certains de recevoir les données attendues et avec la structure attendue. + * Si les données sont invalides (par exemple, il manque un champ), cela signifie que le code de *votre* application est défectueux, qu'il ne renvoie pas ce qu'il devrait, et une erreur serveur sera renvoyée au lieu de renvoyer des données incorrectes. De cette façon, vous et vos clients pouvez être certains de recevoir les données attendues et avec la structure attendue. * Ajouter un **JSON Schema** pour la réponse, dans l’OpenAPI du *chemin d'accès*. - * Ceci sera utilisé par la **documentation automatique**. + * Ceci sera utilisé par les **documents automatiques**. * Ceci sera également utilisé par les outils de génération automatique de code client. * **Sérialiser** les données renvoyées en JSON en utilisant Pydantic, qui est écrit en **Rust**, ce qui sera **beaucoup plus rapide**. @@ -166,9 +166,9 @@ FastAPI fait plusieurs choses en interne avec Pydantic pour s'assurer que ces m De cette façon, vous obtenez le meilleur des deux mondes : annotations de type avec **prise en charge par les outils** et **filtrage des données**. -## Le voir dans la documentation { #see-it-in-the-docs } +## Le voir dans les documents { #see-it-in-the-docs } -Dans la documentation automatique, vous pouvez vérifier que le modèle d'entrée et le modèle de sortie auront chacun leur propre JSON Schema : +Dans les documents automatiques, vous pouvez vérifier que le modèle d'entrée et le modèle de sortie auront chacun leur propre JSON Schema : @@ -182,7 +182,7 @@ Il peut y avoir des cas où vous renvoyez quelque chose qui n'est pas un champ P ### Renvoyer directement une Response { #return-a-response-directly } -Le cas le plus courant serait [de renvoyer directement une Response comme expliqué plus loin dans la documentation avancée](../advanced/response-directly.md). +Le cas le plus courant serait [de renvoyer directement une Response comme expliqué plus loin dans les documents avancés](../advanced/response-directly.md). {* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} @@ -266,6 +266,7 @@ comme décrit dans [les documents Pydantic](https://pydantic.dev/docs/validation Mais si vos données ont des valeurs pour les champs du modèle avec des valeurs par défaut, comme l'article avec l'ID `bar` : + ```Python hl_lines="3 5" { "name": "Bar", @@ -274,6 +275,7 @@ Mais si vos données ont des valeurs pour les champs du modèle avec des valeurs "tax": 20.2 } ``` + elles seront incluses dans la réponse. @@ -281,6 +283,7 @@ elles seront incluses dans la réponse. Si les données ont les mêmes valeurs que les valeurs par défaut, comme l'article avec l'ID `baz` : + ```Python hl_lines="3 5-6" { "name": "Baz", @@ -290,6 +293,7 @@ Si les données ont les mêmes valeurs que les valeurs par défaut, comme l'arti "tags": [] } ``` + FastAPI est suffisamment intelligent (en fait, Pydantic l’est) pour comprendre que, même si `description`, `tax` et `tags` ont les mêmes valeurs que les valeurs par défaut, elles ont été définies explicitement (au lieu d'être prises depuis les valeurs par défaut). @@ -315,7 +319,7 @@ Cela peut être utilisé comme un raccourci rapide si vous n'avez qu'un seul mod Mais il est toujours recommandé d'utiliser les idées ci-dessus, en utilisant plusieurs classes, plutôt que ces paramètres. -En effet, le JSON Schema généré dans l’OpenAPI de votre application (et la documentation) restera celui du modèle complet, même si vous utilisez `response_model_include` ou `response_model_exclude` pour omettre certains attributs. +En effet, le JSON Schema généré dans l’OpenAPI de votre application (et les documents) restera celui du modèle complet, même si vous utilisez `response_model_include` ou `response_model_exclude` pour omettre certains attributs. Cela s'applique également à `response_model_by_alias` qui fonctionne de manière similaire. diff --git a/docs/fr/docs/tutorial/security/simple-oauth2.md b/docs/fr/docs/tutorial/security/simple-oauth2.md index 1ee9e61ec8..f624ec9111 100644 --- a/docs/fr/docs/tutorial/security/simple-oauth2.md +++ b/docs/fr/docs/tutorial/security/simple-oauth2.md @@ -136,11 +136,11 @@ Ainsi, il ne pourra pas essayer d'utiliser ces mêmes mots de passe dans un autr ```Python UserInDB( - username = user_dict["username"], - email = user_dict["email"], - full_name = user_dict["full_name"], - disabled = user_dict["disabled"], - hashed_password = user_dict["hashed_password"], + username=user_dict["username"], + email=user_dict["email"], + full_name=user_dict["full_name"], + disabled=user_dict["disabled"], + hashed_password=user_dict["hashed_password"], ) ``` @@ -162,7 +162,7 @@ Pour cet exemple simple, nous allons faire quelque chose de complètement non s /// tip | Astuce -Dans le prochain chapitre, vous verrez une véritable implémentation sécurisée, avec du hachage de mot de passe et des jetons JWT. +Dans le prochain chapitre, vous verrez une véritable implémentation sécurisée, avec du hachage de mot de passe et des jetons JWT. Mais pour l'instant, concentrons‑nous sur les détails spécifiques dont nous avons besoin. @@ -286,4 +286,4 @@ En utilisant ces outils, vous pouvez rendre le système de sécurité compatible Le seul détail manquant est qu'il n'est pas encore réellement « sécurisé ». -Dans le prochain chapitre, vous verrez comment utiliser une bibliothèque de hachage de mot de passe sécurisée et des jetons JWT. +Dans le prochain chapitre, vous verrez comment utiliser une bibliothèque de hachage de mot de passe sécurisée et des jetons JWT.