982 changed files with 65464 additions and 31704 deletions
@ -7,7 +7,8 @@ on: |
|||
- synchronize |
|||
|
|||
env: |
|||
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }} |
|||
# Forks and Dependabot don't have access to secrets |
|||
HAS_SECRETS: ${{ secrets.PRE_COMMIT != '' }} |
|||
|
|||
jobs: |
|||
pre-commit: |
|||
@ -19,7 +20,7 @@ jobs: |
|||
run: echo "$GITHUB_CONTEXT" |
|||
- uses: actions/checkout@v5 |
|||
name: Checkout PR for own repo |
|||
if: env.IS_FORK == 'false' |
|||
if: env.HAS_SECRETS == 'true' |
|||
with: |
|||
# To be able to commit it needs to fetch the head of the branch, not the |
|||
# merge commit |
|||
@ -31,7 +32,7 @@ jobs: |
|||
# pre-commit lite ci needs the default checkout configs to work |
|||
- uses: actions/checkout@v5 |
|||
name: Checkout PR for fork |
|||
if: env.IS_FORK == 'true' |
|||
if: env.HAS_SECRETS == 'false' |
|||
with: |
|||
# To be able to commit it needs the head branch of the PR, the remote one |
|||
ref: ${{ github.event.pull_request.head.sha }} |
|||
@ -39,24 +40,21 @@ jobs: |
|||
- name: Set up Python |
|||
uses: actions/setup-python@v6 |
|||
with: |
|||
python-version: "3.14" |
|||
python-version-file: ".python-version" |
|||
- name: Setup uv |
|||
uses: astral-sh/setup-uv@v7 |
|||
with: |
|||
cache-dependency-glob: | |
|||
requirements**.txt |
|||
pyproject.toml |
|||
uv.lock |
|||
- name: Install Dependencies |
|||
run: | |
|||
uv venv |
|||
uv pip install -r requirements.txt |
|||
run: uv sync --locked --extra all |
|||
- name: Run prek - pre-commit |
|||
id: precommit |
|||
run: uvx prek run --from-ref origin/${GITHUB_BASE_REF} --to-ref HEAD --show-diff-on-failure |
|||
continue-on-error: true |
|||
- name: Commit and push changes |
|||
if: env.IS_FORK == 'false' |
|||
if: env.HAS_SECRETS == 'true' |
|||
run: | |
|||
git config user.name "github-actions[bot]" |
|||
git config user.email "github-actions[bot]@users.noreply.github.com" |
|||
@ -68,7 +66,7 @@ jobs: |
|||
git push |
|||
fi |
|||
- uses: pre-commit-ci/[email protected] |
|||
if: env.IS_FORK == 'true' |
|||
if: env.HAS_SECRETS == 'false' |
|||
with: |
|||
msg: 🎨 Auto format |
|||
- name: Error out on pre-commit errors |
|||
|
|||
@ -15,6 +15,7 @@ jobs: |
|||
- fastapi-slim |
|||
permissions: |
|||
id-token: write |
|||
contents: read |
|||
steps: |
|||
- name: Dump GitHub context |
|||
env: |
|||
@ -24,19 +25,15 @@ jobs: |
|||
- name: Set up Python |
|||
uses: actions/setup-python@v6 |
|||
with: |
|||
python-version: "3.10" |
|||
python-version-file: ".python-version" |
|||
# Issue ref: https://github.com/actions/setup-python/issues/436 |
|||
# cache: "pip" |
|||
# cache-dependency-path: pyproject.toml |
|||
- name: Install build dependencies |
|||
run: pip install build |
|||
- name: Install uv |
|||
uses: astral-sh/setup-uv@v7 |
|||
- name: Build distribution |
|||
run: uv build |
|||
env: |
|||
TIANGOLO_BUILD_PACKAGE: ${{ matrix.package }} |
|||
run: python -m build |
|||
- name: Publish |
|||
uses: pypa/[email protected] |
|||
- name: Dump GitHub context |
|||
env: |
|||
GITHUB_CONTEXT: ${{ toJson(github) }} |
|||
run: echo "$GITHUB_CONTEXT" |
|||
run: uv publish |
|||
|
|||
@ -0,0 +1 @@ |
|||
3.11 |
|||
@ -22,21 +22,13 @@ Hier ist eine allgemeine Idee, wie die Modelle mit ihren Passwortfeldern aussehe |
|||
|
|||
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} |
|||
|
|||
/// info | Info |
|||
### Über `**user_in.model_dump()` { #about-user-in-model-dump } |
|||
|
|||
In Pydantic v1 hieß die Methode `.dict()`, in Pydantic v2 wurde sie <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> (aber weiterhin unterstützt) und in `.model_dump()` umbenannt. |
|||
|
|||
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, aber Sie sollten `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können. |
|||
|
|||
/// |
|||
|
|||
### Über `**user_in.dict()` { #about-user-in-dict } |
|||
|
|||
#### Die `.dict()`-Methode von Pydantic { #pydantics-dict } |
|||
#### Pydantics `.model_dump()` { #pydantics-model-dump } |
|||
|
|||
`user_in` ist ein Pydantic-Modell der Klasse `UserIn`. |
|||
|
|||
Pydantic-Modelle haben eine `.dict()`-Methode, die ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> mit den Daten des Modells zurückgibt. |
|||
Pydantic-Modelle haben eine `.model_dump()`-Methode, die ein <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">`dict`</abbr> mit den Daten des Modells zurückgibt. |
|||
|
|||
Wenn wir also ein Pydantic-Objekt `user_in` erstellen, etwa so: |
|||
|
|||
@ -47,7 +39,7 @@ user_in = UserIn(username="john", password="secret", email="[email protected] |
|||
und dann aufrufen: |
|||
|
|||
```Python |
|||
user_dict = user_in.dict() |
|||
user_dict = user_in.model_dump() |
|||
``` |
|||
|
|||
haben wir jetzt ein `dict` mit den Daten in der Variablen `user_dict` (es ist ein `dict` statt eines Pydantic-Modellobjekts). |
|||
@ -103,20 +95,20 @@ UserInDB( |
|||
|
|||
#### Ein Pydantic-Modell aus dem Inhalt eines anderen { #a-pydantic-model-from-the-contents-of-another } |
|||
|
|||
Da wir im obigen Beispiel `user_dict` von `user_in.dict()` bekommen haben, wäre dieser Code: |
|||
Da wir im obigen Beispiel `user_dict` von `user_in.model_dump()` bekommen haben, wäre dieser Code: |
|||
|
|||
```Python |
|||
user_dict = user_in.dict() |
|||
user_dict = user_in.model_dump() |
|||
UserInDB(**user_dict) |
|||
``` |
|||
|
|||
gleichwertig zu: |
|||
|
|||
```Python |
|||
UserInDB(**user_in.dict()) |
|||
UserInDB(**user_in.model_dump()) |
|||
``` |
|||
|
|||
... weil `user_in.dict()` ein `dict` ist, und dann lassen wir Python es „entpacken“, indem wir es an `UserInDB` mit vorangestelltem `**` übergeben. |
|||
... weil `user_in.model_dump()` ein `dict` ist, und dann lassen wir Python es „entpacken“, indem wir es an `UserInDB` mit vorangestelltem `**` übergeben. |
|||
|
|||
Auf diese Weise erhalten wir ein Pydantic-Modell aus den Daten eines anderen Pydantic-Modells. |
|||
|
|||
@ -125,7 +117,7 @@ Auf diese Weise erhalten wir ein Pydantic-Modell aus den Daten eines anderen Pyd |
|||
Und dann fügen wir das zusätzliche Schlüsselwort-Argument `hashed_password=hashed_password` hinzu, wie in: |
|||
|
|||
```Python |
|||
UserInDB(**user_in.dict(), hashed_password=hashed_password) |
|||
UserInDB(**user_in.model_dump(), hashed_password=hashed_password) |
|||
``` |
|||
|
|||
... was so ist wie: |
|||
@ -180,7 +172,6 @@ Wenn Sie eine <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" |
|||
|
|||
{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} |
|||
|
|||
|
|||
### `Union` in Python 3.10 { #union-in-python-3-10 } |
|||
|
|||
In diesem Beispiel übergeben wir `Union[PlaneItem, CarItem]` als Wert des Arguments `response_model`. |
|||
@ -203,7 +194,6 @@ Dafür verwenden Sie Pythons Standard-`typing.List` (oder nur `list` in Python 3 |
|||
|
|||
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} |
|||
|
|||
|
|||
## Response mit beliebigem `dict` { #response-with-arbitrary-dict } |
|||
|
|||
Sie können auch eine Response deklarieren, die ein beliebiges `dict` zurückgibt, indem Sie nur die Typen der Schlüssel und Werte ohne ein Pydantic-Modell deklarieren. |
|||
@ -214,7 +204,6 @@ In diesem Fall können Sie `typing.Dict` verwenden (oder nur `dict` in Python 3. |
|||
|
|||
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} |
|||
|
|||
|
|||
## Zusammenfassung { #recap } |
|||
|
|||
Verwenden Sie gerne mehrere Pydantic-Modelle und vererben Sie je nach Bedarf. |
|||
|
|||
@ -1,495 +1,495 @@ |
|||
- name: full-stack-fastapi-template |
|||
html_url: https://github.com/fastapi/full-stack-fastapi-template |
|||
stars: 39475 |
|||
stars: 41312 |
|||
owner_login: fastapi |
|||
owner_html_url: https://github.com/fastapi |
|||
- name: Hello-Python |
|||
html_url: https://github.com/mouredev/Hello-Python |
|||
stars: 33090 |
|||
stars: 34206 |
|||
owner_login: mouredev |
|||
owner_html_url: https://github.com/mouredev |
|||
- name: serve |
|||
html_url: https://github.com/jina-ai/serve |
|||
stars: 21798 |
|||
stars: 21832 |
|||
owner_login: jina-ai |
|||
owner_html_url: https://github.com/jina-ai |
|||
- name: HivisionIDPhotos |
|||
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos |
|||
stars: 20258 |
|||
stars: 20661 |
|||
owner_login: Zeyi-Lin |
|||
owner_html_url: https://github.com/Zeyi-Lin |
|||
- name: sqlmodel |
|||
html_url: https://github.com/fastapi/sqlmodel |
|||
stars: 17212 |
|||
stars: 17567 |
|||
owner_login: fastapi |
|||
owner_html_url: https://github.com/fastapi |
|||
- name: Douyin_TikTok_Download_API |
|||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API |
|||
stars: 15145 |
|||
owner_login: Evil0ctal |
|||
owner_html_url: https://github.com/Evil0ctal |
|||
- name: fastapi-best-practices |
|||
html_url: https://github.com/zhanymkanov/fastapi-best-practices |
|||
stars: 14644 |
|||
stars: 16291 |
|||
owner_login: zhanymkanov |
|||
owner_html_url: https://github.com/zhanymkanov |
|||
- name: Douyin_TikTok_Download_API |
|||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API |
|||
stars: 16132 |
|||
owner_login: Evil0ctal |
|||
owner_html_url: https://github.com/Evil0ctal |
|||
- name: SurfSense |
|||
html_url: https://github.com/MODSetter/SurfSense |
|||
stars: 12723 |
|||
owner_login: MODSetter |
|||
owner_html_url: https://github.com/MODSetter |
|||
- name: machine-learning-zoomcamp |
|||
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp |
|||
stars: 12320 |
|||
stars: 12575 |
|||
owner_login: DataTalksClub |
|||
owner_html_url: https://github.com/DataTalksClub |
|||
- name: fastapi_mcp |
|||
html_url: https://github.com/tadata-org/fastapi_mcp |
|||
stars: 11174 |
|||
stars: 11478 |
|||
owner_login: tadata-org |
|||
owner_html_url: https://github.com/tadata-org |
|||
- name: SurfSense |
|||
html_url: https://github.com/MODSetter/SurfSense |
|||
stars: 10858 |
|||
owner_login: MODSetter |
|||
owner_html_url: https://github.com/MODSetter |
|||
- name: awesome-fastapi |
|||
html_url: https://github.com/mjhea0/awesome-fastapi |
|||
stars: 10758 |
|||
stars: 11018 |
|||
owner_login: mjhea0 |
|||
owner_html_url: https://github.com/mjhea0 |
|||
- name: XHS-Downloader |
|||
html_url: https://github.com/JoeanAmier/XHS-Downloader |
|||
stars: 9313 |
|||
stars: 9938 |
|||
owner_login: JoeanAmier |
|||
owner_html_url: https://github.com/JoeanAmier |
|||
- name: FastUI |
|||
html_url: https://github.com/pydantic/FastUI |
|||
stars: 8915 |
|||
owner_login: pydantic |
|||
owner_html_url: https://github.com/pydantic |
|||
- name: polar |
|||
html_url: https://github.com/polarsource/polar |
|||
stars: 8339 |
|||
stars: 9348 |
|||
owner_login: polarsource |
|||
owner_html_url: https://github.com/polarsource |
|||
- name: FastUI |
|||
html_url: https://github.com/pydantic/FastUI |
|||
stars: 8949 |
|||
owner_login: pydantic |
|||
owner_html_url: https://github.com/pydantic |
|||
- name: FileCodeBox |
|||
html_url: https://github.com/vastsa/FileCodeBox |
|||
stars: 7721 |
|||
stars: 8060 |
|||
owner_login: vastsa |
|||
owner_html_url: https://github.com/vastsa |
|||
- name: nonebot2 |
|||
html_url: https://github.com/nonebot/nonebot2 |
|||
stars: 7170 |
|||
stars: 7311 |
|||
owner_login: nonebot |
|||
owner_html_url: https://github.com/nonebot |
|||
- name: hatchet |
|||
html_url: https://github.com/hatchet-dev/hatchet |
|||
stars: 6253 |
|||
stars: 6479 |
|||
owner_login: hatchet-dev |
|||
owner_html_url: https://github.com/hatchet-dev |
|||
- name: fastapi-users |
|||
html_url: https://github.com/fastapi-users/fastapi-users |
|||
stars: 5849 |
|||
stars: 5970 |
|||
owner_login: fastapi-users |
|||
owner_html_url: https://github.com/fastapi-users |
|||
- name: serge |
|||
html_url: https://github.com/serge-chat/serge |
|||
stars: 5756 |
|||
stars: 5751 |
|||
owner_login: serge-chat |
|||
owner_html_url: https://github.com/serge-chat |
|||
- name: strawberry |
|||
html_url: https://github.com/strawberry-graphql/strawberry |
|||
stars: 4569 |
|||
stars: 4598 |
|||
owner_login: strawberry-graphql |
|||
owner_html_url: https://github.com/strawberry-graphql |
|||
- name: chatgpt-web-share |
|||
html_url: https://github.com/chatpire/chatgpt-web-share |
|||
stars: 4294 |
|||
owner_login: chatpire |
|||
owner_html_url: https://github.com/chatpire |
|||
- name: devpush |
|||
html_url: https://github.com/hunvreus/devpush |
|||
stars: 4407 |
|||
owner_login: hunvreus |
|||
owner_html_url: https://github.com/hunvreus |
|||
- name: Kokoro-FastAPI |
|||
html_url: https://github.com/remsky/Kokoro-FastAPI |
|||
stars: 4359 |
|||
owner_login: remsky |
|||
owner_html_url: https://github.com/remsky |
|||
- name: poem |
|||
html_url: https://github.com/poem-web/poem |
|||
stars: 4276 |
|||
stars: 4337 |
|||
owner_login: poem-web |
|||
owner_html_url: https://github.com/poem-web |
|||
- name: chatgpt-web-share |
|||
html_url: https://github.com/chatpire/chatgpt-web-share |
|||
stars: 4279 |
|||
owner_login: chatpire |
|||
owner_html_url: https://github.com/chatpire |
|||
- name: dynaconf |
|||
html_url: https://github.com/dynaconf/dynaconf |
|||
stars: 4202 |
|||
stars: 4244 |
|||
owner_login: dynaconf |
|||
owner_html_url: https://github.com/dynaconf |
|||
- name: Yuxi-Know |
|||
html_url: https://github.com/xerrors/Yuxi-Know |
|||
stars: 4154 |
|||
owner_login: xerrors |
|||
owner_html_url: https://github.com/xerrors |
|||
- name: atrilabs-engine |
|||
html_url: https://github.com/Atri-Labs/atrilabs-engine |
|||
stars: 4093 |
|||
stars: 4086 |
|||
owner_login: Atri-Labs |
|||
owner_html_url: https://github.com/Atri-Labs |
|||
- name: Kokoro-FastAPI |
|||
html_url: https://github.com/remsky/Kokoro-FastAPI |
|||
stars: 4019 |
|||
owner_login: remsky |
|||
owner_html_url: https://github.com/remsky |
|||
- name: logfire |
|||
html_url: https://github.com/pydantic/logfire |
|||
stars: 3805 |
|||
stars: 3975 |
|||
owner_login: pydantic |
|||
owner_html_url: https://github.com/pydantic |
|||
- name: LitServe |
|||
html_url: https://github.com/Lightning-AI/LitServe |
|||
stars: 3719 |
|||
stars: 3797 |
|||
owner_login: Lightning-AI |
|||
owner_html_url: https://github.com/Lightning-AI |
|||
- name: fastapi-admin |
|||
html_url: https://github.com/fastapi-admin/fastapi-admin |
|||
stars: 3632 |
|||
owner_login: fastapi-admin |
|||
owner_html_url: https://github.com/fastapi-admin |
|||
- name: datamodel-code-generator |
|||
html_url: https://github.com/koxudaxi/datamodel-code-generator |
|||
stars: 3609 |
|||
owner_login: koxudaxi |
|||
owner_html_url: https://github.com/koxudaxi |
|||
- name: huma |
|||
html_url: https://github.com/danielgtaylor/huma |
|||
stars: 3603 |
|||
stars: 3785 |
|||
owner_login: danielgtaylor |
|||
owner_html_url: https://github.com/danielgtaylor |
|||
- name: datamodel-code-generator |
|||
html_url: https://github.com/koxudaxi/datamodel-code-generator |
|||
stars: 3731 |
|||
owner_login: koxudaxi |
|||
owner_html_url: https://github.com/koxudaxi |
|||
- name: fastapi-admin |
|||
html_url: https://github.com/fastapi-admin/fastapi-admin |
|||
stars: 3697 |
|||
owner_login: fastapi-admin |
|||
owner_html_url: https://github.com/fastapi-admin |
|||
- name: farfalle |
|||
html_url: https://github.com/rashadphz/farfalle |
|||
stars: 3490 |
|||
stars: 3506 |
|||
owner_login: rashadphz |
|||
owner_html_url: https://github.com/rashadphz |
|||
- name: tracecat |
|||
html_url: https://github.com/TracecatHQ/tracecat |
|||
stars: 3379 |
|||
stars: 3458 |
|||
owner_login: TracecatHQ |
|||
owner_html_url: https://github.com/TracecatHQ |
|||
- name: mcp-context-forge |
|||
html_url: https://github.com/IBM/mcp-context-forge |
|||
stars: 3216 |
|||
owner_login: IBM |
|||
owner_html_url: https://github.com/IBM |
|||
- name: opyrator |
|||
html_url: https://github.com/ml-tooling/opyrator |
|||
stars: 3135 |
|||
stars: 3134 |
|||
owner_login: ml-tooling |
|||
owner_html_url: https://github.com/ml-tooling |
|||
- name: docarray |
|||
html_url: https://github.com/docarray/docarray |
|||
stars: 3114 |
|||
stars: 3111 |
|||
owner_login: docarray |
|||
owner_html_url: https://github.com/docarray |
|||
- name: devpush |
|||
html_url: https://github.com/hunvreus/devpush |
|||
stars: 3097 |
|||
owner_login: hunvreus |
|||
owner_html_url: https://github.com/hunvreus |
|||
- name: fastapi-realworld-example-app |
|||
html_url: https://github.com/nsidnev/fastapi-realworld-example-app |
|||
stars: 3050 |
|||
stars: 3072 |
|||
owner_login: nsidnev |
|||
owner_html_url: https://github.com/nsidnev |
|||
- name: uvicorn-gunicorn-fastapi-docker |
|||
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker |
|||
stars: 2911 |
|||
stars: 2908 |
|||
owner_login: tiangolo |
|||
owner_html_url: https://github.com/tiangolo |
|||
- name: mcp-context-forge |
|||
html_url: https://github.com/IBM/mcp-context-forge |
|||
stars: 2899 |
|||
owner_login: IBM |
|||
owner_html_url: https://github.com/IBM |
|||
- name: best-of-web-python |
|||
html_url: https://github.com/ml-tooling/best-of-web-python |
|||
stars: 2648 |
|||
owner_login: ml-tooling |
|||
owner_html_url: https://github.com/ml-tooling |
|||
- name: FastAPI-template |
|||
html_url: https://github.com/s3rius/FastAPI-template |
|||
stars: 2637 |
|||
stars: 2728 |
|||
owner_login: s3rius |
|||
owner_html_url: https://github.com/s3rius |
|||
- name: best-of-web-python |
|||
html_url: https://github.com/ml-tooling/best-of-web-python |
|||
stars: 2686 |
|||
owner_login: ml-tooling |
|||
owner_html_url: https://github.com/ml-tooling |
|||
- name: YC-Killer |
|||
html_url: https://github.com/sahibzada-allahyar/YC-Killer |
|||
stars: 2599 |
|||
stars: 2648 |
|||
owner_login: sahibzada-allahyar |
|||
owner_html_url: https://github.com/sahibzada-allahyar |
|||
- name: fastapi-react |
|||
html_url: https://github.com/Buuntu/fastapi-react |
|||
stars: 2569 |
|||
owner_login: Buuntu |
|||
owner_html_url: https://github.com/Buuntu |
|||
- name: Yuxi-Know |
|||
html_url: https://github.com/xerrors/Yuxi-Know |
|||
stars: 2563 |
|||
owner_login: xerrors |
|||
owner_html_url: https://github.com/xerrors |
|||
- name: sqladmin |
|||
html_url: https://github.com/aminalaee/sqladmin |
|||
stars: 2558 |
|||
stars: 2637 |
|||
owner_login: aminalaee |
|||
owner_html_url: https://github.com/aminalaee |
|||
- name: fastapi-react |
|||
html_url: https://github.com/Buuntu/fastapi-react |
|||
stars: 2573 |
|||
owner_login: Buuntu |
|||
owner_html_url: https://github.com/Buuntu |
|||
- name: RasaGPT |
|||
html_url: https://github.com/paulpierre/RasaGPT |
|||
stars: 2451 |
|||
stars: 2460 |
|||
owner_login: paulpierre |
|||
owner_html_url: https://github.com/paulpierre |
|||
- name: supabase-py |
|||
html_url: https://github.com/supabase/supabase-py |
|||
stars: 2344 |
|||
stars: 2428 |
|||
owner_login: supabase |
|||
owner_html_url: https://github.com/supabase |
|||
- name: 30-Days-of-Python |
|||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python |
|||
stars: 2347 |
|||
owner_login: codingforentrepreneurs |
|||
owner_html_url: https://github.com/codingforentrepreneurs |
|||
- name: nextpy |
|||
html_url: https://github.com/dot-agent/nextpy |
|||
stars: 2335 |
|||
stars: 2337 |
|||
owner_login: dot-agent |
|||
owner_html_url: https://github.com/dot-agent |
|||
- name: fastapi-utils |
|||
html_url: https://github.com/fastapiutils/fastapi-utils |
|||
stars: 2291 |
|||
stars: 2299 |
|||
owner_login: fastapiutils |
|||
owner_html_url: https://github.com/fastapiutils |
|||
- name: 30-Days-of-Python |
|||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python |
|||
stars: 2220 |
|||
owner_login: codingforentrepreneurs |
|||
owner_html_url: https://github.com/codingforentrepreneurs |
|||
- name: langserve |
|||
html_url: https://github.com/langchain-ai/langserve |
|||
stars: 2215 |
|||
stars: 2255 |
|||
owner_login: langchain-ai |
|||
owner_html_url: https://github.com/langchain-ai |
|||
- name: NoteDiscovery |
|||
html_url: https://github.com/gamosoft/NoteDiscovery |
|||
stars: 2182 |
|||
owner_login: gamosoft |
|||
owner_html_url: https://github.com/gamosoft |
|||
- name: solara |
|||
html_url: https://github.com/widgetti/solara |
|||
stars: 2122 |
|||
stars: 2154 |
|||
owner_login: widgetti |
|||
owner_html_url: https://github.com/widgetti |
|||
- name: mangum |
|||
html_url: https://github.com/Kludex/mangum |
|||
stars: 2029 |
|||
stars: 2071 |
|||
owner_login: Kludex |
|||
owner_html_url: https://github.com/Kludex |
|||
- name: fastapi_best_architecture |
|||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture |
|||
stars: 2036 |
|||
owner_login: fastapi-practices |
|||
owner_html_url: https://github.com/fastapi-practices |
|||
- name: vue-fastapi-admin |
|||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin |
|||
stars: 1983 |
|||
owner_login: mizhexiaoxiao |
|||
owner_html_url: https://github.com/mizhexiaoxiao |
|||
- name: agentkit |
|||
html_url: https://github.com/BCG-X-Official/agentkit |
|||
stars: 1912 |
|||
stars: 1941 |
|||
owner_login: BCG-X-Official |
|||
owner_html_url: https://github.com/BCG-X-Official |
|||
- name: manage-fastapi |
|||
html_url: https://github.com/ycd/manage-fastapi |
|||
stars: 1885 |
|||
owner_login: ycd |
|||
owner_html_url: https://github.com/ycd |
|||
- name: fastapi-langgraph-agent-production-ready-template |
|||
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template |
|||
stars: 1920 |
|||
owner_login: wassim249 |
|||
owner_html_url: https://github.com/wassim249 |
|||
- name: openapi-python-client |
|||
html_url: https://github.com/openapi-generators/openapi-python-client |
|||
stars: 1862 |
|||
stars: 1900 |
|||
owner_login: openapi-generators |
|||
owner_html_url: https://github.com/openapi-generators |
|||
- name: piccolo |
|||
html_url: https://github.com/piccolo-orm/piccolo |
|||
stars: 1836 |
|||
owner_login: piccolo-orm |
|||
owner_html_url: https://github.com/piccolo-orm |
|||
- name: vue-fastapi-admin |
|||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin |
|||
stars: 1831 |
|||
owner_login: mizhexiaoxiao |
|||
owner_html_url: https://github.com/mizhexiaoxiao |
|||
- name: python-week-2022 |
|||
html_url: https://github.com/rochacbruno/python-week-2022 |
|||
stars: 1817 |
|||
owner_login: rochacbruno |
|||
owner_html_url: https://github.com/rochacbruno |
|||
- name: manage-fastapi |
|||
html_url: https://github.com/ycd/manage-fastapi |
|||
stars: 1894 |
|||
owner_login: ycd |
|||
owner_html_url: https://github.com/ycd |
|||
- name: slowapi |
|||
html_url: https://github.com/laurentS/slowapi |
|||
stars: 1798 |
|||
stars: 1891 |
|||
owner_login: laurentS |
|||
owner_html_url: https://github.com/laurentS |
|||
- name: piccolo |
|||
html_url: https://github.com/piccolo-orm/piccolo |
|||
stars: 1854 |
|||
owner_login: piccolo-orm |
|||
owner_html_url: https://github.com/piccolo-orm |
|||
- name: fastapi-cache |
|||
html_url: https://github.com/long2ice/fastapi-cache |
|||
stars: 1789 |
|||
stars: 1816 |
|||
owner_login: long2ice |
|||
owner_html_url: https://github.com/long2ice |
|||
- name: python-week-2022 |
|||
html_url: https://github.com/rochacbruno/python-week-2022 |
|||
stars: 1813 |
|||
owner_login: rochacbruno |
|||
owner_html_url: https://github.com/rochacbruno |
|||
- name: ormar |
|||
html_url: https://github.com/collerek/ormar |
|||
stars: 1783 |
|||
stars: 1797 |
|||
owner_login: collerek |
|||
owner_html_url: https://github.com/collerek |
|||
- name: termpair |
|||
html_url: https://github.com/cs01/termpair |
|||
stars: 1716 |
|||
owner_login: cs01 |
|||
owner_html_url: https://github.com/cs01 |
|||
- name: FastAPI-boilerplate |
|||
html_url: https://github.com/benavlabs/FastAPI-boilerplate |
|||
stars: 1660 |
|||
stars: 1792 |
|||
owner_login: benavlabs |
|||
owner_html_url: https://github.com/benavlabs |
|||
- name: fastapi-langgraph-agent-production-ready-template |
|||
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template |
|||
stars: 1638 |
|||
owner_login: wassim249 |
|||
owner_html_url: https://github.com/wassim249 |
|||
- name: termpair |
|||
html_url: https://github.com/cs01/termpair |
|||
stars: 1727 |
|||
owner_login: cs01 |
|||
owner_html_url: https://github.com/cs01 |
|||
- name: fastapi-crudrouter |
|||
html_url: https://github.com/awtkns/fastapi-crudrouter |
|||
stars: 1677 |
|||
owner_login: awtkns |
|||
owner_html_url: https://github.com/awtkns |
|||
- name: langchain-serve |
|||
html_url: https://github.com/jina-ai/langchain-serve |
|||
stars: 1635 |
|||
stars: 1634 |
|||
owner_login: jina-ai |
|||
owner_html_url: https://github.com/jina-ai |
|||
- name: awesome-fastapi-projects |
|||
html_url: https://github.com/Kludex/awesome-fastapi-projects |
|||
stars: 1589 |
|||
owner_login: Kludex |
|||
owner_html_url: https://github.com/Kludex |
|||
- name: fastapi-pagination |
|||
html_url: https://github.com/uriyyo/fastapi-pagination |
|||
stars: 1585 |
|||
stars: 1607 |
|||
owner_login: uriyyo |
|||
owner_html_url: https://github.com/uriyyo |
|||
- name: coronavirus-tracker-api |
|||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api |
|||
stars: 1574 |
|||
owner_login: ExpDev07 |
|||
owner_html_url: https://github.com/ExpDev07 |
|||
- name: fastapi-crudrouter |
|||
html_url: https://github.com/awtkns/fastapi-crudrouter |
|||
stars: 1559 |
|||
owner_login: awtkns |
|||
owner_html_url: https://github.com/awtkns |
|||
- name: awesome-fastapi-projects |
|||
html_url: https://github.com/Kludex/awesome-fastapi-projects |
|||
stars: 1592 |
|||
owner_login: Kludex |
|||
owner_html_url: https://github.com/Kludex |
|||
- name: bracket |
|||
html_url: https://github.com/evroon/bracket |
|||
stars: 1489 |
|||
stars: 1580 |
|||
owner_login: evroon |
|||
owner_html_url: https://github.com/evroon |
|||
- name: coronavirus-tracker-api |
|||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api |
|||
stars: 1570 |
|||
owner_login: ExpDev07 |
|||
owner_html_url: https://github.com/ExpDev07 |
|||
- name: fastapi-amis-admin |
|||
html_url: https://github.com/amisadmin/fastapi-amis-admin |
|||
stars: 1475 |
|||
stars: 1512 |
|||
owner_login: amisadmin |
|||
owner_html_url: https://github.com/amisadmin |
|||
- name: fastcrud |
|||
html_url: https://github.com/benavlabs/fastcrud |
|||
stars: 1471 |
|||
owner_login: benavlabs |
|||
owner_html_url: https://github.com/benavlabs |
|||
- name: fastapi-boilerplate |
|||
html_url: https://github.com/teamhide/fastapi-boilerplate |
|||
stars: 1436 |
|||
stars: 1461 |
|||
owner_login: teamhide |
|||
owner_html_url: https://github.com/teamhide |
|||
- name: awesome-python-resources |
|||
html_url: https://github.com/DjangoEx/awesome-python-resources |
|||
stars: 1426 |
|||
stars: 1435 |
|||
owner_login: DjangoEx |
|||
owner_html_url: https://github.com/DjangoEx |
|||
- name: fastcrud |
|||
html_url: https://github.com/benavlabs/fastcrud |
|||
stars: 1414 |
|||
owner_login: benavlabs |
|||
owner_html_url: https://github.com/benavlabs |
|||
- name: prometheus-fastapi-instrumentator |
|||
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator |
|||
stars: 1388 |
|||
stars: 1417 |
|||
owner_login: trallnag |
|||
owner_html_url: https://github.com/trallnag |
|||
- name: fastapi_best_architecture |
|||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture |
|||
stars: 1378 |
|||
owner_login: fastapi-practices |
|||
owner_html_url: https://github.com/fastapi-practices |
|||
- name: fastapi-code-generator |
|||
html_url: https://github.com/koxudaxi/fastapi-code-generator |
|||
stars: 1375 |
|||
stars: 1382 |
|||
owner_login: koxudaxi |
|||
owner_html_url: https://github.com/koxudaxi |
|||
- name: budgetml |
|||
html_url: https://github.com/ebhy/budgetml |
|||
stars: 1345 |
|||
owner_login: ebhy |
|||
owner_html_url: https://github.com/ebhy |
|||
- name: fastapi-tutorial |
|||
html_url: https://github.com/liaogx/fastapi-tutorial |
|||
stars: 1327 |
|||
owner_login: liaogx |
|||
owner_html_url: https://github.com/liaogx |
|||
- name: fastapi-alembic-sqlmodel-async |
|||
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async |
|||
stars: 1259 |
|||
owner_login: jonra1993 |
|||
owner_html_url: https://github.com/jonra1993 |
|||
- name: fastapi-scaff |
|||
html_url: https://github.com/atpuxiner/fastapi-scaff |
|||
stars: 1255 |
|||
stars: 1367 |
|||
owner_login: atpuxiner |
|||
owner_html_url: https://github.com/atpuxiner |
|||
- name: bedrock-chat |
|||
html_url: https://github.com/aws-samples/bedrock-chat |
|||
stars: 1254 |
|||
owner_login: aws-samples |
|||
owner_html_url: https://github.com/aws-samples |
|||
- name: fastapi-tutorial |
|||
html_url: https://github.com/liaogx/fastapi-tutorial |
|||
stars: 1360 |
|||
owner_login: liaogx |
|||
owner_html_url: https://github.com/liaogx |
|||
- name: budgetml |
|||
html_url: https://github.com/ebhy/budgetml |
|||
stars: 1343 |
|||
owner_login: ebhy |
|||
owner_html_url: https://github.com/ebhy |
|||
- name: bolt-python |
|||
html_url: https://github.com/slackapi/bolt-python |
|||
stars: 1253 |
|||
stars: 1276 |
|||
owner_login: slackapi |
|||
owner_html_url: https://github.com/slackapi |
|||
- name: bedrock-chat |
|||
html_url: https://github.com/aws-samples/bedrock-chat |
|||
stars: 1268 |
|||
owner_login: aws-samples |
|||
owner_html_url: https://github.com/aws-samples |
|||
- name: fastapi-alembic-sqlmodel-async |
|||
html_url: https://github.com/vargasjona/fastapi-alembic-sqlmodel-async |
|||
stars: 1265 |
|||
owner_login: vargasjona |
|||
owner_html_url: https://github.com/vargasjona |
|||
- name: fastapi_production_template |
|||
html_url: https://github.com/zhanymkanov/fastapi_production_template |
|||
stars: 1217 |
|||
stars: 1227 |
|||
owner_login: zhanymkanov |
|||
owner_html_url: https://github.com/zhanymkanov |
|||
- name: langchain-extract |
|||
html_url: https://github.com/langchain-ai/langchain-extract |
|||
stars: 1176 |
|||
owner_login: langchain-ai |
|||
owner_html_url: https://github.com/langchain-ai |
|||
- name: restish |
|||
html_url: https://github.com/rest-sh/restish |
|||
stars: 1140 |
|||
stars: 1200 |
|||
owner_login: rest-sh |
|||
owner_html_url: https://github.com/rest-sh |
|||
- name: langchain-extract |
|||
html_url: https://github.com/langchain-ai/langchain-extract |
|||
stars: 1183 |
|||
owner_login: langchain-ai |
|||
owner_html_url: https://github.com/langchain-ai |
|||
- name: odmantic |
|||
html_url: https://github.com/art049/odmantic |
|||
stars: 1138 |
|||
stars: 1162 |
|||
owner_login: art049 |
|||
owner_html_url: https://github.com/art049 |
|||
- name: aktools |
|||
html_url: https://github.com/akfamily/aktools |
|||
stars: 1155 |
|||
owner_login: akfamily |
|||
owner_html_url: https://github.com/akfamily |
|||
- name: RuoYi-Vue3-FastAPI |
|||
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI |
|||
stars: 1155 |
|||
owner_login: insistence |
|||
owner_html_url: https://github.com/insistence |
|||
- name: authx |
|||
html_url: https://github.com/yezz123/authx |
|||
stars: 1119 |
|||
stars: 1142 |
|||
owner_login: yezz123 |
|||
owner_html_url: https://github.com/yezz123 |
|||
- name: NoteDiscovery |
|||
html_url: https://github.com/gamosoft/NoteDiscovery |
|||
stars: 1107 |
|||
owner_login: gamosoft |
|||
owner_html_url: https://github.com/gamosoft |
|||
- name: SAG |
|||
html_url: https://github.com/Zleap-AI/SAG |
|||
stars: 1110 |
|||
owner_login: Zleap-AI |
|||
owner_html_url: https://github.com/Zleap-AI |
|||
- name: flock |
|||
html_url: https://github.com/Onelevenvy/flock |
|||
stars: 1055 |
|||
stars: 1069 |
|||
owner_login: Onelevenvy |
|||
owner_html_url: https://github.com/Onelevenvy |
|||
- name: fastapi-observability |
|||
html_url: https://github.com/blueswen/fastapi-observability |
|||
stars: 1038 |
|||
stars: 1063 |
|||
owner_login: blueswen |
|||
owner_html_url: https://github.com/blueswen |
|||
- name: aktools |
|||
html_url: https://github.com/akfamily/aktools |
|||
stars: 1027 |
|||
owner_login: akfamily |
|||
owner_html_url: https://github.com/akfamily |
|||
- name: RuoYi-Vue3-FastAPI |
|||
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI |
|||
stars: 1016 |
|||
owner_login: insistence |
|||
owner_html_url: https://github.com/insistence |
|||
- name: autollm |
|||
html_url: https://github.com/viddexa/autollm |
|||
stars: 1002 |
|||
owner_login: viddexa |
|||
owner_html_url: https://github.com/viddexa |
|||
- name: enterprise-deep-research |
|||
html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research |
|||
stars: 1061 |
|||
owner_login: SalesforceAIResearch |
|||
owner_html_url: https://github.com/SalesforceAIResearch |
|||
- name: titiler |
|||
html_url: https://github.com/developmentseed/titiler |
|||
stars: 999 |
|||
stars: 1039 |
|||
owner_login: developmentseed |
|||
owner_html_url: https://github.com/developmentseed |
|||
- name: lanarky |
|||
html_url: https://github.com/ajndkr/lanarky |
|||
stars: 994 |
|||
owner_login: ajndkr |
|||
owner_html_url: https://github.com/ajndkr |
|||
- name: every-pdf |
|||
html_url: https://github.com/DDULDDUCK/every-pdf |
|||
stars: 985 |
|||
stars: 1017 |
|||
owner_login: DDULDDUCK |
|||
owner_html_url: https://github.com/DDULDDUCK |
|||
- name: enterprise-deep-research |
|||
html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research |
|||
stars: 973 |
|||
owner_login: SalesforceAIResearch |
|||
owner_html_url: https://github.com/SalesforceAIResearch |
|||
- name: fastapi-mail |
|||
html_url: https://github.com/sabuhish/fastapi-mail |
|||
stars: 964 |
|||
owner_login: sabuhish |
|||
owner_html_url: https://github.com/sabuhish |
|||
- name: autollm |
|||
html_url: https://github.com/viddexa/autollm |
|||
stars: 1005 |
|||
owner_login: viddexa |
|||
owner_html_url: https://github.com/viddexa |
|||
- name: lanarky |
|||
html_url: https://github.com/ajndkr/lanarky |
|||
stars: 995 |
|||
owner_login: ajndkr |
|||
owner_html_url: https://github.com/ajndkr |
|||
|
|||
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
@ -0,0 +1,11 @@ |
|||
/// details | 🌐 Translation by AI and humans |
|||
|
|||
This translation was made by AI guided by humans. 🤝 |
|||
|
|||
It could have mistakes of misunderstanding the original meaning, or looking unnatural, etc. 🤖 |
|||
|
|||
You can improve this translation by [helping us guide the AI LLM better](https://fastapi.tiangolo.com/contributing/#translations). |
|||
|
|||
[English version](ENGLISH_VERSION_URL) |
|||
|
|||
/// |
|||
@ -46,12 +46,6 @@ $ pip install "fastapi[all]" |
|||
|
|||
</div> |
|||
|
|||
/// info | Información |
|||
|
|||
En Pydantic v1 venía incluido con el paquete principal. Ahora se distribuye como este paquete independiente para que puedas elegir si instalarlo o no si no necesitas esa funcionalidad. |
|||
|
|||
/// |
|||
|
|||
### Crear el objeto `Settings` { #create-the-settings-object } |
|||
|
|||
Importa `BaseSettings` de Pydantic y crea una sub-clase, muy similar a un modelo de Pydantic. |
|||
@ -60,31 +54,15 @@ De la misma forma que con los modelos de Pydantic, declaras atributos de clase c |
|||
|
|||
Puedes usar todas las mismas funcionalidades de validación y herramientas que usas para los modelos de Pydantic, como diferentes tipos de datos y validaciones adicionales con `Field()`. |
|||
|
|||
//// tab | Pydantic v2 |
|||
|
|||
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} |
|||
|
|||
//// |
|||
|
|||
//// tab | Pydantic v1 |
|||
|
|||
/// info | Información |
|||
|
|||
En Pydantic v1 importarías `BaseSettings` directamente desde `pydantic` en lugar de desde `pydantic_settings`. |
|||
|
|||
/// |
|||
|
|||
{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *} |
|||
|
|||
//// |
|||
|
|||
/// tip | Consejo |
|||
|
|||
Si quieres algo rápido para copiar y pegar, no uses este ejemplo, usa el último más abajo. |
|||
|
|||
/// |
|||
|
|||
Luego, cuando creas una instance de esa clase `Settings` (en este caso, en el objeto `settings`), Pydantic leerá las variables de entorno de una manera indiferente a mayúsculas y minúsculas, por lo que una variable en mayúsculas `APP_NAME` aún será leída para el atributo `app_name`. |
|||
Luego, cuando creas un instance de esa clase `Settings` (en este caso, en el objeto `settings`), Pydantic leerá las variables de entorno de una manera indiferente a mayúsculas y minúsculas, por lo que una variable en mayúsculas `APP_NAME` aún será leída para el atributo `app_name`. |
|||
|
|||
Luego convertirá y validará los datos. Así que, cuando uses ese objeto `settings`, tendrás datos de los tipos que declaraste (por ejemplo, `items_per_user` será un `int`). |
|||
|
|||
@ -110,7 +88,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||
|
|||
/// tip | Consejo |
|||
|
|||
Para establecer múltiples variables de entorno para un solo comando, simplemente sepáralas con un espacio y ponlas todas antes del comando. |
|||
Para establecer múltiples env vars para un solo comando, simplemente sepáralas con un espacio y ponlas todas antes del comando. |
|||
|
|||
/// |
|||
|
|||
@ -150,7 +128,7 @@ Proveniente del ejemplo anterior, tu archivo `config.py` podría verse como: |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} |
|||
|
|||
Nota que ahora no creamos una instance por defecto `settings = Settings()`. |
|||
Nota que ahora no creamos un instance por defecto `settings = Settings()`. |
|||
|
|||
### El archivo principal de la app { #the-main-app-file } |
|||
|
|||
@ -172,11 +150,11 @@ Y luego podemos requerirlo desde la *path operation function* como una dependenc |
|||
|
|||
### Configuraciones y pruebas { #settings-and-testing } |
|||
|
|||
Luego sería muy fácil proporcionar un objeto de configuraciones diferente durante las pruebas al sobrescribir una dependencia para `get_settings`: |
|||
Luego sería muy fácil proporcionar un objeto de configuraciones diferente durante las pruebas al crear una sobrescritura de dependencia para `get_settings`: |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} |
|||
|
|||
En la dependencia sobreescrita establecemos un nuevo valor para el `admin_email` al crear el nuevo objeto `Settings`, y luego devolvemos ese nuevo objeto. |
|||
En la sobrescritura de dependencia establecemos un nuevo valor para el `admin_email` al crear el nuevo objeto `Settings`, y luego devolvemos ese nuevo objeto. |
|||
|
|||
Luego podemos probar que se está usando. |
|||
|
|||
@ -215,8 +193,6 @@ APP_NAME="ChimichangApp" |
|||
|
|||
Y luego actualizar tu `config.py` con: |
|||
|
|||
//// tab | Pydantic v2 |
|||
|
|||
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} |
|||
|
|||
/// tip | Consejo |
|||
@ -225,26 +201,6 @@ El atributo `model_config` se usa solo para configuración de Pydantic. Puedes l |
|||
|
|||
/// |
|||
|
|||
//// |
|||
|
|||
//// tab | Pydantic v1 |
|||
|
|||
{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *} |
|||
|
|||
/// tip | Consejo |
|||
|
|||
La clase `Config` se usa solo para configuración de Pydantic. Puedes leer más en <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>. |
|||
|
|||
/// |
|||
|
|||
//// |
|||
|
|||
/// info | Información |
|||
|
|||
En la versión 1 de Pydantic la configuración se hacía en una clase interna `Config`, en la versión 2 de Pydantic se hace en un atributo `model_config`. Este atributo toma un `dict`, y para obtener autocompletado y errores en línea, puedes importar y usar `SettingsConfigDict` para definir ese `dict`. |
|||
|
|||
/// |
|||
|
|||
Aquí definimos la configuración `env_file` dentro de tu clase Pydantic `Settings`, y establecemos el valor en el nombre del archivo con el archivo dotenv que queremos usar. |
|||
|
|||
### Creando el `Settings` solo una vez con `lru_cache` { #creating-the-settings-only-once-with-lru-cache } |
|||
@ -331,7 +287,7 @@ participant execute as Ejecutar función |
|||
end |
|||
``` |
|||
|
|||
En el caso de nuestra dependencia `get_settings()`, la función ni siquiera toma argumentos, por lo que siempre devolverá el mismo valor. |
|||
En el caso de nuestra dependencia `get_settings()`, la función ni siquiera toma argumentos, por lo que siempre devuelve el mismo valor. |
|||
|
|||
De esa manera, se comporta casi como si fuera solo una variable global. Pero como usa una función de dependencia, entonces podemos sobrescribirla fácilmente para las pruebas. |
|||
|
|||
|
|||
@ -22,21 +22,13 @@ Aquí tienes una idea general de cómo podrían ser los modelos con sus campos d |
|||
|
|||
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} |
|||
|
|||
/// info | Información |
|||
### Acerca de `**user_in.model_dump()` { #about-user-in-model-dump } |
|||
|
|||
En Pydantic v1 el método se llamaba `.dict()`, fue deprecado (pero aún soportado) en Pydantic v2, y renombrado a `.model_dump()`. |
|||
|
|||
Los ejemplos aquí usan `.dict()` para compatibilidad con Pydantic v1, pero deberías usar `.model_dump()` en su lugar si puedes usar Pydantic v2. |
|||
|
|||
/// |
|||
|
|||
### Acerca de `**user_in.dict()` { #about-user-in-dict } |
|||
|
|||
#### `.dict()` de Pydantic { #pydantics-dict } |
|||
#### `.model_dump()` de Pydantic { #pydantics-model-dump } |
|||
|
|||
`user_in` es un modelo Pydantic de la clase `UserIn`. |
|||
|
|||
Los modelos Pydantic tienen un método `.dict()` que devuelve un `dict` con los datos del modelo. |
|||
Los modelos Pydantic tienen un método `.model_dump()` que devuelve un `dict` con los datos del modelo. |
|||
|
|||
Así que, si creamos un objeto Pydantic `user_in` como: |
|||
|
|||
@ -47,7 +39,7 @@ user_in = UserIn(username="john", password="secret", email="[email protected] |
|||
y luego llamamos a: |
|||
|
|||
```Python |
|||
user_dict = user_in.dict() |
|||
user_dict = user_in.model_dump() |
|||
``` |
|||
|
|||
ahora tenemos un `dict` con los datos en la variable `user_dict` (es un `dict` en lugar de un objeto modelo Pydantic). |
|||
@ -58,7 +50,7 @@ Y si llamamos a: |
|||
print(user_dict) |
|||
``` |
|||
|
|||
obtendremos un `dict` de Python con: |
|||
obtendríamos un `dict` de Python con: |
|||
|
|||
```Python |
|||
{ |
|||
@ -103,20 +95,20 @@ UserInDB( |
|||
|
|||
#### Un modelo Pydantic a partir del contenido de otro { #a-pydantic-model-from-the-contents-of-another } |
|||
|
|||
Como en el ejemplo anterior obtuvimos `user_dict` de `user_in.dict()`, este código: |
|||
Como en el ejemplo anterior obtuvimos `user_dict` de `user_in.model_dump()`, este código: |
|||
|
|||
```Python |
|||
user_dict = user_in.dict() |
|||
user_dict = user_in.model_dump() |
|||
UserInDB(**user_dict) |
|||
``` |
|||
|
|||
sería equivalente a: |
|||
|
|||
```Python |
|||
UserInDB(**user_in.dict()) |
|||
UserInDB(**user_in.model_dump()) |
|||
``` |
|||
|
|||
...porque `user_in.dict()` es un `dict`, y luego hacemos que Python lo "desempaquete" al pasarlo a `UserInDB` con el prefijo `**`. |
|||
...porque `user_in.model_dump()` es un `dict`, y luego hacemos que Python lo "desempaquete" al pasarlo a `UserInDB` con el prefijo `**`. |
|||
|
|||
Así, obtenemos un modelo Pydantic a partir de los datos en otro modelo Pydantic. |
|||
|
|||
@ -125,7 +117,7 @@ Así, obtenemos un modelo Pydantic a partir de los datos en otro modelo Pydantic |
|||
Y luego agregando el argumento de palabra clave adicional `hashed_password=hashed_password`, como en: |
|||
|
|||
```Python |
|||
UserInDB(**user_in.dict(), hashed_password=hashed_password) |
|||
UserInDB(**user_in.model_dump(), hashed_password=hashed_password) |
|||
``` |
|||
|
|||
...termina siendo como: |
|||
@ -156,7 +148,7 @@ Y estos modelos están compartiendo muchos de los datos y duplicando nombres y t |
|||
|
|||
Podríamos hacerlo mejor. |
|||
|
|||
Podemos declarar un modelo `UserBase` que sirva como base para nuestros otros modelos. Y luego podemos hacer subclases de ese modelo que heredan sus atributos (anotaciones de tipos, validación, etc). |
|||
Podemos declarar un modelo `UserBase` que sirva como base para nuestros otros modelos. Y luego podemos hacer subclases de ese modelo que heredan sus atributos (declaraciones de tipos, validación, etc). |
|||
|
|||
Toda la conversión de datos, validación, documentación, etc. seguirá funcionando normalmente. |
|||
|
|||
@ -180,20 +172,19 @@ Al definir una <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" |
|||
|
|||
{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} |
|||
|
|||
|
|||
### `Union` en Python 3.10 { #union-in-python-3-10 } |
|||
|
|||
En este ejemplo pasamos `Union[PlaneItem, CarItem]` como el valor del argumento `response_model`. |
|||
|
|||
Porque lo estamos pasando como un **valor a un argumento** en lugar de ponerlo en **anotaciones de tipos**, tenemos que usar `Union` incluso en Python 3.10. |
|||
Porque lo estamos pasando como un **valor a un argumento** en lugar de ponerlo en una **anotación de tipos**, tenemos que usar `Union` incluso en Python 3.10. |
|||
|
|||
Si estuviera en anotaciones de tipos podríamos haber usado la barra vertical, como: |
|||
Si estuviera en una anotación de tipos podríamos haber usado la barra vertical, como: |
|||
|
|||
```Python |
|||
some_variable: PlaneItem | CarItem |
|||
``` |
|||
|
|||
Pero si ponemos eso en la asignación `response_model=PlaneItem | CarItem` obtendríamos un error, porque Python intentaría realizar una **operación inválida** entre `PlaneItem` y `CarItem` en lugar de interpretar eso como anotaciones de tipos. |
|||
Pero si ponemos eso en la asignación `response_model=PlaneItem | CarItem` obtendríamos un error, porque Python intentaría realizar una **operación inválida** entre `PlaneItem` y `CarItem` en lugar de interpretar eso como una anotación de tipos. |
|||
|
|||
## Lista de modelos { #list-of-models } |
|||
|
|||
@ -203,7 +194,6 @@ Para eso, usa el `typing.List` estándar de Python (o simplemente `list` en Pyth |
|||
|
|||
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} |
|||
|
|||
|
|||
## Response con `dict` arbitrario { #response-with-arbitrary-dict } |
|||
|
|||
También puedes declarar un response usando un `dict` arbitrario plano, declarando solo el tipo de las claves y valores, sin usar un modelo Pydantic. |
|||
@ -214,7 +204,6 @@ En este caso, puedes usar `typing.Dict` (o solo `dict` en Python 3.9 y posterior |
|||
|
|||
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} |
|||
|
|||
|
|||
## Recapitulación { #recap } |
|||
|
|||
Usa múltiples modelos Pydantic y hereda libremente para cada caso. |
|||
|
|||
@ -1,34 +1,34 @@ |
|||
# Test de performance |
|||
# Tests de performance { #benchmarks } |
|||
|
|||
Les tests de performance de TechEmpower montrent que les applications **FastAPI** tournant sous Uvicorn comme <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">étant l'un des frameworks Python les plus rapides disponibles</a>, seulement inférieur à Starlette et Uvicorn (tous deux utilisés au cœur de FastAPI). (*) |
|||
Les benchmarks indépendants de TechEmpower montrent que les applications **FastAPI** s’exécutant avec Uvicorn sont <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">parmi les frameworks Python les plus rapides disponibles</a>, seulement en dessous de Starlette et Uvicorn eux‑mêmes (tous deux utilisés en interne par FastAPI). |
|||
|
|||
Mais en prêtant attention aux tests de performance et aux comparaisons, il faut tenir compte de ce qu'il suit. |
|||
Mais en prêtant attention aux tests de performance et aux comparaisons, vous devez tenir compte de ce qui suit. |
|||
|
|||
## Tests de performance et rapidité |
|||
## Tests de performance et rapidité { #benchmarks-and-speed } |
|||
|
|||
Lorsque vous vérifiez les tests de performance, il est commun de voir plusieurs outils de différents types comparés comme équivalents. |
|||
|
|||
En particulier, on voit Uvicorn, Starlette et FastAPI comparés (parmi de nombreux autres outils). |
|||
|
|||
Plus le problème résolu par un outil est simple, mieux seront les performances obtenues. Et la plupart des tests de performance ne prennent pas en compte les fonctionnalités additionnelles fournies par les outils. |
|||
Plus le problème résolu par un outil est simple, meilleures seront les performances obtenues. Et la plupart des tests de performance ne prennent pas en compte les fonctionnalités additionnelles fournies par les outils. |
|||
|
|||
La hiérarchie est la suivante : |
|||
|
|||
* **Uvicorn** : un serveur ASGI |
|||
* **Starlette** : (utilise Uvicorn) un micro-framework web |
|||
* **FastAPI**: (utilise Starlette) un micro-framework pour API disposant de fonctionnalités additionnelles pour la création d'API, avec la validation des données, etc. |
|||
* **Starlette** : (utilise Uvicorn) un microframework web |
|||
* **FastAPI**: (utilise Starlette) un microframework pour API disposant de fonctionnalités additionnelles pour la création d'API, avec la validation des données, etc. |
|||
|
|||
* **Uvicorn** : |
|||
* A les meilleures performances, étant donné qu'il n'a pas beaucoup de code mis-à-part le serveur en lui-même. |
|||
* On n'écrit pas une application avec uniquement Uvicorn. Cela signifie que le code devrait inclure plus ou moins, au minimum, tout le code offert par Starlette (ou **FastAPI**). Et si on fait cela, l'application finale apportera les mêmes complications que si on avait utilisé un framework et que l'on avait minimisé la quantité de code et de bugs. |
|||
* Si on compare Uvicorn, il faut le comparer à d'autre applications de serveurs comme Daphne, Hypercorn, uWSGI, etc. |
|||
* A les meilleures performances, étant donné qu'il n'a pas beaucoup de code mis à part le serveur en lui‑même. |
|||
* On n'écrit pas une application directement avec Uvicorn. Cela signifie que le code devrait inclure, au minimum, plus ou moins tout le code offert par Starlette (ou **FastAPI**). Et si on fait cela, l'application finale aura la même surcharge que si on avait utilisé un framework, tout en minimisant la quantité de code et les bugs. |
|||
* Si on compare Uvicorn, il faut le comparer à d'autres serveurs d'applications comme Daphne, Hypercorn, uWSGI, etc. |
|||
* **Starlette** : |
|||
* A les seconde meilleures performances après Uvicorn. Starlette utilise en réalité Uvicorn. De ce fait, il ne peut qu’être plus "lent" qu'Uvicorn car il requiert l'exécution de plus de code. |
|||
* Cependant il nous apporte les outils pour construire une application web simple, avec un routage basé sur des chemins, etc. |
|||
* Si on compare Starlette, il faut le comparer à d'autres frameworks web (ou micorframework) comme Sanic, Flask, Django, etc. |
|||
* A les secondes meilleures performances après Uvicorn. En réalité, Starlette utilise Uvicorn. De ce fait, il ne peut qu’être plus « lent » qu'Uvicorn car il requiert l'exécution de plus de code. |
|||
* Cependant, il apporte les outils pour construire une application web simple, avec un routage basé sur des chemins, etc. |
|||
* Si on compare Starlette, il faut le comparer à d'autres frameworks web (ou microframeworks) comme Sanic, Flask, Django, etc. |
|||
* **FastAPI** : |
|||
* Comme Starlette, FastAPI utilise Uvicorn et ne peut donc pas être plus rapide que ce dernier. |
|||
* FastAPI apporte des fonctionnalités supplémentaires à Starlette. Des fonctionnalités qui sont nécessaires presque systématiquement lors de la création d'une API, comme la validation des données, la sérialisation. En utilisant FastAPI, on obtient une documentation automatiquement (qui ne requiert aucune manipulation pour être mise en place). |
|||
* Si on n'utilisait pas FastAPI mais directement Starlette (ou un outil équivalent comme Sanic, Flask, Responder, etc) il faudrait implémenter la validation des données et la sérialisation par nous-même. Le résultat serait donc le même dans les deux cas mais du travail supplémentaire serait à réaliser avec Starlette, surtout en considérant que la validation des données et la sérialisation représentent la plus grande quantité de code à écrire dans une application. |
|||
* De ce fait, en utilisant FastAPI on minimise le temps de développement, les bugs, le nombre de lignes de code, et on obtient les mêmes performances (si ce n'est de meilleurs performances) que l'on aurait pu avoir sans ce framework (en ayant à implémenter de nombreuses fonctionnalités importantes par nous-mêmes). |
|||
* Si on compare FastAPI, il faut le comparer à d'autres frameworks web (ou ensemble d'outils) qui fournissent la validation des données, la sérialisation et la documentation, comme Flask-apispec, NestJS, Molten, etc. |
|||
* Comme Starlette utilise Uvicorn et ne peut donc pas être plus rapide que lui, **FastAPI** utilise Starlette et ne peut donc pas être plus rapide que lui. |
|||
* FastAPI apporte des fonctionnalités supplémentaires à Starlette. Des fonctionnalités dont vous avez presque toujours besoin lors de la création d'une API, comme la validation des données et la sérialisation. En l'utilisant, vous obtenez une documentation automatique « gratuitement » (la documentation automatique n'ajoute même pas de surcharge à l’exécution, elle est générée au démarrage). |
|||
* Si on n'utilisait pas FastAPI mais directement Starlette (ou un autre outil comme Sanic, Flask, Responder, etc.), il faudrait implémenter toute la validation des données et la sérialisation soi‑même. L'application finale aurait donc la même surcharge que si elle avait été construite avec FastAPI. Et dans de nombreux cas, cette validation des données et cette sérialisation représentent la plus grande quantité de code écrite dans les applications. |
|||
* De ce fait, en utilisant FastAPI on minimise le temps de développement, les bugs, le nombre de lignes de code, et on obtient probablement les mêmes performances (voire de meilleures performances) que l'on aurait pu avoir sans ce framework (car il aurait fallu tout implémenter dans votre code). |
|||
* Si on compare FastAPI, il faut le comparer à d'autres frameworks d’application web (ou ensembles d'outils) qui fournissent la validation des données, la sérialisation et la documentation, comme Flask-apispec, NestJS, Molten, etc. Des frameworks avec validation des données, sérialisation et documentation automatiques intégrées. |
|||
|
|||
@ -1,56 +1,231 @@ |
|||
# À propos de HTTPS |
|||
# À propos de HTTPS { #about-https } |
|||
|
|||
Il est facile de penser que HTTPS peut simplement être "activé" ou non. |
|||
Il est facile de supposer que HTTPS est quelque chose qui est simplement « activé » ou non. |
|||
|
|||
Mais c'est beaucoup plus complexe que cela. |
|||
|
|||
/// tip |
|||
/// tip | Astuce |
|||
|
|||
Si vous êtes pressé ou si cela ne vous intéresse pas, passez aux sections suivantes pour obtenir des instructions étape par étape afin de tout configurer avec différentes techniques. |
|||
Si vous êtes pressé ou si cela ne vous intéresse pas, continuez avec les sections suivantes pour obtenir des instructions étape par étape afin de tout configurer avec différentes techniques. |
|||
|
|||
/// |
|||
|
|||
Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez <a href="https://howhttps.works/" |
|||
class="external-link" target="_blank">https://howhttps.works/</a>. |
|||
Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>. |
|||
|
|||
Maintenant, du point de vue d'un développeur, voici plusieurs choses à avoir en tête en pensant au HTTPS : |
|||
|
|||
* Pour le HTTPS, le serveur a besoin de "certificats" générés par une tierce partie. |
|||
* Ces certificats sont en fait acquis auprès de la tierce partie, et non "générés". |
|||
* Les certificats ont une durée de vie. |
|||
* Ils expirent. |
|||
* Puis ils doivent être renouvelés et acquis à nouveau auprès de la tierce partie. |
|||
* Le cryptage de la connexion se fait au niveau du protocole TCP. |
|||
* C'est une couche en dessous de HTTP. |
|||
* Donc, le certificat et le traitement du cryptage sont faits avant HTTP. |
|||
* TCP ne connaît pas les "domaines", seulement les adresses IP. |
|||
* L'information sur le domaine spécifique demandé se trouve dans les données HTTP. |
|||
* Les certificats HTTPS "certifient" un certain domaine, mais le protocole et le cryptage se font au niveau TCP, avant de savoir quel domaine est traité. |
|||
* Par défaut, cela signifie que vous ne pouvez avoir qu'un seul certificat HTTPS par adresse IP. |
|||
* Quelle que soit la taille de votre serveur ou la taille de chacune des applications qu'il contient. |
|||
* Il existe cependant une solution à ce problème. |
|||
* Il existe une extension du protocole TLS (celui qui gère le cryptage au niveau TCP, avant HTTP) appelée <a |
|||
href="https://fr.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr |
|||
title="Server Name Indication (indication du nom du serveur)">SNI (indication du nom du serveur)</abbr></a>. |
|||
* Cette extension SNI permet à un seul serveur (avec une seule adresse IP) d'avoir plusieurs certificats HTTPS et de servir plusieurs domaines/applications HTTPS. |
|||
* Pour que cela fonctionne, un seul composant (programme) fonctionnant sur le serveur, écoutant sur l'adresse IP publique, doit avoir tous les certificats HTTPS du serveur. |
|||
* Après avoir obtenu une connexion sécurisée, le protocole de communication est toujours HTTP. |
|||
* Le contenu est crypté, même s'il est envoyé avec le protocole HTTP. |
|||
|
|||
Il est courant d'avoir un seul programme/serveur HTTP fonctionnant sur le serveur (la machine, l'hôte, etc.) et |
|||
gérant toutes les parties HTTPS : envoyer les requêtes HTTP décryptées à l'application HTTP réelle fonctionnant sur |
|||
le même serveur (dans ce cas, l'application **FastAPI**), prendre la réponse HTTP de l'application, la crypter en utilisant le certificat approprié et la renvoyer au client en utilisant HTTPS. Ce serveur est souvent appelé un <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Proxy de terminaison TLS</a>. |
|||
|
|||
## Let's Encrypt |
|||
|
|||
Avant Let's Encrypt, ces certificats HTTPS étaient vendus par des tiers de confiance. |
|||
|
|||
Le processus d'acquisition d'un de ces certificats était auparavant lourd, nécessitait pas mal de paperasses et les certificats étaient assez chers. |
|||
|
|||
Mais ensuite, <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> a été créé. |
|||
|
|||
Il s'agit d'un projet de la Fondation Linux. Il fournit des certificats HTTPS gratuitement. De manière automatisée. Ces certificats utilisent toutes les sécurités cryptographiques standard et ont une durée de vie courte (environ 3 mois), de sorte que la sécurité est en fait meilleure en raison de leur durée de vie réduite. |
|||
* Pour le HTTPS, **le serveur** doit **disposer de « certificats »** générés par une **tierce partie**. |
|||
* Ces certificats sont en réalité **acquis** auprès de la tierce partie, et non « générés ». |
|||
* Les certificats ont une **durée de vie**. |
|||
* Ils **expirent**. |
|||
* Puis ils doivent être **renouvelés**, **acquis à nouveau** auprès de la tierce partie. |
|||
* Le cryptage de la connexion se fait au **niveau TCP**. |
|||
* C'est une couche **en dessous de HTTP**. |
|||
* Donc, la gestion du **certificat et du cryptage** est effectuée **avant HTTP**. |
|||
* **TCP ne connaît pas les « domaines »**. Il ne connaît que les adresses IP. |
|||
* L'information sur le **domaine spécifique** demandé se trouve dans les **données HTTP**. |
|||
* Les **certificats HTTPS** « certifient » un **certain domaine**, mais le protocole et le cryptage se font au niveau TCP, **avant de savoir** quel domaine est traité. |
|||
* **Par défaut**, cela signifie que vous ne pouvez avoir qu'**un seul certificat HTTPS par adresse IP**. |
|||
* Quelle que soit la taille de votre serveur ou la petitesse de chacune des applications qu'il contient. |
|||
* Il existe cependant une **solution** à ce problème. |
|||
* Il existe une **extension** du protocole **TLS** (celui qui gère le cryptage au niveau TCP, avant HTTP) appelée **<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication - Indication du nom du serveur">SNI</abbr></a>**. |
|||
* Cette extension SNI permet à un seul serveur (avec une **seule adresse IP**) d'avoir **plusieurs certificats HTTPS** et de servir **plusieurs domaines/applications HTTPS**. |
|||
* Pour que cela fonctionne, un **seul** composant (programme) fonctionnant sur le serveur, écoutant sur l'**adresse IP publique**, doit avoir **tous les certificats HTTPS** du serveur. |
|||
* **Après** l'établissement d'une connexion sécurisée, le protocole de communication est **toujours HTTP**. |
|||
* Le contenu est **crypté**, même s'il est envoyé avec le **protocole HTTP**. |
|||
|
|||
Il est courant d'avoir **un seul programme/serveur HTTP** fonctionnant sur le serveur (la machine, l'hôte, etc.) et **gérant toutes les parties HTTPS** : recevoir les **requêtes HTTPS chiffrées**, envoyer les **requêtes HTTP déchiffrées** à l'application HTTP réelle fonctionnant sur le même serveur (l'application **FastAPI**, dans ce cas), prendre la **réponse HTTP** de l'application, la **chiffrer** en utilisant le **certificat HTTPS** approprié et la renvoyer au client en utilisant **HTTPS**. Ce serveur est souvent appelé un **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">Proxy de terminaison TLS</a>**. |
|||
|
|||
Parmi les options que vous pourriez utiliser comme Proxy de terminaison TLS : |
|||
|
|||
* Traefik (qui peut également gérer les renouvellements de certificats) |
|||
* Caddy (qui peut également gérer les renouvellements de certificats) |
|||
* Nginx |
|||
* HAProxy |
|||
|
|||
## Let's Encrypt { #lets-encrypt } |
|||
|
|||
Avant Let's Encrypt, ces **certificats HTTPS** étaient vendus par des tiers de confiance. |
|||
|
|||
Le processus d'acquisition de l'un de ces certificats était auparavant lourd, nécessitait pas mal de paperasses et les certificats étaient assez chers. |
|||
|
|||
Mais ensuite, **<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>** a été créé. |
|||
|
|||
Il s'agit d'un projet de la Fondation Linux. Il fournit **des certificats HTTPS gratuitement**, de manière automatisée. Ces certificats utilisent toutes les sécurités cryptographiques standard et ont une durée de vie courte (environ 3 mois), de sorte que la **sécurité est en fait meilleure** en raison de leur durée de vie réduite. |
|||
|
|||
Les domaines sont vérifiés de manière sécurisée et les certificats sont générés automatiquement. Cela permet également d'automatiser le renouvellement de ces certificats. |
|||
|
|||
L'idée est d'automatiser l'acquisition et le renouvellement de ces certificats, afin que vous puissiez disposer d'un HTTPS sécurisé, gratuitement et pour toujours. |
|||
L'idée est d'automatiser l'acquisition et le renouvellement de ces certificats, afin que vous puissiez disposer d'un **HTTPS sécurisé, gratuitement et pour toujours**. |
|||
|
|||
## HTTPS pour les développeurs { #https-for-developers } |
|||
|
|||
Voici un exemple de ce à quoi pourrait ressembler une API HTTPS, étape par étape, en portant principalement attention aux idées importantes pour les développeurs. |
|||
|
|||
### Nom de domaine { #domain-name } |
|||
|
|||
Tout commencerait probablement par le fait que vous **acquériez** un **nom de domaine**. Ensuite, vous le configureriez dans un serveur DNS (possiblement le même que votre fournisseur cloud). |
|||
|
|||
Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP **publique** <abbr title="Qui ne change pas">fixe</abbr>. |
|||
|
|||
Dans le ou les serveurs DNS, vous configureriez un enregistrement (un « `A record` ») pour faire pointer **votre domaine** vers l'**adresse IP publique de votre serveur**. |
|||
|
|||
Vous feriez probablement cela une seule fois, la première fois, lors de la mise en place de l'ensemble. |
|||
|
|||
/// tip | Astuce |
|||
|
|||
Cette partie relative au nom de domaine intervient bien avant HTTPS, mais comme tout dépend du domaine et de l'adresse IP, il vaut la peine de la mentionner ici. |
|||
|
|||
/// |
|||
|
|||
### DNS { #dns } |
|||
|
|||
Concentrons-nous maintenant sur toutes les parties réellement liées à HTTPS. |
|||
|
|||
D'abord, le navigateur vérifierait auprès des **serveurs DNS** quelle est l'**IP du domaine**, dans ce cas, `someapp.example.com`. |
|||
|
|||
Les serveurs DNS indiqueraient au navigateur d'utiliser une **adresse IP** spécifique. Ce serait l'adresse IP publique utilisée par votre serveur, celle que vous avez configurée dans les serveurs DNS. |
|||
|
|||
<img src="/img/deployment/https/https01.drawio.svg"> |
|||
|
|||
### Début de la négociation TLS (Handshake) { #tls-handshake-start } |
|||
|
|||
Le navigateur communiquerait ensuite avec cette adresse IP sur le **port 443** (le port HTTPS). |
|||
|
|||
La première partie de la communication consiste simplement à établir la connexion entre le client et le serveur et à décider des clés cryptographiques qu'ils utiliseront, etc. |
|||
|
|||
<img src="/img/deployment/https/https02.drawio.svg"> |
|||
|
|||
Cette interaction entre le client et le serveur pour établir la connexion TLS s'appelle la **négociation TLS (TLS handshake)**. |
|||
|
|||
### TLS avec l'extension SNI { #tls-with-sni-extension } |
|||
|
|||
**Un seul processus** sur le serveur peut écouter sur un **port** spécifique d'une **adresse IP** spécifique. Il pourrait y avoir d'autres processus écoutant sur d'autres ports de la même adresse IP, mais un seul pour chaque combinaison d'adresse IP et de port. |
|||
|
|||
TLS (HTTPS) utilise par défaut le port spécifique `443`. C'est donc le port dont nous aurions besoin. |
|||
|
|||
Comme un seul processus peut écouter sur ce port, le processus qui le ferait serait le **Proxy de terminaison TLS**. |
|||
|
|||
Le Proxy de terminaison TLS aurait accès à un ou plusieurs **certificats TLS** (certificats HTTPS). |
|||
|
|||
En utilisant l'**extension SNI** mentionnée plus haut, le Proxy de terminaison TLS vérifierait lequel des certificats TLS (HTTPS) disponibles il devrait utiliser pour cette connexion, en choisissant celui qui correspond au domaine attendu par le client. |
|||
|
|||
Dans ce cas, il utiliserait le certificat pour `someapp.example.com`. |
|||
|
|||
<img src="/img/deployment/https/https03.drawio.svg"> |
|||
|
|||
Le client **fait déjà confiance** à l'entité qui a généré ce certificat TLS (dans ce cas Let's Encrypt, mais nous y reviendrons plus tard), il peut donc **vérifier** que le certificat est valide. |
|||
|
|||
Ensuite, en utilisant le certificat, le client et le Proxy de terminaison TLS **décident comment chiffrer** le reste de la **communication TCP**. Cela termine la partie **négociation TLS**. |
|||
|
|||
Après cela, le client et le serveur disposent d'une **connexion TCP chiffrée**, c'est ce que fournit TLS. Ils peuvent alors utiliser cette connexion pour démarrer la **communication HTTP** proprement dite. |
|||
|
|||
Et c'est ce qu'est **HTTPS** : c'est simplement du **HTTP** à l'intérieur d'une **connexion TLS sécurisée** au lieu d'une connexion TCP pure (non chiffrée). |
|||
|
|||
/// tip | Astuce |
|||
|
|||
Remarquez que le cryptage de la communication se produit au **niveau TCP**, pas au niveau HTTP. |
|||
|
|||
/// |
|||
|
|||
### Requête HTTPS { #https-request } |
|||
|
|||
Maintenant que le client et le serveur (spécifiquement le navigateur et le Proxy de terminaison TLS) ont une **connexion TCP chiffrée**, ils peuvent démarrer la **communication HTTP**. |
|||
|
|||
Ainsi, le client envoie une **requête HTTPS**. Ce n'est qu'une requête HTTP à travers une connexion TLS chiffrée. |
|||
|
|||
<img src="/img/deployment/https/https04.drawio.svg"> |
|||
|
|||
### Déchiffrer la requête { #decrypt-the-request } |
|||
|
|||
Le Proxy de terminaison TLS utiliserait le chiffrement convenu pour **déchiffrer la requête**, et transmettrait la **requête HTTP en clair (déchiffrée)** au processus exécutant l'application (par exemple un processus avec Uvicorn exécutant l'application FastAPI). |
|||
|
|||
<img src="/img/deployment/https/https05.drawio.svg"> |
|||
|
|||
### Réponse HTTP { #http-response } |
|||
|
|||
L'application traiterait la requête et enverrait une **réponse HTTP en clair (non chiffrée)** au Proxy de terminaison TLS. |
|||
|
|||
<img src="/img/deployment/https/https06.drawio.svg"> |
|||
|
|||
### Réponse HTTPS { #https-response } |
|||
|
|||
Le Proxy de terminaison TLS **chiffrerait ensuite la réponse** en utilisant la cryptographie convenue auparavant (qui a commencé avec le certificat pour `someapp.example.com`), et la renverrait au navigateur. |
|||
|
|||
Ensuite, le navigateur vérifierait que la réponse est valide et chiffrée avec la bonne clé cryptographique, etc. Il **déchiffrerait la réponse** et la traiterait. |
|||
|
|||
<img src="/img/deployment/https/https07.drawio.svg"> |
|||
|
|||
Le client (navigateur) saura que la réponse provient du bon serveur parce qu'elle utilise la cryptographie convenue auparavant à l'aide du **certificat HTTPS**. |
|||
|
|||
### Applications multiples { #multiple-applications } |
|||
|
|||
Sur le même serveur (ou les mêmes serveurs), il pourrait y avoir **plusieurs applications**, par exemple d'autres programmes d'API ou une base de données. |
|||
|
|||
Un seul processus peut gérer l'adresse IP et le port spécifiques (le Proxy de terminaison TLS dans notre exemple), mais les autres applications/processus peuvent également s'exécuter sur le ou les serveurs, tant qu'ils n'essaient pas d'utiliser la même **combinaison d'adresse IP publique et de port**. |
|||
|
|||
<img src="/img/deployment/https/https08.drawio.svg"> |
|||
|
|||
De cette façon, le Proxy de terminaison TLS pourrait gérer HTTPS et les certificats pour **plusieurs domaines**, pour plusieurs applications, puis transmettre les requêtes à la bonne application dans chaque cas. |
|||
|
|||
### Renouvellement des certificats { #certificate-renewal } |
|||
|
|||
À un moment donné dans le futur, chaque certificat **expirerait** (environ 3 mois après son acquisition). |
|||
|
|||
Ensuite, il y aurait un autre programme (dans certains cas c'est un autre programme, dans d'autres cas cela pourrait être le même Proxy de terminaison TLS) qui communiquerait avec Let's Encrypt et renouvellerait le ou les certificats. |
|||
|
|||
<img src="/img/deployment/https/https.drawio.svg"> |
|||
|
|||
Les **certificats TLS** sont **associés à un nom de domaine**, pas à une adresse IP. |
|||
|
|||
Ainsi, pour renouveler les certificats, le programme de renouvellement doit **prouver** à l'autorité (Let's Encrypt) qu'il **« possède » et contrôle ce domaine**. |
|||
|
|||
Pour ce faire, et pour s'adapter aux différents besoins des applications, il existe plusieurs façons de procéder. Parmi les plus courantes : |
|||
|
|||
* **Modifier certains enregistrements DNS**. |
|||
* Pour cela, le programme de renouvellement doit prendre en charge les API du fournisseur DNS ; ainsi, selon le fournisseur DNS que vous utilisez, cela peut être ou non une option. |
|||
* **S'exécuter comme un serveur** (au moins pendant le processus d'acquisition du certificat) sur l'adresse IP publique associée au domaine. |
|||
* Comme nous l'avons dit plus haut, un seul processus peut écouter sur une adresse IP et un port spécifiques. |
|||
* C'est l'une des raisons pour lesquelles il est très utile que le même Proxy de terminaison TLS prenne également en charge le processus de renouvellement des certificats. |
|||
* Sinon, vous pourriez avoir à arrêter le Proxy de terminaison TLS momentanément, démarrer le programme de renouvellement pour acquérir les certificats, puis les configurer avec le Proxy de terminaison TLS, et ensuite redémarrer le Proxy de terminaison TLS. Ce n'est pas idéal, car votre/vos application(s) ne seront pas disponibles pendant le temps où le Proxy de terminaison TLS est arrêté. |
|||
|
|||
Tout ce processus de renouvellement, tout en continuant à servir l'application, est l'une des principales raisons pour lesquelles vous voudriez avoir un **système séparé pour gérer HTTPS** avec un Proxy de terminaison TLS, au lieu d'utiliser directement les certificats TLS avec le serveur d'application (par exemple Uvicorn). |
|||
|
|||
## En-têtes Proxy Forwarded { #proxy-forwarded-headers } |
|||
|
|||
Lorsque vous utilisez un proxy pour gérer HTTPS, votre **serveur d'application** (par exemple Uvicorn via FastAPI CLI) ne connaît rien du processus HTTPS, il communique en HTTP en clair avec le **Proxy de terminaison TLS**. |
|||
|
|||
Ce **proxy** définirait normalement certains en-têtes HTTP à la volée avant de transmettre la requête au **serveur d'application**, pour informer le serveur d'application que la requête est **transmise** par le proxy. |
|||
|
|||
/// note | Détails techniques |
|||
|
|||
Les en-têtes du proxy sont : |
|||
|
|||
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a> |
|||
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a> |
|||
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a> |
|||
|
|||
/// |
|||
|
|||
Néanmoins, comme le **serveur d'application** ne sait pas qu'il se trouve derrière un **proxy** de confiance, par défaut, il ne ferait pas confiance à ces en-têtes. |
|||
|
|||
Mais vous pouvez configurer le **serveur d'application** pour qu'il fasse confiance aux en-têtes transmis (*forwarded*) envoyés par le **proxy**. Si vous utilisez FastAPI CLI, vous pouvez utiliser l'*option CLI* `--forwarded-allow-ips` pour lui indiquer à partir de quelles IP il doit faire confiance à ces en-têtes transmis. |
|||
|
|||
Par exemple, si le **serveur d'application** ne reçoit des communications que du **proxy** de confiance, vous pouvez définir `--forwarded-allow-ips="*"` pour lui faire faire confiance à toutes les IP entrantes, puisqu'il ne recevra des requêtes que depuis l'IP utilisée par le **proxy**. |
|||
|
|||
De cette façon, l'application sera en mesure de savoir quelle est sa propre URL publique, si elle utilise HTTPS, le domaine, etc. |
|||
|
|||
Cela serait utile, par exemple, pour gérer correctement les redirections. |
|||
|
|||
/// tip | Astuce |
|||
|
|||
Vous pouvez en savoir plus dans la documentation [Derrière un proxy - Activer les en-têtes transmis par le proxy](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} |
|||
|
|||
/// |
|||
|
|||
## Récapitulatif { #recap } |
|||
|
|||
Disposer de **HTTPS** est très important, et assez **critique** dans la plupart des cas. La majeure partie de l'effort que vous, en tant que développeur, devez fournir autour de HTTPS consiste simplement à **comprendre ces concepts** et leur fonctionnement. |
|||
|
|||
Mais une fois que vous connaissez les informations de base sur **HTTPS pour les développeurs**, vous pouvez facilement combiner et configurer différents outils pour vous aider à tout gérer simplement. |
|||
|
|||
Dans certains des prochains chapitres, je vous montrerai plusieurs exemples concrets de configuration de **HTTPS** pour des applications **FastAPI**. 🔒 |
|||
|
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue