From 316566e40efb5b7dabc549ff0060a016e68719ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 3 Mar 2025 15:33:33 +0100 Subject: [PATCH 001/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20pau?= =?UTF-8?q?se=20TestDriven=20(#13446)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/sponsors.yml | 6 +++--- docs/en/docs/advanced/index.md | 15 --------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index b994e533a..5cbf05f9d 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -58,9 +58,9 @@ bronze: - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source title: Biosecurity risk assessments made easy. img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png - - url: https://testdriven.io/courses/tdd-fastapi/ - title: Learn to build high-quality web apps with best practices - img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg + # - url: https://testdriven.io/courses/tdd-fastapi/ + # title: Learn to build high-quality web apps with best practices + # img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg - url: https://lambdatest.com/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage title: LambdaTest, AI-Powered Cloud-based Test Orchestration Platform img: https://fastapi.tiangolo.com/img/sponsors/lambdatest.png diff --git a/docs/en/docs/advanced/index.md b/docs/en/docs/advanced/index.md index 36f0720c0..47385e2c6 100644 --- a/docs/en/docs/advanced/index.md +++ b/docs/en/docs/advanced/index.md @@ -19,18 +19,3 @@ And it's possible that for your use case, the solution is in one of them. You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank}. And the next sections assume you already read it, and assume that you know those main ideas. - -## External Courses - -Although the [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} and this **Advanced User Guide** are written as a guided tutorial (like a book) and should be enough for you to **learn FastAPI**, you might want to complement it with additional courses. - -Or it might be the case that you just prefer to take other courses because they adapt better to your learning style. - -Some course providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**. - -And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good learning experience** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇 - -You might want to try their courses: - -* Talk Python Training -* Test-Driven Development From ab22979dc566619f72eb989aacb84c95539ae5a4 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 3 Mar 2025 14:33:58 +0000 Subject: [PATCH 002/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0679ce8a1..72c47d4fb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* 🔧 Update sponsors: pause TestDriven. PR [#13446](https://github.com/fastapi/fastapi/pull/13446) by [@tiangolo](https://github.com/tiangolo). + ## 0.115.11 ### Fixes From 8c94e97c89f617ad808d8ca24da6e52a238bcee9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 13:18:57 +0100 Subject: [PATCH 003/455] =?UTF-8?q?=E2=AC=86=20Bump=20ruff=20to=200.9.4=20?= =?UTF-8?q?(#13299)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ⬆ Bump ruff from 0.6.4 to 0.9.4 Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.4 to 0.9.4. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.6.4...0.9.4) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * update pre-commit accordingly and make formatting changes * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alejandra <90076947+alejsdev@users.noreply.github.com> Co-authored-by: svlandeg Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- fastapi/dependencies/utils.py | 42 +++++++-------- fastapi/openapi/utils.py | 12 ++--- fastapi/routing.py | 24 ++++----- requirements-docs-tests.txt | 2 +- scripts/translate.py | 12 ++--- tests/test_enforce_once_required_parameter.py | 6 +-- tests/test_generic_parameterless_depends.py | 4 +- tests/test_repeated_dependency_schema.py | 6 +-- .../test_tutorial001.py | 48 ++++++++--------- .../test_tutorial002.py | 54 +++++++++---------- .../test_tutorial003.py | 54 +++++++++---------- .../test_sql_databases/test_tutorial002.py | 6 +-- 13 files changed, 136 insertions(+), 136 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 767ef8d9e..05c33a608 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.4 + rev: v0.9.4 hooks: - id: ruff args: diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index e2866b488..d205d17fa 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -133,9 +133,9 @@ def get_param_sub_dependant( def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> Dependant: - assert callable( - depends.dependency - ), "A parameter-less dependency must have a callable dependency" + assert callable(depends.dependency), ( + "A parameter-less dependency must have a callable dependency" + ) return get_sub_dependant(depends=depends, dependency=depends.dependency, path=path) @@ -302,9 +302,9 @@ def get_dependant( type_annotation=param_details.type_annotation, dependant=dependant, ): - assert ( - param_details.field is None - ), f"Cannot specify multiple FastAPI annotations for {param_name!r}" + assert param_details.field is None, ( + f"Cannot specify multiple FastAPI annotations for {param_name!r}" + ) continue assert param_details.field is not None if isinstance(param_details.field.field_info, params.Body): @@ -439,9 +439,9 @@ def analyze_param( ), ): assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}" - assert ( - field_info is None - ), f"Cannot specify FastAPI annotation for type {type_annotation!r}" + assert field_info is None, ( + f"Cannot specify FastAPI annotation for type {type_annotation!r}" + ) # Handle default assignations, neither field_info nor depends was not found in Annotated nor default value elif field_info is None and depends is None: default_value = value if value is not inspect.Signature.empty else RequiredParam @@ -494,9 +494,9 @@ def analyze_param( field_info=field_info, ) if is_path_param: - assert is_scalar_field( - field=field - ), "Path params must be of one of the supported types" + assert is_scalar_field(field=field), ( + "Path params must be of one of the supported types" + ) elif isinstance(field_info, params.Query): assert ( is_scalar_field(field) @@ -521,9 +521,9 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: elif field_info_in == params.ParamTypes.header: dependant.header_params.append(field) else: - assert ( - field_info_in == params.ParamTypes.cookie - ), f"non-body parameters must be in path, query, header or cookie: {field.name}" + assert field_info_in == params.ParamTypes.cookie, ( + f"non-body parameters must be in path, query, header or cookie: {field.name}" + ) dependant.cookie_params.append(field) @@ -782,9 +782,9 @@ def request_params_to_args( if single_not_embedded_field: field_info = first_field.field_info - assert isinstance( - field_info, params.Param - ), "Params must be subclasses of Param" + assert isinstance(field_info, params.Param), ( + "Params must be subclasses of Param" + ) loc: Tuple[str, ...] = (field_info.in_.value,) v_, errors_ = _validate_value_with_model_field( field=first_field, value=params_to_process, values=values, loc=loc @@ -794,9 +794,9 @@ def request_params_to_args( for field in fields: value = _get_multidict_value(field, received_params) field_info = field.field_info - assert isinstance( - field_info, params.Param - ), "Params must be subclasses of Param" + assert isinstance(field_info, params.Param), ( + "Params must be subclasses of Param" + ) loc = (field_info.in_.value, field.alias) v_, errors_ = _validate_value_with_model_field( field=field, value=value, values=values, loc=loc diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 947eca948..bd8f3c106 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -364,9 +364,9 @@ def get_openapi_path( openapi_response = operation_responses.setdefault( status_code_key, {} ) - assert isinstance( - process_response, dict - ), "An additional response must be a dict" + assert isinstance(process_response, dict), ( + "An additional response must be a dict" + ) field = route.response_fields.get(additional_status_code) additional_field_schema: Optional[Dict[str, Any]] = None if field: @@ -434,9 +434,9 @@ def get_fields_from_routes( route, routing.APIRoute ): if route.body_field: - assert isinstance( - route.body_field, ModelField - ), "A request body must be a Pydantic Field" + assert isinstance(route.body_field, ModelField), ( + "A request body must be a Pydantic Field" + ) body_fields_from_routes.append(route.body_field) if route.response_field: responses_from_routes.append(route.response_field) diff --git a/fastapi/routing.py b/fastapi/routing.py index 8ea4bb219..457481e32 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -504,9 +504,9 @@ class APIRoute(routing.Route): status_code = int(status_code) self.status_code = status_code if self.response_model: - assert is_body_allowed_for_status_code( - status_code - ), f"Status code {status_code} must not have a response body" + assert is_body_allowed_for_status_code(status_code), ( + f"Status code {status_code} must not have a response body" + ) response_name = "Response_" + self.unique_id self.response_field = create_model_field( name=response_name, @@ -537,9 +537,9 @@ class APIRoute(routing.Route): assert isinstance(response, dict), "An additional response must be a dict" model = response.get("model") if model: - assert is_body_allowed_for_status_code( - additional_status_code - ), f"Status code {additional_status_code} must not have a response body" + assert is_body_allowed_for_status_code(additional_status_code), ( + f"Status code {additional_status_code} must not have a response body" + ) response_name = f"Response_{additional_status_code}_{self.unique_id}" response_field = create_model_field( name=response_name, type_=model, mode="serialization" @@ -844,9 +844,9 @@ class APIRouter(routing.Router): ) if prefix: assert prefix.startswith("/"), "A path prefix must start with '/'" - assert not prefix.endswith( - "/" - ), "A path prefix must not end with '/', as the routes will start with '/'" + assert not prefix.endswith("/"), ( + "A path prefix must not end with '/', as the routes will start with '/'" + ) self.prefix = prefix self.tags: List[Union[str, Enum]] = tags or [] self.dependencies = list(dependencies or []) @@ -1256,9 +1256,9 @@ class APIRouter(routing.Router): """ if prefix: assert prefix.startswith("/"), "A path prefix must start with '/'" - assert not prefix.endswith( - "/" - ), "A path prefix must not end with '/', as the routes will start with '/'" + assert not prefix.endswith("/"), ( + "A path prefix must not end with '/', as the routes will start with '/'" + ) else: for r in router.routes: path = getattr(r, "path") # noqa: B009 diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index 331d2a5b3..e7718e61d 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests httpx >=0.23.0,<0.28.0 # For linting and generating docs versions -ruff ==0.6.4 +ruff ==0.9.4 diff --git a/scripts/translate.py b/scripts/translate.py index ce11b3877..9a2136d1b 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -38,9 +38,9 @@ def get_langs() -> dict[str, str]: def generate_lang_path(*, lang: str, path: Path) -> Path: en_docs_path = Path("docs/en/docs") - assert str(path).startswith( - str(en_docs_path) - ), f"Path must be inside {en_docs_path}" + assert str(path).startswith(str(en_docs_path)), ( + f"Path must be inside {en_docs_path}" + ) lang_docs_path = Path(f"docs/{lang}/docs") out_path = Path(str(path).replace(str(en_docs_path), str(lang_docs_path))) return out_path @@ -56,9 +56,9 @@ def translate_page(*, lang: str, path: Path) -> None: lang_prompt_content = lang_prompt_path.read_text() en_docs_path = Path("docs/en/docs") - assert str(path).startswith( - str(en_docs_path) - ), f"Path must be inside {en_docs_path}" + assert str(path).startswith(str(en_docs_path)), ( + f"Path must be inside {en_docs_path}" + ) out_path = generate_lang_path(lang=lang, path=path) out_path.parent.mkdir(parents=True, exist_ok=True) original_content = path.read_text() diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index b64f8341b..30329282f 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -48,7 +48,7 @@ expected_schema = { "type": "array", }, "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error " "Type", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, "required": ["loc", "msg", "type"], "title": "ValidationError", @@ -73,7 +73,7 @@ expected_schema = { "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", }, "422": { "content": { @@ -83,7 +83,7 @@ expected_schema = { } } }, - "description": "Validation " "Error", + "description": "Validation Error", }, }, "summary": "Foo Handler", diff --git a/tests/test_generic_parameterless_depends.py b/tests/test_generic_parameterless_depends.py index fe13ff89b..5aa35320c 100644 --- a/tests/test_generic_parameterless_depends.py +++ b/tests/test_generic_parameterless_depends.py @@ -55,7 +55,7 @@ def test_openapi_schema(): "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", } }, "summary": "A", @@ -67,7 +67,7 @@ def test_openapi_schema(): "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", } }, "summary": "B", diff --git a/tests/test_repeated_dependency_schema.py b/tests/test_repeated_dependency_schema.py index d7d0dfa05..c21829bd9 100644 --- a/tests/test_repeated_dependency_schema.py +++ b/tests/test_repeated_dependency_schema.py @@ -41,7 +41,7 @@ schema = { "type": "array", }, "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error " "Type", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, "required": ["loc", "msg", "type"], "title": "ValidationError", @@ -66,7 +66,7 @@ schema = { "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", }, "422": { "content": { @@ -76,7 +76,7 @@ schema = { } } }, - "description": "Validation " "Error", + "description": "Validation Error", }, }, "summary": "Get Deps", diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py index 72db54bd2..a04dba219 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py @@ -8,31 +8,31 @@ client = TestClient(app) def test_swagger_ui(): response = client.get("/docs") assert response.status_code == 200, response.text - assert ( - '"syntaxHighlight": false' in response.text - ), "syntaxHighlight should be included and converted to JSON" - assert ( - '"dom_id": "#swagger-ui"' in response.text - ), "default configs should be preserved" + assert '"syntaxHighlight": false' in response.text, ( + "syntaxHighlight should be included and converted to JSON" + ) + assert '"dom_id": "#swagger-ui"' in response.text, ( + "default configs should be preserved" + ) assert "presets: [" in response.text, "default configs should be preserved" - assert ( - "SwaggerUIBundle.presets.apis," in response.text - ), "default configs should be preserved" - assert ( - "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text - ), "default configs should be preserved" - assert ( - '"layout": "BaseLayout",' in response.text - ), "default configs should be preserved" - assert ( - '"deepLinking": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showExtensions": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showCommonExtensions": true,' in response.text - ), "default configs should be preserved" + assert "SwaggerUIBundle.presets.apis," in response.text, ( + "default configs should be preserved" + ) + assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, ( + "default configs should be preserved" + ) + assert '"layout": "BaseLayout",' in response.text, ( + "default configs should be preserved" + ) + assert '"deepLinking": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showExtensions": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showCommonExtensions": true,' in response.text, ( + "default configs should be preserved" + ) def test_get_users(): diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py index d06a385b5..ea56b6f21 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py @@ -8,34 +8,34 @@ client = TestClient(app) def test_swagger_ui(): response = client.get("/docs") assert response.status_code == 200, response.text - assert ( - '"syntaxHighlight": false' not in response.text - ), "not used parameters should not be included" - assert ( - '"syntaxHighlight": {"theme": "obsidian"}' in response.text - ), "parameters with middle dots should be included in a JSON compatible way" - assert ( - '"dom_id": "#swagger-ui"' in response.text - ), "default configs should be preserved" + assert '"syntaxHighlight": false' not in response.text, ( + "not used parameters should not be included" + ) + assert '"syntaxHighlight": {"theme": "obsidian"}' in response.text, ( + "parameters with middle dots should be included in a JSON compatible way" + ) + assert '"dom_id": "#swagger-ui"' in response.text, ( + "default configs should be preserved" + ) assert "presets: [" in response.text, "default configs should be preserved" - assert ( - "SwaggerUIBundle.presets.apis," in response.text - ), "default configs should be preserved" - assert ( - "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text - ), "default configs should be preserved" - assert ( - '"layout": "BaseLayout",' in response.text - ), "default configs should be preserved" - assert ( - '"deepLinking": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showExtensions": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showCommonExtensions": true,' in response.text - ), "default configs should be preserved" + assert "SwaggerUIBundle.presets.apis," in response.text, ( + "default configs should be preserved" + ) + assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, ( + "default configs should be preserved" + ) + assert '"layout": "BaseLayout",' in response.text, ( + "default configs should be preserved" + ) + assert '"deepLinking": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showExtensions": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showCommonExtensions": true,' in response.text, ( + "default configs should be preserved" + ) def test_get_users(): diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py index 187e89ace..926bbb14f 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py @@ -8,34 +8,34 @@ client = TestClient(app) def test_swagger_ui(): response = client.get("/docs") assert response.status_code == 200, response.text - assert ( - '"deepLinking": false,' in response.text - ), "overridden configs should be preserved" - assert ( - '"deepLinking": true' not in response.text - ), "overridden configs should not include the old value" - assert ( - '"syntaxHighlight": false' not in response.text - ), "not used parameters should not be included" - assert ( - '"dom_id": "#swagger-ui"' in response.text - ), "default configs should be preserved" + assert '"deepLinking": false,' in response.text, ( + "overridden configs should be preserved" + ) + assert '"deepLinking": true' not in response.text, ( + "overridden configs should not include the old value" + ) + assert '"syntaxHighlight": false' not in response.text, ( + "not used parameters should not be included" + ) + assert '"dom_id": "#swagger-ui"' in response.text, ( + "default configs should be preserved" + ) assert "presets: [" in response.text, "default configs should be preserved" - assert ( - "SwaggerUIBundle.presets.apis," in response.text - ), "default configs should be preserved" - assert ( - "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text - ), "default configs should be preserved" - assert ( - '"layout": "BaseLayout",' in response.text - ), "default configs should be preserved" - assert ( - '"showExtensions": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showCommonExtensions": true,' in response.text - ), "default configs should be preserved" + assert "SwaggerUIBundle.presets.apis," in response.text, ( + "default configs should be preserved" + ) + assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, ( + "default configs should be preserved" + ) + assert '"layout": "BaseLayout",' in response.text, ( + "default configs should be preserved" + ) + assert '"showExtensions": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showCommonExtensions": true,' in response.text, ( + "default configs should be preserved" + ) def test_get_users(): diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial002.py b/tests/test_tutorial/test_sql_databases/test_tutorial002.py index 68c1966f5..79e48c1c3 100644 --- a/tests/test_tutorial/test_sql_databases/test_tutorial002.py +++ b/tests/test_tutorial/test_sql_databases/test_tutorial002.py @@ -71,9 +71,9 @@ def test_crud_app(client: TestClient): assert response.json() == snapshot( {"age": 30, "id": IsInt(), "name": "Dead Pond"} ) - assert ( - response.json()["id"] != 9000 - ), "The ID should be generated by the database" + assert response.json()["id"] != 9000, ( + "The ID should be generated by the database" + ) # Read a hero hero_id = response.json()["id"] From daf6820307816571433824617f69f9ac51621193 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 6 Mar 2025 12:19:24 +0000 Subject: [PATCH 004/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 72c47d4fb..52edd7773 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* ⬆ Bump ruff to 0.9.4. PR [#13299](https://github.com/fastapi/fastapi/pull/13299) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update sponsors: pause TestDriven. PR [#13446](https://github.com/fastapi/fastapi/pull/13446) by [@tiangolo](https://github.com/tiangolo). ## 0.115.11 From a592e8ad4dba1941a3619bd270ccb0f026ec5ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=C6=B0=C6=A1ng=20T=E1=BA=A5n=20Th=C3=A0nh?= <51350651+ptt3199@users.noreply.github.com> Date: Fri, 7 Mar 2025 10:24:13 +0700 Subject: [PATCH 005/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Vietnamese=20trans?= =?UTF-8?q?lation=20for=20`docs/vi/docs/deployment/cloud.md`=20(#13407)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sofie Van Landeghem Co-authored-by: Dinh Van Luc <39489075+MrL8199@users.noreply.github.com> --- docs/vi/docs/deployment/cloud.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 docs/vi/docs/deployment/cloud.md diff --git a/docs/vi/docs/deployment/cloud.md b/docs/vi/docs/deployment/cloud.md new file mode 100644 index 000000000..9ab72769d --- /dev/null +++ b/docs/vi/docs/deployment/cloud.md @@ -0,0 +1,17 @@ +# Triển khai FastAPI trên các Dịch vụ Cloud + +Bạn có thể sử dụng **bất kỳ nhà cung cấp dịch vụ cloud** nào để triển khai ứng dụng FastAPI của mình. + +Trong hầu hết các trường hợp, các nhà cung cấp dịch vụ cloud lớn đều có hướng dẫn triển khai FastAPI với họ. + +## Nhà cung cấp dịch vụ Cloud - Nhà tài trợ +Một vài nhà cung cấp dịch vụ cloud ✨ [**tài trợ cho FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, điều này giúp đảm bảo sự phát triển liên tục và khỏe mạnh của FastAPI và hệ sinh thái của nó. + +Thêm nữa, điều này cũng thể hiện cam kết thực sự của họ đối với FastAPI và **cộng đồng người dùng** (bạn), vì họ không chỉ muốn cung cấp cho bạn một **dịch vụ tốt** mà còn muốn đảm bảo rằng bạn có một **framework tốt và bền vững**, đó chính là FastAPI. 🙇 + +Bạn có thể thử các dịch vụ của họ và làm theo hướng dẫn của họ: + +* Platform.sh +* Porter +* Coherence +* Render From 0c36a7ac0587c05e3f8d6b54e65565190f68e580 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 7 Mar 2025 03:24:33 +0000 Subject: [PATCH 006/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 52edd7773..e9bccf0fb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/cloud.md`. PR [#13407](https://github.com/fastapi/fastapi/pull/13407) by [@ptt3199](https://github.com/ptt3199). + ### Internal * ⬆ Bump ruff to 0.9.4. PR [#13299](https://github.com/fastapi/fastapi/pull/13299) by [@dependabot[bot]](https://github.com/apps/dependabot). From a88a6050a6423630ac141a862742fca79333d516 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 04:24:42 +0100 Subject: [PATCH 007/455] =?UTF-8?q?=E2=AC=86=20Bump=20black=20from=2024.10?= =?UTF-8?q?.0=20to=2025.1.0=20(#13436)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [black](https://github.com/psf/black) from 24.10.0 to 25.1.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index cd2e4e58e..8812e27f9 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -14,6 +14,6 @@ cairosvg==2.7.1 mkdocstrings[python]==0.26.1 griffe-typingdoc==0.2.7 # For griffe, it formats with black -black==24.10.0 +black==25.1.0 mkdocs-macros-plugin==1.3.7 markdown-include-variants==0.0.4 From 79bc28fab4b33c7822a5a30408ec0fec69d6630c Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 7 Mar 2025 03:25:02 +0000 Subject: [PATCH 008/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e9bccf0fb..86f9ab0cb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump black from 24.10.0 to 25.1.0. PR [#13436](https://github.com/fastapi/fastapi/pull/13436) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ruff to 0.9.4. PR [#13299](https://github.com/fastapi/fastapi/pull/13299) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update sponsors: pause TestDriven. PR [#13446](https://github.com/fastapi/fastapi/pull/13446) by [@tiangolo](https://github.com/tiangolo). From c46e4a1b1424cef38349627a32b4419d0a2a1612 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 04:25:10 +0100 Subject: [PATCH 009/455] =?UTF-8?q?=E2=AC=86=20Bump=20sqlmodel=20from=200.?= =?UTF-8?q?0.22=20to=200.0.23=20(#13437)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sqlmodel](https://github.com/fastapi/sqlmodel) from 0.0.22 to 0.0.23. - [Release notes](https://github.com/fastapi/sqlmodel/releases) - [Changelog](https://github.com/fastapi/sqlmodel/blob/main/docs/release-notes.md) - [Commits](https://github.com/fastapi/sqlmodel/compare/0.0.22...0.0.23) --- updated-dependencies: - dependency-name: sqlmodel dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-tests.txt b/requirements-tests.txt index 4a15844e4..6a870add6 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -4,7 +4,7 @@ pytest >=7.1.3,<9.0.0 coverage[toml] >= 6.5.0,< 8.0 mypy ==1.8.0 dirty-equals ==0.8.0 -sqlmodel==0.0.22 +sqlmodel==0.0.23 flask >=1.1.2,<4.0.0 anyio[trio] >=3.2.1,<5.0.0 PyJWT==2.8.0 From 643d2845de09a437b955a163ab25eb0887bfd0e1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 7 Mar 2025 03:25:46 +0000 Subject: [PATCH 010/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 86f9ab0cb..ee987b544 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump sqlmodel from 0.0.22 to 0.0.23. PR [#13437](https://github.com/fastapi/fastapi/pull/13437) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump black from 24.10.0 to 25.1.0. PR [#13436](https://github.com/fastapi/fastapi/pull/13436) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ruff to 0.9.4. PR [#13299](https://github.com/fastapi/fastapi/pull/13299) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update sponsors: pause TestDriven. PR [#13446](https://github.com/fastapi/fastapi/pull/13446) by [@tiangolo](https://github.com/tiangolo). From 3565ea00b6a3193743dddb98bdd47f878374ae64 Mon Sep 17 00:00:00 2001 From: Lee Yesong Date: Mon, 10 Mar 2025 21:29:03 +0900 Subject: [PATCH 011/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Korean=20translati?= =?UTF-8?q?on=20for=20`docs/ko/docs/tutorial/security/oauth2-jwt.md`=20(#1?= =?UTF-8?q?3333)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ko/docs/tutorial/security/oauth2-jwt.md | 273 +++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 docs/ko/docs/tutorial/security/oauth2-jwt.md diff --git a/docs/ko/docs/tutorial/security/oauth2-jwt.md b/docs/ko/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 000000000..d8bac8346 --- /dev/null +++ b/docs/ko/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,273 @@ +# 패스워드 해싱을 이용한 OAuth2, JWT 토큰을 사용하는 Bearer 인증 + +모든 보안 흐름을 구성했으므로, 이제 JWT 토큰과 패스워드 해싱을 사용해 애플리케이션을 안전하게 만들 것입니다. + +이 코드는 실제로 애플리케이션에서 패스워드를 해싱하여 DB에 저장하는 등의 작업에 활용할 수 있습니다. + +이전 장에 이어서 시작해 봅시다. + +## JWT + +JWT 는 "JSON Web Tokens" 을 의미합니다. + +JSON 객체를 공백이 없는 긴 문자열로 인코딩하는 표준이며, 다음과 같은 형태입니다: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +JWT는 암호화되지 않아 누구든지 토큰에서 정보를 복원할 수 있습니다. + +하지만 JWT는 서명되어 있습니다. 그래서 자신이 발급한 토큰을 받았을 때, 실제로 자신이 발급한게 맞는지 검증할 수 있습니다. + +만료 기간이 일주일인 토큰을 발행했다고 가정해 봅시다. 다음 날 사용자가 토큰을 가져왔을 때, 그 사용자가 시스템에 여전히 로그인되어 있다는 것을 알 수 있습니다. + +일주일 뒤에는 토큰이 만료될 것이고, 사용자는 인가되지 않아 새 토큰을 받기 위해 다시 로그인해야 할 것입니다. 만약 사용자(또는 제3자)가 토큰을 수정하거나 만료일을 변경하면, 서명이 일치하지 않기 때문에 알아챌 수 있을 것입니다. + +만약 JWT 토큰을 다뤄보고, 작동 방식도 알아보고 싶다면 https://jwt.io 을 확인하십시오. + +## `PyJWT` 설치 + +파이썬으로 JWT 토큰을 생성하고 검증하려면 `PyJWT` 를 설치해야 합니다. + +[가상환경](../../virtual-environments.md){.internal-link target=_blank} 을 만들고 활성화한 다음 `pyjwt` 를 설치하십시오: + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// info | 참고 + +RSA나 ECDSA 같은 전자 서명 알고리즘을 사용하려면, `pyjwt[crypto]`라는 암호화 라이브러리 의존성을 설치해야 합니다. + +더 자세한 내용은 PyJWT 설치 에서 확인할 수 있습니다. + +/// + +## 패스워드 해싱 + +"해싱(Hashing)"은 어떤 내용(여기서는 패스워드)을 해석할 수 없는 일련의 바이트 집합(단순 문자열)으로 변환하는 것을 의미합니다. + +동일한 내용(똑같은 패스워드)을 해싱하면 동일한 문자열을 얻습니다. + +하지만 그 문자열을 다시 패스워드로 되돌릴 수는 없습니다. + +### 패스워드를 해싱하는 이유 + +데이터베이스를 탈취당하더라도, 침입자는 사용자의 평문 패스워드 대신 해시 값만 얻을 수 있습니다. + +따라서 침입자는 훔친 사용자 패스워드를 다른 시스템에서 활용할 수 없습니다. (대다수 사용자가 여러 시스템에서 동일한 패스워드를 사용하기 때문에 평문 패스워드가 유출되면 위험합니다.) + +## `passlib` 설치 + +PassLib는 패스워드 해시를 다루는 훌륭한 파이썬 패키지입니다. + +많은 안전한 해시 알고리즘과 도구들을 지원합니다. + +추천하는 알고리즘은 "Bcrypt"입니다. + +[가상환경](../../virtual-environments.md){.internal-link target=_blank} 을 만들고 활성화한 다음 PassLib와 Bcrypt를 설치하십시오: + +
+ +```console +$ pip install "passlib[bcrypt]" + +---> 100% +``` + +
+ +/// tip | 팁 + +`passlib`를 사용하여, **Django**, **Flask** 의 보안 플러그인이나 다른 도구로 생성한 패스워드를 읽을 수 있도록 설정할 수도 있습니다. + +예를 들자면, FastAPI 애플리케이션과 Django 애플리케이션이 같은 데이터베이스에서 데이터를 공유할 수 있습니다. 또는 같은 데이터베이스를 사용하여 Django 애플리케이션을 점진적으로 마이그레이션 할 수도 있습니다. + +그리고 사용자는 FastAPI 애플리케이션과 Django 애플리케이션에 동시에 로그인할 수 있습니다. + +/// + +## 패스워드의 해시와 검증 + +필요한 도구를 `passlib`에서 임포트합니다. + +PassLib "컨텍스트(context)"를 생성합니다. 이것은 패스워드를 해싱하고 검증하는데 사용합니다. + +/// tip | 팁 + +PassLib 컨텍스트는 다양한 해싱 알고리즘을 사용할 수 있는 기능을 제공하며, 더 이상 사용이 권장되지 않는 오래된 해싱 알고리즘을 검증하는 기능도 포함되어 있습니다. + +예를 들어, 다른 시스템(Django 같은)에서 생성한 패스워드를 읽고 검증할 수 있으며, 새로운 패스워드를 Bcrypt 같은 다른 알고리즘으로 해싱할 수도 있습니다. + +그리고 동시에 그런 모든 알고리즘과 호환성을 유지합니다. + +/// + +사용자로부터 받은 패스워드를 해싱하는 유틸리티 함수를 생성합니다. + +그리고 받은 패스워드가 저장된 해시와 일치하는지 검증하는 또 다른 유틸리티 함수도 생성합니다. + +그리고 사용자를 인증하고 반환하는 또 다른 함수도 생성합니다. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} + +/// note + +새로운 (가짜) 데이터베이스 `fake_users_db`를 확인하면, 해시 처리된 패스워드가 어떻게 생겼는지 볼 수 있습니다: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`. + +/// + +## JWT 토큰 처리 + +설치된 모듈을 임포트 합니다. + +JWT 토큰 서명에 사용될 임의의 비밀키를 생성합니다. + +안전한 임의의 비밀키를 생성하려면 다음 명령어를 사용하십시오: + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +그리고 생성한 비밀키를 복사해 변수 `SECRET_KEY`에 대입합니다. (이 예제의 변수 값을 그대로 사용하지 마십시오.) + +JWT 토큰을 서명하는 데 사용될 알고리즘을 위한 변수 `ALGORITHM` 을 생성하고 `"HS256"` 으로 설정합니다. + +토큰 만료 기간을 위한 변수를 생성합니다. + +응답을 위한 토큰 엔드포인트에 사용될 Pydantic 모델을 정의합니다. + +새 액세스 토큰을 생성하기 위한 유틸리티 함수를 생성합니다. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} + +## 의존성 수정 + +`get_current_user` 함수를 이전과 동일한 토큰을 받도록 수정하되, 이번에는 JWT 토큰을 사용하도록 합니다. + +받은 토큰을 디코딩하여 검증한 후 현재 사용자를 반환합니다. + +토큰이 유효하지 않다면 HTTP 오류를 반환합니다. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} + +## `/token` 경로 작업 수정 + +토큰의 만료 시각을 설정하기 위해 `timedelta` 를 생성합니다. + +실제 JWT 액세스 토큰을 생성하여 반환합니다. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} + +### JWT "주체(subject)" `sub`에 대한 기술 세부 사항 + +JWT 명세에 따르면 토큰의 주체를 포함하는 `sub`라는 키가 있습니다. + +사용 여부는 선택사항이지만, 사용자의 식별 정보를 저장할 수 있으므로 여기서는 이를 사용합니다. + +JWT는 사용자를 식별하고 사용자가 API를 직접 사용할 수 있도록 허용하는 것 외에도 다른 용도로 사용될 수도 있습니다. + +예를 들어 "자동차"나 "블로그 게시물"을 식별하는 데 사용할 수 있습니다. + +그리고 "자동차를 운전하다"나 "블로그 게시물을 수정하다"처럼 해당 엔터티에 대한 권한을 추가할 수 있습니다. + +그 후 이 JWT 토큰을 사용자(또는 봇)에게 제공하면, 그들은 계정을 따로 만들 필요 없이 API가 생성한 JWT 토큰만으로 작업(자동차 운전 또는 블로그 게시물 편집)을 수행할 수 있습니다. + +이러한 개념을 활용하면 JWT는 훨씬 더 복잡한 시나리오에도 사용할 수 있습니다. + +이 경우 여러 엔터티가 동일한 ID를 가질 수 있습니다. 예를 들어 foo라는 ID를 가진 사용자, 자동차, 블로그 게시물이 있을 수 있습니다. + +그래서 ID 충돌을 방지하기 위해, 사용자의 JWT 토큰을 생성할 때 접두사로 `sub` 키를 추가할 수 있습니다. 예를 들어 `username:` 을 붙이는 방식입니다. 이 예제에서는 `sub` 값이 `username:johndoe`이 될 수 있습니다. + +가장 중요한 점은 `sub` 키는 전체 애플리케이션에서 고유한 식별자가 되어야 하며 문자열이어야 한다는 점입니다. + +## 확인해봅시다 + +서버를 실행하고 문서로 이동하십시오: http://127.0.0.1:8000/docs. + +다음과 같은 사용자 인터페이스를 볼 수 있습니다: + + + +이전과 같은 방법으로 애플리케이션에 인증하십시오. + +다음 인증 정보를 사용하십시오: + +Username: `johndoe` +Password: `secret` + +/// check + +코드 어디에도 평문 패스워드 "`secret`" 이 없다는 점에 유의하십시오. 해시된 버전만 있습니다. + +/// + + + +`/users/me/` 를 호출하면 다음과 같은 응답을 얻을 수 있습니다: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +개발자 도구를 열어보면 전송된 데이터에 토큰만 포함된 것을 확인할 수 있습니다. 패스워드는 사용자를 인증하고 액세스 토큰을 받기 위한 첫 번째 요청에만 전송되며, 이후에는 전송되지 않습니다: + + + +/// note + +`Bearer `로 시작하는 `Authorization` 헤더에 주목하십시오. + +/// + +## `scopes` 의 고급 사용법 + +OAuth2는 "스코프(scopes)" 라는 개념을 갖고 있습니다. + +이를 사용하여 JWT 토큰에 특정 권한 집합을 추가할 수 있습니다. + +그 후 이 토큰을 사용자에게 직접 제공하거나 제3자에게 제공하여, 특정 제한사항 하에있는 API와 통신하도록 할 수 있습니다. + +**FastAPI** 에서의 사용 방법과 통합 방식은 **심화 사용자 안내서** 에서 자세히 배울 수 있습니다. + +## 요약 + +지금까지 살펴본 내용을 바탕으로, OAuth2와 JWT 같은 표준을 사용하여 안전한 **FastAPI** 애플리케이션을 만들 수 있습니다. + +거의 모든 프레임워크에서 보안 처리는 상당히 복잡한 주제입니다. + +이를 단순화하는 많은 패키지는 데이터 모델, 데이터베이스, 사용 가능한 기능들에 대해 여러 제약이 있습니다. 그리고 지나치게 단순화하는 일부 패키지들은 심각한 보안 결함을 가질 수도 있습니다. + +--- + +**FastAPI** 는 어떤 데이터베이스, 데이터 모델, 도구도 강요하지 않습니다. + +프로젝트에 가장 적합한 것을 선택할 수 있는 유연성을 제공합니다. + +그리고 `passlib` 와 `PyJWT` 처럼 잘 관리되고 널리 사용되는 패키지들을 바로 사용할 수 있습니다. **FastAPI** 는 외부 패키지 통합을 위해 복잡한 메커니즘이 필요하지 않기 때문입니다. + +그러나 유연성, 견고성, 보안성을 해치지 않으면서 과정을 단순화할 수 있는 도구들을 제공합니다. + +그리고 OAuth2와 같은 표준 프로토콜을 비교적 간단한 방법으로 구현하고 사용할 수 있습니다. + +더 세분화된 권한 체계를 위해 OAuth2의 "스코프"를 사용하는 방법은 **심화 사용자 안내서**에서 더 자세히 배울 수 있습니다. OAuth2의 스코프는 제3자 애플리케이션이 사용자를 대신해 그들의 API와 상호작용하도록 권한을 부여하기 위해, Facebook, Google, GitHub, Microsoft, Twitter 등의 많은 대형 인증 제공업체들이 사용하는 메커니즘입니다. From e988050f79b32c9444fba8d014d0c69cd7a4b6c7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 10 Mar 2025 12:29:25 +0000 Subject: [PATCH 012/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ee987b544..c900dc918 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). * 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/cloud.md`. PR [#13407](https://github.com/fastapi/fastapi/pull/13407) by [@ptt3199](https://github.com/ptt3199). ### Internal From d3cfe72cd7f5148ac89d5f411391bb565f25662a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 19 Mar 2025 14:33:41 +0300 Subject: [PATCH 013/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#13493)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/people.yml | 578 +++++++++++++++++----------------------- 1 file changed, 243 insertions(+), 335 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 7f910ab34..4afce19b5 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,11 +1,11 @@ maintainers: - login: tiangolo - answers: 1894 + answers: 1897 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo experts: - login: tiangolo - count: 1894 + count: 1897 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: github-actions @@ -13,11 +13,11 @@ experts: avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 url: https://github.com/apps/github-actions - login: Kludex - count: 645 + count: 654 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: jgould22 - count: 250 + count: 263 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: dmontagu @@ -25,7 +25,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu - login: YuriiMotov - count: 223 + count: 238 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov - login: Mause @@ -34,7 +34,7 @@ experts: url: https://github.com/Mause - login: ycd count: 217 - avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=29682e4b6ac7d5293742ccf818188394b9a82972&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 url: https://github.com/ycd - login: JarroVGIT count: 192 @@ -46,14 +46,14 @@ experts: url: https://github.com/euri10 - login: iudeen count: 128 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 url: https://github.com/iudeen - login: phy25 count: 126 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 85 + count: 91 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: raphaelauv @@ -69,7 +69,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik - login: n8sty - count: 66 + count: 67 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty - login: falkben @@ -80,46 +80,46 @@ experts: count: 50 avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 url: https://github.com/acidjunk -- login: sm-Fifteen - count: 49 - avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 - url: https://github.com/sm-Fifteen - login: yinziyan1206 count: 49 avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 url: https://github.com/yinziyan1206 +- login: sm-Fifteen + count: 49 + avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 + url: https://github.com/sm-Fifteen +- login: luzzodev + count: 48 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: adriangb count: 46 avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 url: https://github.com/adriangb -- login: Dustyposa - count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 - url: https://github.com/Dustyposa - login: insomnes count: 45 avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 url: https://github.com/insomnes -- login: odiseo0 - count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 - url: https://github.com/odiseo0 +- login: Dustyposa + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 + url: https://github.com/Dustyposa - login: frankie567 count: 43 avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4 url: https://github.com/frankie567 +- login: odiseo0 + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 + url: https://github.com/odiseo0 +- login: sinisaos + count: 40 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos - login: includeamin count: 40 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 url: https://github.com/includeamin -- login: sinisaos - count: 39 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos -- login: luzzodev - count: 37 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev - login: chbndrhnns count: 37 avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 @@ -160,10 +160,10 @@ experts: count: 22 avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 url: https://github.com/nymous -- login: acnebs +- login: connebs count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/9054108?v=4 - url: https://github.com/acnebs + avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=e151d5f545a3395136d711c227c22032fda67cfa&v=4 + url: https://github.com/connebs - login: chrisK824 count: 22 avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 @@ -188,14 +188,14 @@ experts: count: 19 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 -- login: sehraramiz - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz - login: zoliknemet count: 18 avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 url: https://github.com/zoliknemet +- login: sehraramiz + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz - login: retnikt count: 18 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 @@ -216,6 +216,10 @@ experts: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=e19427d8dc296d6950e9c424adacc92d37496fe9&v=4 url: https://github.com/nkhitrov +- login: alv2017 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: jonatasoli count: 16 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 @@ -224,6 +228,10 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 url: https://github.com/dstlny +- login: abhint + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 + url: https://github.com/abhint - login: ceb10n count: 15 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 @@ -236,100 +244,96 @@ experts: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/33907262?u=2721fb37014d50daf473267c808aa678ecaefe09&v=4 url: https://github.com/simondale00 -- login: ghost - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4 - url: https://github.com/ghost -- login: abhint - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 - url: https://github.com/abhint last_month_experts: -- login: Kludex - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: YuriiMotov - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov -- login: sehraramiz - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz -- login: luzzodev - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev -- login: yokwejuste - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 - url: https://github.com/yokwejuste +- login: jgould22 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: alv2017 - count: 3 + count: 10 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -- login: Trinkes - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 - url: https://github.com/Trinkes -- login: PREPONDERANCE - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE -- login: nbx3 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: XiaoXinYo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 - url: https://github.com/XiaoXinYo -- login: iloveitaly - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly -three_months_experts: - login: luzzodev - count: 33 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev +- login: YuriiMotov + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov +- login: Kludex + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: JavierSanchezCastro + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: tiangolo + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: vtgn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 + url: https://github.com/vtgn +three_months_experts: - login: YuriiMotov count: 31 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov - login: Kludex - count: 24 + count: 25 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex +- login: luzzodev + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: alv2017 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 +- login: jgould22 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: sehraramiz count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz -- login: estebanx64 - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 -- login: yvallois - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois +- login: JavierSanchezCastro + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: tiangolo + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo - login: yokwejuste count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste -- login: jgould22 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: alv2017 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 url: https://github.com/viniciusCalcantara +- login: SobikXexe + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 + url: https://github.com/SobikXexe +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: vtgn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 + url: https://github.com/vtgn - login: Trinkes count: 2 avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 @@ -344,117 +348,81 @@ three_months_experts: url: https://github.com/nbx3 - login: XiaoXinYo count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 url: https://github.com/XiaoXinYo -- login: JavierSanchezCastro - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro - login: iloveitaly count: 2 avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 url: https://github.com/iloveitaly -- login: LincolnPuzey - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18750802?v=4 - url: https://github.com/LincolnPuzey -- login: Knighthawk-Leo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72437494?u=27c68db94a3107b605e603cc136f4ba83f0106d5&v=4 - url: https://github.com/Knighthawk-Leo -- login: gelezo43 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 - url: https://github.com/gelezo43 -- login: AliYmn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=98c1fca46c7e4dabe8c39d17b5e55d1511d41cf9&v=4 - url: https://github.com/AliYmn -- login: RichieB2B - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 - url: https://github.com/RichieB2B -- login: Synrom - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 - url: https://github.com/Synrom -- login: iiotsrc - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 - url: https://github.com/iiotsrc -- login: Kfir-G - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 - url: https://github.com/Kfir-G six_months_experts: - login: YuriiMotov - count: 72 + count: 63 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov +- login: luzzodev + count: 48 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: Kludex - count: 40 + count: 48 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex -- login: luzzodev - count: 37 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev - login: sinisaos - count: 37 + count: 23 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos +- login: jgould22 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: JavierSanchezCastro - count: 16 + count: 17 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: alv2017 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: Kfir-G count: 13 avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 url: https://github.com/Kfir-G -- login: tiangolo - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo - login: sehraramiz count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz - login: ceb10n - count: 10 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n - login: estebanx64 count: 7 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 +- login: tiangolo + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo - login: yvallois count: 6 avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 url: https://github.com/yvallois -- login: n8sty - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty -- login: TomFaulkner - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/14956620?v=4 - url: https://github.com/TomFaulkner - login: yokwejuste count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste -- login: jgould22 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: alv2017 +- login: n8sty count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 url: https://github.com/viniciusCalcantara +- login: SobikXexe + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 + url: https://github.com/SobikXexe - login: pawelad count: 3 avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 @@ -467,26 +435,18 @@ six_months_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 url: https://github.com/Isuxiz -- login: bertomaniac - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 - url: https://github.com/bertomaniac -- login: PhysicallyActive - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 - url: https://github.com/PhysicallyActive - login: Minibrams count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 url: https://github.com/Minibrams -- login: AIdjis - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 - url: https://github.com/AIdjis -- login: svlandeg - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: vtgn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 + url: https://github.com/vtgn - login: Trinkes count: 2 avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 @@ -499,26 +459,10 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 url: https://github.com/nbx3 -- login: yanggeorge - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 - url: https://github.com/yanggeorge - login: XiaoXinYo count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 url: https://github.com/XiaoXinYo -- login: pythonweb2 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 -- login: slafs - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs -- login: AmirHmZz - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/38752106?u=07f80e451bda00a9492bbc764e49d24ad3ada8cc&v=4 - url: https://github.com/AmirHmZz - login: iloveitaly count: 2 avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 @@ -527,10 +471,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/18750802?v=4 url: https://github.com/LincolnPuzey -- login: alejsdev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 - url: https://github.com/alejsdev - login: Knighthawk-Leo count: 2 avatarUrl: https://avatars.githubusercontent.com/u/72437494?u=27c68db94a3107b605e603cc136f4ba83f0106d5&v=4 @@ -559,10 +499,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 url: https://github.com/Synrom -- login: ecly - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/8410422?v=4 - url: https://github.com/ecly - login: iiotsrc count: 2 avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 @@ -575,14 +511,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/47495003?u=6e225cb42c688d0cd70e65c6baedb9f5922b1178&v=4 url: https://github.com/jd-solanki -- login: AumGupta - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86357151?u=7d05aa606c0611a18f4db16cf26361ce10a6e195&v=4 - url: https://github.com/AumGupta -- login: DeoLeung - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 - url: https://github.com/DeoLeung - login: Reemyos count: 2 avatarUrl: https://avatars.githubusercontent.com/u/44867003?v=4 @@ -591,77 +519,61 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 url: https://github.com/deight93 +- login: PhysicallyActive + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 + url: https://github.com/PhysicallyActive - login: Jkrox count: 2 avatarUrl: https://avatars.githubusercontent.com/u/83181939?u=d6a922d97129f7f3916d6a1c166bc011b3a72b7f&v=4 url: https://github.com/Jkrox -- login: mmzeynalli - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/33568903?u=19efd0c0722730b83a70b7c86c36e5b7d83e07d2&v=4 - url: https://github.com/mmzeynalli -- login: ddahan - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 - url: https://github.com/ddahan - login: jfeaver count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1091338?u=0bcba366447d8fadad63f6705a52d128da4c7ec2&v=4 url: https://github.com/jfeaver -- login: Wurstnase - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/8709415?u=f479af475a97aee9a1dab302cfc35d07e9ea245f&v=4 - url: https://github.com/Wurstnase - login: tristan count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1412?u=aab8aaa4cc0f1210ac45fc93873a5909d314c965&v=4 url: https://github.com/tristan -- login: chandanch - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/8663552?u=afc484bc0a952c83f1fb6a1583cda443f807cd66&v=4 - url: https://github.com/chandanch -- login: rvishruth - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/79176273?v=4 - url: https://github.com/rvishruth -- login: mattmess1221 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=723662989f2027755e67d200137c13c53ae154ac&v=4 - url: https://github.com/mattmess1221 one_year_experts: - login: YuriiMotov - count: 223 + count: 214 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov - login: Kludex - count: 81 + count: 66 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex +- login: luzzodev + count: 48 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: sinisaos + count: 40 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos - login: JavierSanchezCastro - count: 47 + count: 39 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: jgould22 - count: 42 + count: 35 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: sinisaos - count: 39 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos -- login: luzzodev - count: 37 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev - login: tiangolo count: 24 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: alv2017 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: n8sty - count: 23 + count: 15 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty - login: estebanx64 - count: 19 + count: 15 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 - login: ceb10n @@ -682,10 +594,10 @@ one_year_experts: url: https://github.com/Kfir-G - login: mattmess1221 count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=723662989f2027755e67d200137c13c53ae154ac&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 url: https://github.com/mattmess1221 - login: hasansezertasan - count: 10 + count: 8 avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 url: https://github.com/hasansezertasan - login: AIdjis @@ -704,22 +616,18 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 url: https://github.com/pythonweb2 -- login: acidjunk - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk - login: gustavosett count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/99373133?u=1739ca547c3d200f1b72450520bce46a97aab184&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/99373133?u=1382fe27034a0179f07cf989f63c4f23017f043c&v=4 url: https://github.com/gustavosett -- login: binbjz - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/8213913?u=22b68b7a0d5bf5e09c02084c0f5f53d7503114cd&v=4 - url: https://github.com/binbjz - login: chyok count: 5 avatarUrl: https://avatars.githubusercontent.com/u/32629225?u=3b7c30e8a09426a1b9284f6e8a0ae53a525596bf&v=4 url: https://github.com/chyok +- login: svlandeg + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg - login: TomFaulkner count: 4 avatarUrl: https://avatars.githubusercontent.com/u/14956620?v=4 @@ -728,42 +636,34 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste -- login: DeoLeung +- login: acidjunk count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 - url: https://github.com/DeoLeung -- login: flo-at - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/564288?v=4 - url: https://github.com/flo-at -- login: GodMoonGoodman - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/29688727?u=7b251da620d999644c37c1feeb292d033eed7ad6&v=4 - url: https://github.com/GodMoonGoodman + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk - login: bertomaniac count: 4 avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 url: https://github.com/bertomaniac -- login: alv2017 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: msehnout - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9369632?u=8c988f1b008a3f601385a3616f9327820f66e3a5&v=4 - url: https://github.com/msehnout +- login: binbjz + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/8213913?u=22b68b7a0d5bf5e09c02084c0f5f53d7503114cd&v=4 + url: https://github.com/binbjz - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 url: https://github.com/viniciusCalcantara +- login: SobikXexe + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 + url: https://github.com/SobikXexe +- login: DeoLeung + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 + url: https://github.com/DeoLeung - login: pawelad count: 3 avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 url: https://github.com/pawelad -- login: ThirVondukr - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/50728601?u=167c0bd655e52817082e50979a86d2f98f95b1a3&v=4 - url: https://github.com/ThirVondukr - login: dbfreem count: 3 avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 @@ -772,10 +672,6 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 url: https://github.com/Isuxiz -- login: angely-dev - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/4362224?v=4 - url: https://github.com/angely-dev - login: deight93 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 @@ -792,42 +688,70 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/53449841?v=4 url: https://github.com/ryanisn -- login: svlandeg - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg - login: alexandercronin count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8014288?u=69580504c51a0cdd756fc47b23bb7f404bd694e7&v=4 url: https://github.com/alexandercronin -- login: aanchlia - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/2835374?u=3c3ed29aa8b09ccaf8d66def0ce82bc2f7e5aab6&v=4 - url: https://github.com/aanchlia -- login: chrisK824 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 - url: https://github.com/chrisK824 - login: omarcruzpantoja count: 3 avatarUrl: https://avatars.githubusercontent.com/u/15116058?u=4b64c643fad49225d854e1aaecd1ffc6f9071a1b&v=4 url: https://github.com/omarcruzpantoja -- login: ahmedabdou14 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/104530599?u=d87b866e7c1db970d6f8e8031643818349b046d5&v=4 - url: https://github.com/ahmedabdou14 +- login: Wyko + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/467094?v=4 + url: https://github.com/Wyko +- login: ddahan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 + url: https://github.com/ddahan +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: Trolldemorted + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10261186?v=4 + url: https://github.com/Trolldemorted +- login: vtgn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 + url: https://github.com/vtgn +- login: SDAravind + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/72403396?v=4 + url: https://github.com/SDAravind +- login: slafs + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 + url: https://github.com/slafs +- login: redb0 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30475117?v=4 + url: https://github.com/redb0 +- login: pedroconceicao + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/32837064?u=5a0e6559bc391442629a28b6923790b54deb4464&v=4 + url: https://github.com/pedroconceicao +- login: msukmanowsky + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/362755?u=782e6bf5b9f0356c3f74b4d894fda9f179252086&v=4 + url: https://github.com/msukmanowsky +- login: rishabhc32 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/15983714?u=147776509107af8bdf099223e1840d3f40f944da&v=4 + url: https://github.com/rishabhc32 +- login: meower1 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/109747197?u=0a5cc2a6ae74e558f0afc2874da85132e5953d8b&v=4 + url: https://github.com/meower1 - login: Trinkes count: 2 avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 url: https://github.com/Trinkes -- login: Leon0824 +- login: anantgupta129 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1922026?v=4 - url: https://github.com/Leon0824 -- login: CarlosOliveira-23 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/102637302?u=cf350a4db956f30cbb2c27d3be0d15c282e32b14&v=4 - url: https://github.com/CarlosOliveira-23 + avatarUrl: https://avatars.githubusercontent.com/u/66518357?u=6e25dcd84638f17d2c6df5dc26f07fd7c6dc118e&v=4 + url: https://github.com/anantgupta129 - login: nbx3 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 @@ -838,16 +762,8 @@ one_year_experts: url: https://github.com/yanggeorge - login: XiaoXinYo count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 url: https://github.com/XiaoXinYo -- login: anantgupta129 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/66518357?u=6e25dcd84638f17d2c6df5dc26f07fd7c6dc118e&v=4 - url: https://github.com/anantgupta129 -- login: slafs - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs - login: monchin count: 2 avatarUrl: https://avatars.githubusercontent.com/u/18521800?v=4 @@ -860,11 +776,3 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 url: https://github.com/iloveitaly -- login: msukmanowsky - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/362755?u=782e6bf5b9f0356c3f74b4d894fda9f179252086&v=4 - url: https://github.com/msukmanowsky -- login: shurshilov - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/11828278?u=6bcadc5ce4f2f56a514331c9f68eb987d4afe29a&v=4 - url: https://github.com/shurshilov From 685969141934670994c58799dde27cc6e4aca45d Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 19 Mar 2025 11:34:07 +0000 Subject: [PATCH 014/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c900dc918..681f9237c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 👥 Update FastAPI People - Experts. PR [#13493](https://github.com/fastapi/fastapi/pull/13493) by [@tiangolo](https://github.com/tiangolo). + ### Translations * 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). From 7ab1b9edcc0a464efe46fefed845dd2df9996473 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Mar 2025 12:54:33 +0100 Subject: [PATCH 015/455] =?UTF-8?q?=E2=AC=86=20Bump=20pydantic-ai=20from?= =?UTF-8?q?=200.0.15=20to=200.0.30=20(#13438)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pydantic-ai](https://github.com/pydantic/pydantic-ai) from 0.0.15 to 0.0.30. - [Release notes](https://github.com/pydantic/pydantic-ai/releases) - [Changelog](https://github.com/pydantic/pydantic-ai/blob/main/docs/message-history.md) - [Commits](https://github.com/pydantic/pydantic-ai/compare/v0.0.15...v0.0.30) --- updated-dependencies: - dependency-name: pydantic-ai dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-translations.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-translations.txt b/requirements-translations.txt index a8f8a02d7..7a2a8004e 100644 --- a/requirements-translations.txt +++ b/requirements-translations.txt @@ -1 +1 @@ -pydantic-ai==0.0.15 +pydantic-ai==0.0.30 From 90d52cfa16edada8c95f0ef4f2979acc9984b230 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 19 Mar 2025 11:54:58 +0000 Subject: [PATCH 016/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 681f9237c..10a55f550 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Internal +* ⬆ Bump pydantic-ai from 0.0.15 to 0.0.30. PR [#13438](https://github.com/fastapi/fastapi/pull/13438) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump sqlmodel from 0.0.22 to 0.0.23. PR [#13437](https://github.com/fastapi/fastapi/pull/13437) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump black from 24.10.0 to 25.1.0. PR [#13436](https://github.com/fastapi/fastapi/pull/13436) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump ruff to 0.9.4. PR [#13299](https://github.com/fastapi/fastapi/pull/13299) by [@dependabot[bot]](https://github.com/apps/dependabot). From f806e0380767a8d89e7a64dc3ccb41e3535a5961 Mon Sep 17 00:00:00 2001 From: k94-ishi <32672580+k94-ishi@users.noreply.github.com> Date: Wed, 19 Mar 2025 21:22:33 +0900 Subject: [PATCH 017/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Japanese=20transla?= =?UTF-8?q?tion=20for=20`docs/ja/docs/virtual-environments.md`=20(#13304)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ja/docs/virtual-environments.md | 831 +++++++++++++++++++++++++++ 1 file changed, 831 insertions(+) create mode 100644 docs/ja/docs/virtual-environments.md diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md new file mode 100644 index 000000000..791cf64a8 --- /dev/null +++ b/docs/ja/docs/virtual-environments.md @@ -0,0 +1,831 @@ +# 仮想環境 + +Pythonプロジェクトの作業では、**仮想環境**(または類似の仕組み)を使用し、プロジェクトごとにインストールするパッケージを分離するべきでしょう。 + +/// info | 情報 + +もし、仮想環境の概要や作成方法、使用方法について既にご存知なら、このセクションをスキップすることができます。🤓 + +/// + +/// tip | 豆知識 + +**仮想環境**は、**環境変数**とは異なります。 + +**環境変数**は、プログラムが使用できるシステム内の変数です。 + +**仮想環境**は、ファイルをまとめたディレクトリのことです。 + +/// + +/// info | 情報 +このページでは、**仮想環境**の使用方法と、そのはたらきについて説明します。 + +もし**すべてを管理するツール**(Pythonのインストールも含む)を導入する準備ができているなら、uv をお試しください。 + +/// + +## プロジェクトの作成 + +まず、プロジェクト用のディレクトリを作成します。 + +私は通常 home/user ディレクトリの中に `code` というディレクトリを用意していて、プロジェクトごとに1つのディレクトリをその中に作成しています。 + +
+ +```console +// Go to the home directory +$ cd +// Create a directory for all your code projects +$ mkdir code +// Enter into that code directory +$ cd code +// Create a directory for this project +$ mkdir awesome-project +// Enter into that project directory +$ cd awesome-project +``` + +
+ +## 仮想環境の作成 + +Pythonプロジェクトでの**初めての**作業を開始する際には、**プロジェクト内**に仮想環境を作成してください。 + +/// tip | 豆知識 + +これを行うのは、**プロジェクトごとに1回だけ**です。作業のたびに行う必要はありません。 + +/// + +//// tab | `venv` + +仮想環境を作成するには、Pythonに付属している `venv` モジュールを使用できます。 + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | このコマンドの意味 + +- `python` : `python` というプログラムを呼び出します +- `-m` : モジュールをスクリプトとして呼び出します。どのモジュールを呼び出すのか、この次に指定します +- `venv` : 通常Pythonに付随してインストールされる `venv`モジュールを使用します +- `.venv` : 仮想環境を`.venv`という新しいディレクトリに作成します + +/// + +//// + +//// tab | `uv` + +もし `uv` をインストール済みなら、仮想環境を作成するために `uv` を使うこともできます。 + +
+ +```console +$ uv venv +``` + +
+ +/// tip | 豆知識 + +デフォルトでは、 `uv` は `.venv` というディレクトリに仮想環境を作成します。 + +ただし、追加の引数にディレクトリ名を与えてカスタマイズすることもできます。 + +/// + +//// + +このコマンドは `.venv` というディレクトリに新しい仮想環境を作成します。 + +/// details | `.venv` またはその他の名前 + +仮想環境を別のディレクトリに作成することも可能ですが、 `.venv` と名付けるのが一般的な慣習です。 + +/// + +## 仮想環境の有効化 + +実行されるPythonコマンドやインストールされるパッケージが新しく作成した仮想環境を使用するよう、その仮想環境を有効化しましょう。 + +/// tip | 豆知識 + +そのプロジェクトの作業で**新しいターミナルセッション**を開始する際には、**毎回**有効化が必要です。 + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +もしWindowsでBashを使用している場合 (Git Bashなど): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | 豆知識 + +**新しいパッケージ**を仮想環境にインストールするときには、再度**有効化**してください。 + +こうすることで、そのパッケージがインストールした**ターミナル(CLI)プログラム**を使用する場合に、仮想環境内のものが確実に使われ、グローバル環境にインストールされている別のもの(おそらく必要なものとは異なるバージョン)を誤って使用することを防ぎます。 + +/// + +## 仮想環境が有効であることを確認する + +仮想環境が有効である(前のコマンドが正常に機能した)ことを確認します。 + +/// tip | 豆知識 + +これは**任意**ですが、すべてが期待通りに機能し、意図した仮想環境を使用していることを**確認する**良い方法です。 + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +`.venv/bin/python` にある `python` バイナリが、プロジェクト(この場合は `awesome-project` )内に表示されていれば、正常に動作しています 🎉。 + +//// + +//// tab | Windows PowerShell + +
+ +``` console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +`.venv\Scripts\python` にある `python` バイナリが、プロジェクト(この場合は `awesome-project` )内に表示されていれば、正常に動作しています 🎉。 + +//// + +## `pip` をアップグレードする + +/// tip | 豆知識 + +もし `uv` を使用している場合は、 `pip` の代わりに `uv` を使ってインストールを行うため、 `pip` をアップグレードする必要はありません 😎。 + +/// + +もしパッケージのインストールに `pip`(Pythonに標準で付属しています)を使用しているなら、 `pip` を最新バージョンに**アップグレード**しましょう。 + +パッケージのインストール中に発生する想定外のエラーの多くは、最初に `pip` をアップグレードしておくだけで解決されます。 + +/// tip | 豆知識 + +通常、これは仮想環境を作成した直後に**一度だけ**実行します。 + +/// + +仮想環境が有効であることを(上で説明したコマンドで)確認し、アップグレードを実行しましょう: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +## `.gitignore` を追加する + +**Git**を使用している場合(使用するべきでしょう)、 `.gitignore` ファイルを追加して、 `.venv` 内のあらゆるファイルをGitの管理対象から除外します。 + +/// tip | 豆知識 + +もし `uv` を使用して仮想環境を作成した場合、すでにこの作業は済んでいるので、この手順をスキップできます 😎。 + +/// + +/// tip | 豆知識 + +これも、仮想環境を作成した直後に**一度だけ**実行します。 + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | このコマンドの意味 + +- `echo "*"` : ターミナルに `*` というテキストを「表示」しようとします。(次の部分によってその動作が少し変わります) +- `>` : `>` の左側のコマンドがターミナルに表示しようとする内容を、ターミナルには表示せず、 `>` の右側のファイルに書き込みます。 +- `.gitignore` : `*` を書き込むファイル名。 + +ここで、Gitにおける `*` は「すべて」を意味するので、このコマンドによって `.venv` ディレクトリ内のすべてがGitに無視されるようになります。 + +このコマンドは以下のテキストを持つ `.gitignore` ファイルを作成します: + +```gitignore +* +``` + +/// + +## パッケージのインストール + +仮想環境を有効化した後、その中でパッケージをインストールできます。 + +/// tip | 豆知識 + +プロジェクトに必要なパッケージをインストールまたはアップグレードする場合、これを**一度**実行します。 + +もし新しいパッケージを追加したり、バージョンをアップグレードする必要がある場合は、もう**一度この手順を繰り返し**ます。 + +/// + +### パッケージを直接インストールする + +急いでいて、プロジェクトのパッケージ要件を宣言するファイルを使いたくない場合、パッケージを直接インストールできます。 + +/// tip | 豆知識 + +プログラムが必要とするパッケージとバージョンをファイル(例えば `requirements.txt` や `pyproject.toml` )に記載しておくのは、(とても)良い考えです。 + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +もし `uv` を使用できるなら: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### `requirements.txt` からインストールする + +もし `requirements.txt` があるなら、パッケージのインストールに使用できます。 + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +もし `uv` を使用できるなら: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +パッケージが記載された `requirements.txt` は以下のようになっています: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## プログラムを実行する + +仮想環境を有効化した後、プログラムを実行できます。この際、仮想環境内のPythonと、そこにインストールしたパッケージが使用されます。 + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## エディタの設定 + +プロジェクトではおそらくエディタを使用するでしょう。コード補完やインラインエラーの表示ができるように、作成した仮想環境をエディタでも使えるよう設定してください。(多くの場合、自動検出されます) + +設定例: + +* VS Code +* PyCharm + +/// tip | 豆知識 + +この設定は通常、仮想環境を作成した際に**一度だけ**行います。 + +/// + +## 仮想環境の無効化 + +プロジェクトの作業が終了したら、その仮想環境を**無効化**できます。 + +
+ +```console +$ deactivate +``` + +
+ +これにより、 `python` コマンドを実行しても、そのプロジェクト用(のパッケージがインストールされた)仮想環境から `python` プログラムを呼び出そうとはしなくなります。 + +## 作業準備完了 + +ここまでで、プロジェクトの作業を始める準備が整いました。 + +/// tip | 豆知識 + +上記の内容を理解したいですか? + +もしそうなら、以下を読み進めてください。👇🤓 + +/// + +## なぜ仮想環境? + +FastAPIを使った作業をするには、 [Python](https://www.python.org/) のインストールが必要です。 + +それから、FastAPIや、使用したいその他の**パッケージ**を**インストール**する必要があります。 + +パッケージをインストールするには、通常、Python に付属する `pip` コマンド (または同様の代替コマンド) を使用します。 + +ただし、`pip` を直接使用すると、パッケージは**グローバルなPython環境**(OS全体にインストールされたPython環境)にインストールされます。 + +### 問題点 + +では、グローバルPython環境にパッケージをインストールすることの問題点は何でしょうか? + +ある時点で、あなたは**異なるパッケージ**に依存する多くのプログラムを書くことになるでしょう。そして、これらの中には同じパッケージの**異なるバージョン**に依存するものも出てくるでしょう。😱 + +例えば、 `philosophers-stone` (賢者の石)というプロジェクトを作成するとします。このプログラムは **`harry` (ハリー)というパッケージのバージョン `1`**に依存しています。そのため、 `harry` (ハリー)をインストールする必要があります。 + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +それから、 `prisoner-of-azkaban` (アズカバンの囚人)という別のプロジェクトを作成したとします。このプロジェクトも `harry` (ハリー)に依存していますが、**`harry` (ハリー)のバージョン `3`**が必要です。 + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +しかし、ここで問題になるのは、もしローカルの**仮想環境**ではなくグローバル(環境)にパッケージをインストールするなら、 `harry` (ハリー)のどのバージョンをインストールするか選ばないといけないことです。 + +例えば、 `philosophers-stone` (賢者の石)を実行するには、まず `harry` (ハリー)のバージョン `1` をインストールする必要があります: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +これにより、`harry` (ハリー)バージョン1がグローバルなPython環境にインストールされます。 + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +しかし、 `prisoner-of-azkaban` (アズカバンの囚人)を実行したい場合は、`harry` (ハリー)のバージョン `1` をアンインストールし、`harry` (ハリー)のバージョン `3` をインストールし直す必要があります。(あるいは、単に`harry` (ハリー)のバージョン `3` をインストールすることで、自動的にバージョン `1` がアンインストールされます) + +
+ +```console +$ pip install "harry==3" +``` + +
+ +このようにして、グローバル環境への `harry` (ハリー)のバージョン `3` のインストールが完了します。 + +それから、 `philosophers-stone` (賢者の石)を再び実行しようとすると、このプログラムは `harry` (ハリー)のバージョン `1` が必要なため、**動作しなくなる**可能性があります。 + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|⛔️| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | 豆知識 + +Pythonのパッケージでは、**新しいバージョン**で**互換性を損なう変更を避ける**よう努めるのが一般的ですが、それでも注意が必要です。すべてが正常に動作することをテストで確認してから、意図的に指定して新しいバージョンをインストールするのが良いでしょう。 + +/// + +あなたのすべての**プロジェクトが依存している**、**多数の**他の**パッケージ**が上記の問題を抱えていると想像してください。これは管理が非常に困難です。そして、**互換性のないバージョン**のパッケージを使ってプロジェクトを実行し、なぜ動作しないのか分からなくなるでしょう。 + +また、使用しているOS(Linux、Windows、macOS など)によっては、Pythonがすでにインストールされていることがあります。この場合、特定のバージョンのパッケージが**OSの動作に必要である**ことがあります。グローバル環境にパッケージをインストールすると、OSに付属するプログラムを**壊してしまう**可能性があります。 + +## パッケージのインストール先 + +Pythonをインストールしたとき、ファイルを含んだいくつかのディレクトリが作成されます。 + +これらの中には、インストールされたパッケージを保存するためのものもあります。 + +以下のコマンドを実行したとき: + +
+ +```console +// Don't run this now, it's just an example 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +FastAPIのコードを含む圧縮ファイルが、通常は [PyPI](https://pypi.org/project/fastapi/) からダウンロードされます。 + +また、FastAPIが依存する他のパッケージも**ダウンロード**されます。 + +それから、これらのファイルは**解凍**され、コンピュータのあるディレクトリに配置されます。 + +デフォルトでは、これらのファイルはPythonのインストール時に作成されるディレクトリ、つまり**グローバル環境**に配置されます。 + +## 仮想環境とは + +すべてのパッケージをグローバル環境に配置することによって生じる問題の解決策は、作業する**プロジェクトごとの仮想環境**を使用することです。 + +仮想環境は**ディレクトリ**であり、グローバル環境と非常に似ていて、一つのプロジェクトで使う特定のパッケージ群をインストールできる場所です。 + +このようにして、それぞれのプロジェクトが独自の仮想環境(`.venv` ディレクトリ)に独自のパッケージ群を持つことができます。 + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## 仮想環境の有効化とは + +仮想環境を有効にしたとき、例えば次のコマンドを実行した場合を考えます: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +あるいは、WindowsでBashを使用している場合 (Git Bashなど): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +これによって、いくつかの [環境変数](environment-variables.md){.internal-link target=_blank} が作成・修正され、次に実行されるコマンドで使用できるようになります。 + +これらの環境変数のひとつに、 `PATH` 変数があります。 + +/// tip | 豆知識 + +`PATH` 変数についての詳細は [環境変数](environment-variables.md#path環境変数){.internal-link target=_blank} を参照してください。 + +/// + +仮想環境を有効にすると、その仮想環境のパス `.venv/bin` (LinuxとmacOS)、あるいは `.venv\Scripts` (Windows)が `PATH` 変数に追加されます。 + +その環境を有効にする前の `PATH` 変数が次のようになっているとします。 + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +これは、OSが以下のディレクトリ中でプログラムを探すことを意味します: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +これは、OSが以下のディレクトリ中でプログラムを探すことを意味します: + +* `C:\Windows\System32` + +//// + +仮想環境を有効にすると、 `PATH` 変数は次のようになります。 + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +これは、OSが他のディレクトリを探すより前に、最初に以下のディレクトリ中でプログラムを探し始めることを意味します: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +そのため、ターミナルで `python` と入力した際に、OSはPythonプログラムを以下のパスで発見し、使用します。 + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +これは、OSが他のディレクトリを探すより前に、最初に以下のディレクトリ中でプログラムを探し始めることを意味します: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +そのため、ターミナルで `python` と入力した際に、OSはPythonプログラムを以下のパスで発見し、使用します。 + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +//// + +重要な点は、仮想環境のパスを `PATH` 変数の**先頭**に配置することです。OSは利用可能な他のPythonを見つけるより**前に**、この仮想環境のPythonを見つけるようになります。このようにして、 `python` を実行したときに、他の `python` (例えばグローバル環境の `python` )ではなく、**その仮想環境の**Pythonを使用するようになります。 + +仮想環境を有効にして変更されることは他にもありますが、これが最も重要な変更のひとつです。 + +## 仮想環境の確認 + +仮想環境が有効かどうか、例えば次のように確認できます。: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +これは、使用される `python` プログラムが**その仮想環境の**ものであることを意味します。 + +LinuxやmacOSでは `which` を、Windows PowerShellでは `Get-Command` を使用します。 + +このコマンドの動作は、 `PATH`変数に設定された**それぞれのパスを順に**確認していき、呼ばれている `python` プログラムを探します。そして、見つかり次第そのプログラムへの**パスを表示します**。 + +最も重要なことは、 `python` が呼ばれたときに、まさにこのコマンドで確認した "`python`" が実行されることです。 + +こうして、自分が想定通りの仮想環境にいるかを確認できます。 + +/// tip | 豆知識 + +ある仮想環境を有効にし、そのPythonを使用したまま**他のプロジェクトに移動して**しまうことは簡単に起こり得ます。 + +そして、その第二のプロジェクトは動作しないでしょう。なぜなら別のプロジェクトの仮想環境の**誤ったPython**を使用しているからです。 + +そのため、どの `python` が使用されているのか確認できることは役立ちます。🤓 + +/// + +## なぜ仮想環境を無効化するのか + +例えば、`philosophers-stone` (賢者の石)というプロジェクトで作業をしていて、**その仮想環境を有効にし**、必要なパッケージをインストールしてその環境内で作業を進めているとします。 + +それから、**別のプロジェクト**、 `prisoner-of-azkaban` (アズカバンの囚人)に取り掛かろうとします。 + +そのプロジェクトディレクトリへ移動します: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +もし `philosophers-stone` (賢者の石)の仮想環境を無効化していないと、`python` を実行したとき、 ターミナルは `philosophers-stone` (賢者の石)のPythonを使用しようとします。 + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// Error importing sirius, it's not installed 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +しかし、その仮想環境を無効化し、 `prisoner-of-azkaban` (アズカバンの囚人)のための新しい仮想環境を有効にすれば、 `python` を実行したときに `prisoner-of-azkaban` (アズカバンの囚人)の仮想環境の Python が使用されるようになります。 + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎 +$ deactivate + +// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀 +$ source .venv/bin/activate + +// Now when you run python, it will find the package sirius installed in this virtual environment ✨ +$ python main.py + +I solemnly swear 🐺 +``` + +
+ +## 代替手段 + +これは、あらゆる仕組みを**根本から**学ぶためのシンプルな入門ガイドです。 + +仮想環境、パッケージの依存関係(requirements)、プロジェクトの管理には、多くの**代替手段**があります。 + +準備が整い、パッケージの依存関係、仮想環境など**プロジェクト全体の管理**ツールを使いたいと考えたら、uv を試してみることをおすすめします。 + +`uv` では以下のような多くのことができます: + +* 異なるバージョンも含めた**Python のインストール** +* プロジェクトごとの**仮想環境**の管理 +* **パッケージ**のインストール +* プロジェクトのパッケージの**依存関係やバージョン**の管理 +* パッケージとそのバージョンの、依存関係を含めた**厳密な**組み合わせを保持し、これによって、本番環境で、開発環境と全く同じようにプロジェクトを実行できる(これは**locking**と呼ばれます) +* その他のさまざまな機能 + +## まとめ + +ここまで読みすべて理解したなら、世間の多くの開発者と比べて、仮想環境について**あなたはより多くのことを知っています**。🤓 + +これらの詳細を知ることは、将来、複雑に見える何かのデバッグにきっと役立つでしょう。しかし、その頃には、あなたは**そのすべての動作を根本から**理解しているでしょう。😎 From 7e33df505afd89ab235b8e8abdf08316e1a5bc78 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 19 Mar 2025 12:22:56 +0000 Subject: [PATCH 018/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 10a55f550..f4d8a9917 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* 🌐 Add Japanese translation for `docs/ja/docs/virtual-environments.md`. PR [#13304](https://github.com/fastapi/fastapi/pull/13304) by [@k94-ishi](https://github.com/k94-ishi). * 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). * 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/cloud.md`. PR [#13407](https://github.com/fastapi/fastapi/pull/13407) by [@ptt3199](https://github.com/ptt3199). From f9f1d93c584843e700522c26fb768eb0ce110f4d Mon Sep 17 00:00:00 2001 From: Valentyn Date: Wed, 19 Mar 2025 13:03:13 -0400 Subject: [PATCH 019/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/header-param-models.md`=20?= =?UTF-8?q?page=20(#13461)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/header-param-models.md | 58 ++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 docs/uk/docs/tutorial/header-param-models.md diff --git a/docs/uk/docs/tutorial/header-param-models.md b/docs/uk/docs/tutorial/header-param-models.md new file mode 100644 index 000000000..6f7b0bdae --- /dev/null +++ b/docs/uk/docs/tutorial/header-param-models.md @@ -0,0 +1,58 @@ +# Моделі Параметрів Заголовків + +Якщо у Вас є група пов’язаних параметрів заголовків, Ви можете створити **Pydantic модель** для їх оголошення. + +Це дозволить Вам повторно **використовувати модель** в **різних місцях**, а також оголосити валідації та метадані для всіх параметрів одночасно. 😎 + +/// note | Нотатки + +Ця можливість підтримується починаючи з версії FastAPI `0.115.0`. 🤓 + +/// + +## Параметри Заголовків з Використанням Pydantic Model + +Оголосіть потрібні **параметри заголовків** у **Pydantic моделі**, а потім оголосіть параметр як `Header`: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +FastAPI буде витягувати дані для кожного поля з заголовків у запиті та передавати їх у створену Вами Pydantic модель. + +**FastAPI** буде **витягувати** дані для **кожного поля** з **заголовків** у запиті та передавати їх у створену Вами Pydantic модель. + +## Перевірка в Документації + +Ви можете побачити необхідні заголовки в інтерфейсі документації за адресою `/docs`: + +
+ +
+ +## Заборона Додаткових Заголовків + +У деяких особливих випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** заголовки, які хочете отримати. + +Ви можете використати конфігурацію моделі Pydantic, щоб `заборонити` будь-які `додаткові` поля: + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Якщо клієнт спробує надіслати **додаткові заголовки**, він отримає **помилку** у відповіді. + +Наприклад, якщо клієнт спробує надіслати заголовок `tool` зі значенням `plumbus`, він отримає **помилку** з повідомленням про те, що параметр заголовка `tool` не дозволений: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## Підсумок + +Ви можете використовувати **Pydantic моделі** для оголошення **заголовків** у **FastAPI**. 😎 From f077c17e1e5d3b5ccd1ac43f9228f576b0401095 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Wed, 19 Mar 2025 13:03:38 -0400 Subject: [PATCH 020/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/cookie-param-models.md`=20?= =?UTF-8?q?page=20(#13460)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/cookie-param-models.md | 76 ++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/uk/docs/tutorial/cookie-param-models.md diff --git a/docs/uk/docs/tutorial/cookie-param-models.md b/docs/uk/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..f070b6ac8 --- /dev/null +++ b/docs/uk/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Моделі для Cookie-параметрів + +Якщо у Вас є група **cookies** параметрів, які пов'язані між собою, Ви можете створити **Pydantic-модель**, щоб оголосити їх. 🍪 + +Це дозволить Вам повторно **використовувати модель** у **різних місцях**, а також оголосити валідацію та метадані для всіх параметрів одночасно. 😎 + +/// note | Нотатки + +Це підтримується з версії FastAPI `0.115.0`. 🤓 + +/// + +/// tip | Порада + +Ця ж техніка застосовується до `Query`, `Cookie`, та `Header`. 😎 + +/// + +## Cookie з Pydantic-моделлю + +Оголосіть **cookie-параметри**, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть параметр як `Cookie`: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** буде **витягувати** дані для **кожного поля** з **cookie** параметрів, отриманих у запиті, і передавати Вам Pydantic-модель, яку Ви визначили. + +## Перевірка у документації + +Ви можете побачити визначені cookie в інтерфейсі документації за адресою `/docs`: + +
+ +
+ +/// info | Інформація + +Майте на увазі, що оскільки **браузери обробляють cookie** особливим чином і "за лаштунками", вони **не** дозволяють **JavaScript** легко з ними працювати. + +Якщо Ви зайдете до **інтерфейсу документації API** за адресою `/docs`, Ви зможете побачити **документацію** для cookie у Ваших **операціях шляху**. + +Але навіть якщо Ви заповните дані й натиснете "Execute", оскільки інтерфейс документації працює з **JavaScript**, cookie не будуть відправлені, і Ви побачите **помилку**, ніби Ви не ввели жодних значень. + +/// + +## Заборона додаткових cookie + +У деяких спеціальних випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** список cookie, які хочете отримувати. + +Ваша API тепер має можливість контролювати власну згоду на cookie. 🤪🍪 + +Ви можете використовувати налаштування моделі Pydantic, щоб `заборонити` будь-які `додаткові` поля: + +{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} + +Якщо клієнт спробує надіслати якісь **додаткові cookie**, він отримає відповідь з **помилкою**. + +Бідні банери cookie, які так старанно намагаються отримати Вашу згоду, щоб API її відхилила. 🍪 + +Наприклад, якщо клієнт спробує надіслати cookie `santa_tracker` зі значенням `good-list-please`, він отримає відповідь з помилкою, яка повідомить, що cookie `santa_tracker` не дозволено: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## Підсумок + +Ви можете використовувати **Pydantic-моделі** для оголошення cookie у FastAPI. 😎 From f977da6ae0e43d3c29fba57095777e596ca32d3e Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 19 Mar 2025 17:03:40 +0000 Subject: [PATCH 021/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f4d8a9917..bde2306b9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-param-models.md` page. PR [#13461](https://github.com/fastapi/fastapi/pull/13461) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Japanese translation for `docs/ja/docs/virtual-environments.md`. PR [#13304](https://github.com/fastapi/fastapi/pull/13304) by [@k94-ishi](https://github.com/k94-ishi). * 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). * 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/cloud.md`. PR [#13407](https://github.com/fastapi/fastapi/pull/13407) by [@ptt3199](https://github.com/ptt3199). From e4c1dd799d5b1a1c4697bbc5f923dff701d2ffff Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 19 Mar 2025 17:04:06 +0000 Subject: [PATCH 022/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bde2306b9..f63d240fe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cookie-param-models.md` page. PR [#13460](https://github.com/fastapi/fastapi/pull/13460) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-param-models.md` page. PR [#13461](https://github.com/fastapi/fastapi/pull/13461) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Japanese translation for `docs/ja/docs/virtual-environments.md`. PR [#13304](https://github.com/fastapi/fastapi/pull/13304) by [@k94-ishi](https://github.com/k94-ishi). * 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). From 8557a88d169a7981fb18aff10160517ea1338cf4 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Wed, 19 Mar 2025 13:04:17 -0400 Subject: [PATCH 023/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/response-status-code.md`?= =?UTF-8?q?=20page=20(#13462)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/response-status-code.md | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 docs/uk/docs/tutorial/response-status-code.md diff --git a/docs/uk/docs/tutorial/response-status-code.md b/docs/uk/docs/tutorial/response-status-code.md new file mode 100644 index 000000000..1ed69d6f2 --- /dev/null +++ b/docs/uk/docs/tutorial/response-status-code.md @@ -0,0 +1,100 @@ +# Статус коди Відповідей + +Так само як Ви можете вказати модель відповіді, Ви також можете оголосити HTTP код статусу для відповіді за допомогою параметра `status_code` в будь-якій з *операцій шляху*: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* тощо. + +{* ../../docs_src/response_status_code/tutorial001.py hl[6] *} + +/// note | Нотатка + +Зверніть увагу, що `status_code` є параметром методу "декоратора" (`get`, `post` і т.д.), а не Вашої *функції операції шляху*, як усі інші параметри та тіло запиту. + +/// + +Параметр `status_code` приймає число, яке відповідає HTTP коду статусу. + +/// info | Інформація +`status_code` також може отримувати значення з `IntEnum`, наприклад, з Python `http.HTTPStatus`. + +/// + +Він буде: + +* Повертати вказаний код статусу у відповіді. +* Документувати його як такий у схемі OpenAPI (і, таким чином, в інтерфейсі користувача): + + + +/// note | Нотатка + +Деякі коди відповіді (див. наступний розділ) вказують, що відповідь не має тіла. + +FastAPI знає про це і створить OpenAPI документацію, яка вказує, що тіла відповіді немає. + +/// + +## Про HTTP статус коди + +/// note | Нотатка + +Якщо Ви вже знаєте, що таке HTTP коди статусу, переходьте до наступного розділу. + +/// + +В HTTP Ви надсилаєте числовий код статусу з 3 цифр як частину відповіді. + +Ці коди статусу мають пов’язану назву для їх розпізнавання, але найважливішою частиною є саме число. + +Коротко: + +* **`100 - 199`** "Інформаційні" відповіді. Ви рідко використовуєте їх напряму. Відповіді з такими кодами не можуть мати тіла. +* **`200 - 299`** "Успішні" відповіді. Це ті, які Ви використовуватимете найчастіше. + * `200` - код за замовчуванням, який означає, що все пройшло "OK". + * Інший приклад – `201`, "Created" (створено). Його зазвичай використовують після створення нового запису в базі даних. + * Особливий випадок – `204`, "No Content" (немає вмісту). Ця відповідь використовується, коли немає даних для повернення клієнту, тому відповідь не повинна мати тіла. +* **`300 - 399`** "Перенаправлення". Відповіді з цими кодами можуть мати або не мати тіла, за винятком `304`, "Not Modified" (не змінено), яка не повинна мати тіла. +* **`400 - 499`** "Помилка клієнта". Це другий тип, який Ви, ймовірно, будете використовувати найчастіше. + * Приклад `404`, "Not Found" (не знайдено). + * Для загальних помилок клієнта можна використовувати `400`. +* `500 - 599` "Помилки сервера". Ви майже ніколи не використовуєте їх напряму. Якщо в коді Вашого застосунку або на сервері щось пішло не так, автоматично буде повернено один із цих кодів статусу. + +/// tip | Порада + +Щоб дізнатися більше про кожен код статусу і призначення кожного з них, перегляньте документацію MDN про HTTP коди статусу. + +/// + +## Легкий спосіб запам'ятати назви + +Розглянемо ще раз попередній приклад: + +{* ../../docs_src/response_status_code/tutorial001.py hl[6] *} + +`201` - це код статусу для "Created" (створено). + +Але Вам не потрібно запам'ятовувати, що означає кожен із цих кодів. + +Ви можете використовувати зручні змінні з `fastapi.status` + +{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *} + +Ці змінні просто для зручності. Вони містять ті ж самі числа, але Ви можете скористатися автозаповненням в редакторі: + + + +/// note | Технічні деталі + +Ви також можете використати `from starlette import status`. + +**FastAPI** надає ті ж самі змінні `starlette.status` як `fastapi.status`, просто для зручності розробника. Однак вони походять безпосередньо зі Starlette. + +/// + +## Зміна значення за замовчуванням + +Далі, у Посібнику для досвідчених користувачів{.internal-link target=_blank}, Ви дізнаєтесь, як повернути інший код статусу, ніж той, який Ви оголосили тут. From 3afd733753ba2dc51eb141d1b0d2bf4b2bf8f4f3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 19 Mar 2025 17:04:51 +0000 Subject: [PATCH 024/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f63d240fe..d9a1f5ac1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/response-status-code.md` page. PR [#13462](https://github.com/fastapi/fastapi/pull/13462) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cookie-param-models.md` page. PR [#13460](https://github.com/fastapi/fastapi/pull/13460) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-param-models.md` page. PR [#13461](https://github.com/fastapi/fastapi/pull/13461) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Japanese translation for `docs/ja/docs/virtual-environments.md`. PR [#13304](https://github.com/fastapi/fastapi/pull/13304) by [@k94-ishi](https://github.com/k94-ishi). From ecf6e7eec292122ac33a8d96c2c8bff94fa597f4 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Wed, 19 Mar 2025 13:09:57 -0400 Subject: [PATCH 025/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/metadata.md`=20page=20(#13?= =?UTF-8?q?459)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/metadata.md | 120 ++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/uk/docs/tutorial/metadata.md diff --git a/docs/uk/docs/tutorial/metadata.md b/docs/uk/docs/tutorial/metadata.md new file mode 100644 index 000000000..64e667ec6 --- /dev/null +++ b/docs/uk/docs/tutorial/metadata.md @@ -0,0 +1,120 @@ +# Метадані та URL-адреси документації + +Ви можете налаштувати кілька конфігурацій метаданих у Вашому додатку **FastAPI**. + +## Метадані для API + +Ви можете встановити такі поля, які використовуються в специфікації OpenAPI та в автоматично згенерованих інтерфейсах документації API: + +| Параметр | Тип | Опис | +|------------|------|-------------| +| `title` | `str` | Назва API. | +| `summary` | `str` | Короткий опис API. Доступно з OpenAPI 3.1.0, FastAPI 0.99.0. | +| `description` | `str` | Більш детальний опис API. Може використовувати Markdown. | +| `version` | `string` | Версія API. Це версія Вашого додатка, а не OpenAPI. Наприклад, `2.5.0`. | +| `terms_of_service` | `str` | URL до умов використання API. Якщо вказано, має бути у форматі URL. | +| `contact` | `dict` | Інформація для контакту з API. Може містити кілька полів.
contact поля
ПараметрТипОпис
namestrІм'я контактної особи або організації.
urlstrURL з інформацією для контакту. Повинен бути у форматі URL.
emailstrEmail контактної особи або організації. Повинен бути у форматі електронної пошти.
| +| `license_info` | `dict` | Інформація про ліцензію для API. Може містити кілька полів.
license_info поля
ПараметрТипОпис
namestrОБОВ'ЯЗКОВО (якщо встановлено license_info). Назва ліцензії для API.
identifierstrЛіцензійний вираз за SPDX для API. Поле identifier взаємовиключне з полем url. Доступно з OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL до ліцензії, яка використовується для API. Повинен бути у форматі URL.
| + +Ви можете налаштувати їх наступним чином: + +{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *} + +/// tip | Підказка + +У полі `description` можна використовувати Markdown, і він буде відображатися у результаті. + +/// + +З цією конфігурацією автоматична документація API виглядатиме так: + + + +## Ідентифікатор ліцензії + +З початку використання OpenAPI 3.1.0 та FastAPI 0.99.0 Ви також можете налаштувати `license_info` за допомогою `identifier` замість `url`. + +Наприклад: + +{* ../../docs_src/metadata/tutorial001_1.py hl[31] *} + +## Метадані для тегів + +Ви також можете додати додаткові метадані для різних тегів, які використовуються для групування операцій шляхів, за допомогою параметра `openapi_tags`. + +Він приймає список, який містить один словник для кожного тега. + +Кожен словник може містити: + +* `name` (**обов'язково**): `str` з тією ж назвою тегу, яку Ви використовуєте у параметрі `tags` у Ваших *операціях шляху* та `APIRouter`s. +* `description`: `str` з коротким описом тегу. Може містити Markdown і буде відображено в інтерфейсі документації. +* `externalDocs`: `dict` який описує зовнішню документацію з такими полями: + * `description`: `str` з коротким описом зовнішньої документації. + * `url` (**обов'язково**): `str`з URL-адресою зовнішньої документації. + +### Створення метаданих для тегів + +Спробуймо це на прикладі з тегами для `users` та `items`. + +Створіть метадані для своїх тегів і передайте їх у параметр `openapi_tags`: + +{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *} + +Зверніть увагу, що в описах можна використовувати Markdown, наприклад, "login" буде показано жирним шрифтом (**login**), а "fancy" буде показано курсивом (_fancy_). + +/// tip | Порада + +Не обов'язково додавати метадані для всіх тегів, які Ви використовуєте. + +/// + +### Використання тегів + +Використовуйте параметр `tags` зі своїми *операціями шляху* (і `APIRouter`) для призначення їх до різних тегів: + +{* ../../docs_src/metadata/tutorial004.py hl[21,26] *} + +/// info | Інформація + +Детальніше про теги читайте в розділі [Конфігурація шляхів операцій](path-operation-configuration.md#tags){.internal-link target=_blank}. + +/// + +### Перевірка документації + +Якщо Ви зараз перевірите документацію, вона покаже всі додаткові метадані: + + + +### Порядок тегів + +Порядок кожного словника метаданих тегу також визначає порядок відображення в інтерфейсі документації. + +Наприклад, хоча `users` мав би йти після `items` в алфавітному порядку, він відображається перед ними, оскільки ми додали його метадані як перший словник у списку. + +## URL для OpenAPI + +За замовчуванням схема OpenAPI надається за адресою `/openapi.json`. + +Але Ви можете налаштувати це за допомогою параметра `openapi_url`. + +Наприклад, щоб налаштувати його на `/api/v1/openapi.json`: + +{* ../../docs_src/metadata/tutorial002.py hl[3] *} + +Якщо Ви хочете повністю вимкнути схему OpenAPI, Ви можете встановити `openapi_url=None`, це також вимкне інтерфейси документації, які її використовують. + +## URL-адреси документації + +Ви можете налаштувати два інтерфейси користувача для документації, які включені: + +* **Swagger UI**: доступний за адресою `/docs`. + * Ви можете змінити його URL за допомогою параметра `docs_url`. + * Ви можете вимкнути його, встановивши `docs_url=None`. +* **ReDoc**: доступний за адресою `/redoc`. + * Ви можете змінити його URL за допомогою параметра `redoc_url`. + * Ви можете вимкнути його, встановивши `redoc_url=None`. + +Наприклад, щоб налаштувати Swagger UI на `/documentation` і вимкнути ReDoc: + +{* ../../docs_src/metadata/tutorial003.py hl[3] *} From 4e40e1e85d2e62375f79ee726a8448539d503030 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 19 Mar 2025 17:10:19 +0000 Subject: [PATCH 026/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d9a1f5ac1..009705cdd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/metadata.md` page. PR [#13459](https://github.com/fastapi/fastapi/pull/13459) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/response-status-code.md` page. PR [#13462](https://github.com/fastapi/fastapi/pull/13462) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cookie-param-models.md` page. PR [#13460](https://github.com/fastapi/fastapi/pull/13460) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-param-models.md` page. PR [#13461](https://github.com/fastapi/fastapi/pull/13461) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 241de23b68664a45d07534513bc2dfb0191ba24f Mon Sep 17 00:00:00 2001 From: Rishat-F <66554797+Rishat-F@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:29:48 +0300 Subject: [PATCH 027/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20`docs/en/docs/t?= =?UTF-8?q?utorial/middleware.md`=20(#13444)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alejandra <90076947+alejsdev@users.noreply.github.com> --- docs/en/docs/tutorial/middleware.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/tutorial/middleware.md b/docs/en/docs/tutorial/middleware.md index 53c47a085..4f7980165 100644 --- a/docs/en/docs/tutorial/middleware.md +++ b/docs/en/docs/tutorial/middleware.md @@ -15,7 +15,7 @@ A "middleware" is a function that works with every **request** before it is proc If you have dependencies with `yield`, the exit code will run *after* the middleware. -If there were any background tasks (documented later), they will run *after* all the middleware. +If there were any background tasks (covered in the [Background Tasks](background-tasks.md){.internal-link target=_blank} section, you will see it later), they will run *after* all the middleware. /// From c08a3e8f2250cc84032e4261a18ec717de74d0c7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 20 Mar 2025 12:30:17 +0000 Subject: [PATCH 028/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 009705cdd..5410c75b8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Update `docs/en/docs/tutorial/middleware.md`. PR [#13444](https://github.com/fastapi/fastapi/pull/13444) by [@Rishat-F](https://github.com/Rishat-F). * 👥 Update FastAPI People - Experts. PR [#13493](https://github.com/fastapi/fastapi/pull/13493) by [@tiangolo](https://github.com/tiangolo). ### Translations From 2537d9d1c2517f9e552ca2b076b3b63b1acbc55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 23 Mar 2025 20:48:54 +0000 Subject: [PATCH 029/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20`convert=5Fundersc?= =?UTF-8?q?ores=3DFalse`=20for=20header=20Pydantic=20models=20(#13515)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/header-param-models.md | 16 + docs_src/header_param_models/tutorial003.py | 19 ++ .../header_param_models/tutorial003_an.py | 22 ++ .../tutorial003_an_py310.py | 21 ++ .../tutorial003_an_py39.py | 21 ++ .../header_param_models/tutorial003_py310.py | 17 ++ .../header_param_models/tutorial003_py39.py | 19 ++ fastapi/dependencies/utils.py | 10 +- fastapi/openapi/utils.py | 23 +- .../test_tutorial001.py | 6 +- .../test_tutorial002.py | 6 +- .../test_tutorial003.py | 285 ++++++++++++++++++ 12 files changed, 457 insertions(+), 8 deletions(-) create mode 100644 docs_src/header_param_models/tutorial003.py create mode 100644 docs_src/header_param_models/tutorial003_an.py create mode 100644 docs_src/header_param_models/tutorial003_an_py310.py create mode 100644 docs_src/header_param_models/tutorial003_an_py39.py create mode 100644 docs_src/header_param_models/tutorial003_py310.py create mode 100644 docs_src/header_param_models/tutorial003_py39.py create mode 100644 tests/test_tutorial/test_header_param_models/test_tutorial003.py diff --git a/docs/en/docs/tutorial/header-param-models.md b/docs/en/docs/tutorial/header-param-models.md index 73950a668..4cdf09705 100644 --- a/docs/en/docs/tutorial/header-param-models.md +++ b/docs/en/docs/tutorial/header-param-models.md @@ -51,6 +51,22 @@ For example, if the client tries to send a `tool` header with a value of `plumbu } ``` +## Disable Convert Underscores + +The same way as with regular header parameters, when you have underscore characters in the parameter names, they are **automatically converted to hyphens**. + +For example, if you have a header parameter `save_data` in the code, the expected HTTP header will be `save-data`, and it will show up like that in the docs. + +If for some reason you need to disable this automatic conversion, you can do it as well for Pydantic models for header parameters. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning + +Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores. + +/// + ## Summary You can use **Pydantic models** to declare **headers** in **FastAPI**. 😎 diff --git a/docs_src/header_param_models/tutorial003.py b/docs_src/header_param_models/tutorial003.py new file mode 100644 index 000000000..dc2eb74bd --- /dev/null +++ b/docs_src/header_param_models/tutorial003.py @@ -0,0 +1,19 @@ +from typing import List, Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: List[str] = [] + + +@app.get("/items/") +async def read_items(headers: CommonHeaders = Header(convert_underscores=False)): + return headers diff --git a/docs_src/header_param_models/tutorial003_an.py b/docs_src/header_param_models/tutorial003_an.py new file mode 100644 index 000000000..e3edb1189 --- /dev/null +++ b/docs_src/header_param_models/tutorial003_an.py @@ -0,0 +1,22 @@ +from typing import List, Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel +from typing_extensions import Annotated + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: List[str] = [] + + +@app.get("/items/") +async def read_items( + headers: Annotated[CommonHeaders, Header(convert_underscores=False)], +): + return headers diff --git a/docs_src/header_param_models/tutorial003_an_py310.py b/docs_src/header_param_models/tutorial003_an_py310.py new file mode 100644 index 000000000..07bfa83bf --- /dev/null +++ b/docs_src/header_param_models/tutorial003_an_py310.py @@ -0,0 +1,21 @@ +from typing import Annotated + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: str | None = None + traceparent: str | None = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items( + headers: Annotated[CommonHeaders, Header(convert_underscores=False)], +): + return headers diff --git a/docs_src/header_param_models/tutorial003_an_py39.py b/docs_src/header_param_models/tutorial003_an_py39.py new file mode 100644 index 000000000..8be6b01d0 --- /dev/null +++ b/docs_src/header_param_models/tutorial003_an_py39.py @@ -0,0 +1,21 @@ +from typing import Annotated, Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items( + headers: Annotated[CommonHeaders, Header(convert_underscores=False)], +): + return headers diff --git a/docs_src/header_param_models/tutorial003_py310.py b/docs_src/header_param_models/tutorial003_py310.py new file mode 100644 index 000000000..65e92a28c --- /dev/null +++ b/docs_src/header_param_models/tutorial003_py310.py @@ -0,0 +1,17 @@ +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: str | None = None + traceparent: str | None = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items(headers: CommonHeaders = Header(convert_underscores=False)): + return headers diff --git a/docs_src/header_param_models/tutorial003_py39.py b/docs_src/header_param_models/tutorial003_py39.py new file mode 100644 index 000000000..848c34111 --- /dev/null +++ b/docs_src/header_param_models/tutorial003_py39.py @@ -0,0 +1,19 @@ +from typing import Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items(headers: CommonHeaders = Header(convert_underscores=False)): + return headers diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index d205d17fa..84dfa4d03 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -750,9 +750,15 @@ def request_params_to_args( first_field = fields[0] fields_to_extract = fields single_not_embedded_field = False + default_convert_underscores = True if len(fields) == 1 and lenient_issubclass(first_field.type_, BaseModel): fields_to_extract = get_cached_model_fields(first_field.type_) single_not_embedded_field = True + # If headers are in a Pydantic model, the way to disable convert_underscores + # would be with Header(convert_underscores=False) at the Pydantic model level + default_convert_underscores = getattr( + first_field.field_info, "convert_underscores", True + ) params_to_process: Dict[str, Any] = {} @@ -763,7 +769,9 @@ def request_params_to_args( if isinstance(received_params, Headers): # Handle fields extracted from a Pydantic Model for a header, each field # doesn't have a FieldInfo of type Header with the default convert_underscores=True - convert_underscores = getattr(field.field_info, "convert_underscores", True) + convert_underscores = getattr( + field.field_info, "convert_underscores", default_convert_underscores + ) if convert_underscores: alias = ( field.alias diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index bd8f3c106..808646cc2 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -32,6 +32,7 @@ from fastapi.utils import ( generate_operation_id_for_path, is_body_allowed_for_status_code, ) +from pydantic import BaseModel from starlette.responses import JSONResponse from starlette.routing import BaseRoute from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY @@ -113,6 +114,13 @@ def _get_openapi_operation_parameters( (ParamTypes.header, header_params), (ParamTypes.cookie, cookie_params), ] + default_convert_underscores = True + if len(flat_dependant.header_params) == 1: + first_field = flat_dependant.header_params[0] + if lenient_issubclass(first_field.type_, BaseModel): + default_convert_underscores = getattr( + first_field.field_info, "convert_underscores", True + ) for param_type, param_group in parameter_groups: for param in param_group: field_info = param.field_info @@ -126,8 +134,21 @@ def _get_openapi_operation_parameters( field_mapping=field_mapping, separate_input_output_schemas=separate_input_output_schemas, ) + name = param.alias + convert_underscores = getattr( + param.field_info, + "convert_underscores", + default_convert_underscores, + ) + if ( + param_type == ParamTypes.header + and param.alias == param.name + and convert_underscores + ): + name = param.name.replace("_", "-") + parameter = { - "name": param.alias, + "name": name, "in": param_type.value, "required": param.required, "schema": param_schema, diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial001.py b/tests/test_tutorial/test_header_param_models/test_tutorial001.py index 06b2404cf..bc876897b 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial001.py @@ -129,13 +129,13 @@ def test_openapi_schema(client: TestClient): "schema": {"type": "string", "title": "Host"}, }, { - "name": "save_data", + "name": "save-data", "in": "header", "required": True, "schema": {"type": "boolean", "title": "Save Data"}, }, { - "name": "if_modified_since", + "name": "if-modified-since", "in": "header", "required": False, "schema": IsDict( @@ -171,7 +171,7 @@ def test_openapi_schema(client: TestClient): ), }, { - "name": "x_tag", + "name": "x-tag", "in": "header", "required": False, "schema": { diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial002.py b/tests/test_tutorial/test_header_param_models/test_tutorial002.py index e07655a0c..0615521c4 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial002.py @@ -140,13 +140,13 @@ def test_openapi_schema(client: TestClient): "schema": {"type": "string", "title": "Host"}, }, { - "name": "save_data", + "name": "save-data", "in": "header", "required": True, "schema": {"type": "boolean", "title": "Save Data"}, }, { - "name": "if_modified_since", + "name": "if-modified-since", "in": "header", "required": False, "schema": IsDict( @@ -182,7 +182,7 @@ def test_openapi_schema(client: TestClient): ), }, { - "name": "x_tag", + "name": "x-tag", "in": "header", "required": False, "schema": { diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial003.py b/tests/test_tutorial/test_header_param_models/test_tutorial003.py new file mode 100644 index 000000000..60940e1da --- /dev/null +++ b/tests/test_tutorial/test_header_param_models/test_tutorial003.py @@ -0,0 +1,285 @@ +import importlib + +import pytest +from dirty_equals import IsDict +from fastapi.testclient import TestClient +from inline_snapshot import snapshot + +from tests.utils import needs_py39, needs_py310 + + +@pytest.fixture( + name="client", + params=[ + "tutorial003", + pytest.param("tutorial003_py39", marks=needs_py39), + pytest.param("tutorial003_py310", marks=needs_py310), + "tutorial003_an", + pytest.param("tutorial003_an_py39", marks=needs_py39), + pytest.param("tutorial003_an_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.header_param_models.{request.param}") + + client = TestClient(mod.app) + return client + + +def test_header_param_model(client: TestClient): + response = client.get( + "/items/", + headers=[ + ("save_data", "true"), + ("if_modified_since", "yesterday"), + ("traceparent", "123"), + ("x_tag", "one"), + ("x_tag", "two"), + ], + ) + assert response.status_code == 200 + assert response.json() == { + "host": "testserver", + "save_data": True, + "if_modified_since": "yesterday", + "traceparent": "123", + "x_tag": ["one", "two"], + } + + +def test_header_param_model_no_underscore(client: TestClient): + response = client.get( + "/items/", + headers=[ + ("save-data", "true"), + ("if-modified-since", "yesterday"), + ("traceparent", "123"), + ("x-tag", "one"), + ("x-tag", "two"), + ], + ) + assert response.status_code == 422 + assert response.json() == snapshot( + { + "detail": [ + IsDict( + { + "type": "missing", + "loc": ["header", "save_data"], + "msg": "Field required", + "input": { + "host": "testserver", + "traceparent": "123", + "x_tag": [], + "accept": "*/*", + "accept-encoding": "gzip, deflate", + "connection": "keep-alive", + "user-agent": "testclient", + "save-data": "true", + "if-modified-since": "yesterday", + "x-tag": "two", + }, + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "value_error.missing", + "loc": ["header", "save_data"], + "msg": "field required", + } + ) + ] + } + ) + + +def test_header_param_model_defaults(client: TestClient): + response = client.get("/items/", headers=[("save_data", "true")]) + assert response.status_code == 200 + assert response.json() == { + "host": "testserver", + "save_data": True, + "if_modified_since": None, + "traceparent": None, + "x_tag": [], + } + + +def test_header_param_model_invalid(client: TestClient): + response = client.get("/items/") + assert response.status_code == 422 + assert response.json() == snapshot( + { + "detail": [ + IsDict( + { + "type": "missing", + "loc": ["header", "save_data"], + "msg": "Field required", + "input": { + "x_tag": [], + "host": "testserver", + "accept": "*/*", + "accept-encoding": "gzip, deflate", + "connection": "keep-alive", + "user-agent": "testclient", + }, + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "value_error.missing", + "loc": ["header", "save_data"], + "msg": "field required", + } + ) + ] + } + ) + + +def test_header_param_model_extra(client: TestClient): + response = client.get( + "/items/", headers=[("save_data", "true"), ("tool", "plumbus")] + ) + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "host": "testserver", + "save_data": True, + "if_modified_since": None, + "traceparent": None, + "x_tag": [], + } + ) + + +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "name": "host", + "in": "header", + "required": True, + "schema": {"type": "string", "title": "Host"}, + }, + { + "name": "save_data", + "in": "header", + "required": True, + "schema": {"type": "boolean", "title": "Save Data"}, + }, + { + "name": "if_modified_since", + "in": "header", + "required": False, + "schema": IsDict( + { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "If Modified Since", + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "string", + "title": "If Modified Since", + } + ), + }, + { + "name": "traceparent", + "in": "header", + "required": False, + "schema": IsDict( + { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Traceparent", + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "string", + "title": "Traceparent", + } + ), + }, + { + "name": "x_tag", + "in": "header", + "required": False, + "schema": { + "type": "array", + "items": {"type": "string"}, + "default": [], + "title": "X Tag", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } + ) From 8e76d4e5f4ee2e4b9f77378a39aa15940255e164 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 23 Mar 2025 20:49:19 +0000 Subject: [PATCH 030/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5410c75b8..9d4bd3301 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Fix `convert_underscores=False` for header Pydantic models. PR [#13515](https://github.com/fastapi/fastapi/pull/13515) by [@tiangolo](https://github.com/tiangolo). + ### Docs * 📝 Update `docs/en/docs/tutorial/middleware.md`. PR [#13444](https://github.com/fastapi/fastapi/pull/13444) by [@Rishat-F](https://github.com/Rishat-F). From 628c34e0cae200564d191c95d7edea78c88c4b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 23 Mar 2025 23:54:13 +0100 Subject: [PATCH 031/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?5.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9d4bd3301..7e54dd7d6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.115.12 + ### Fixes * 🐛 Fix `convert_underscores=False` for header Pydantic models. PR [#13515](https://github.com/fastapi/fastapi/pull/13515) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 757b76106..80eb783da 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.115.11" +__version__ = "0.115.12" from starlette import status as status From d70f0ecec3d537b903b5c663c4fc3fcc9269db84 Mon Sep 17 00:00:00 2001 From: Blueswen Date: Mon, 24 Mar 2025 19:12:43 +0800 Subject: [PATCH 032/455] =?UTF-8?q?=F0=9F=93=9D=20Add=20External=20Link:?= =?UTF-8?q?=20Taiwanese=20talk=20on=20FastAPI=20with=20observability=20=20?= =?UTF-8?q?(#13527)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/external_links.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/en/data/external_links.yml b/docs/en/data/external_links.yml index 9e411a631..00bb55422 100644 --- a/docs/en/data/external_links.yml +++ b/docs/en/data/external_links.yml @@ -411,3 +411,8 @@ Talks: author_link: https://twitter.com/chriswithers13 link: https://www.youtube.com/watch?v=3DLwPcrE5mA title: 'PyCon UK 2019: FastAPI from the ground up' + Taiwanese: + - author: Bluewen + author_link: https://github.com/blueswen + link: https://www.youtube.com/watch?v=y3sumuoDq4w + title: 'PyCon TW 2024: 全方位強化 Python 服務可觀測性:以 FastAPI 和 Grafana Stack 為例' From cbd7d4895b0a88802f50cd5c6fb05c1ffcb417e7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 24 Mar 2025 11:13:09 +0000 Subject: [PATCH 033/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7e54dd7d6..d09b7c0a0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Add External Link: Taiwanese talk on FastAPI with observability . PR [#13527](https://github.com/fastapi/fastapi/pull/13527) by [@blueswen](https://github.com/blueswen). + ## 0.115.12 ### Fixes From f0d59e57f10e4592f43e11ddca3640791140016c Mon Sep 17 00:00:00 2001 From: Zhongheng Cheng Date: Mon, 24 Mar 2025 17:09:43 -0400 Subject: [PATCH 034/455] =?UTF-8?q?=F0=9F=8C=90=20Update=20Chinese=20trans?= =?UTF-8?q?lation=20for=20`docs/zh/docs/tutorial/first-steps.md`=20(#13348?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/tutorial/first-steps.md | 99 ++++++++++++---------------- 1 file changed, 43 insertions(+), 56 deletions(-) diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md index c4ff460e0..80a34116a 100644 --- a/docs/zh/docs/tutorial/first-steps.md +++ b/docs/zh/docs/tutorial/first-steps.md @@ -11,34 +11,49 @@
```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-/// note - -`uvicorn main:app` 命令含义如下: - -* `main`:`main.py` 文件(一个 Python「模块」)。 -* `app`:在 `main.py` 文件中通过 `app = FastAPI()` 创建的对象。 -* `--reload`:让服务器在更新代码后重新启动。仅在开发时使用该选项。 - -/// - 在输出中,会有一行信息像下面这样: ```hl_lines="4" INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` - 该行显示了你的应用在本机所提供服务的 URL 地址。 ### 查看 @@ -63,7 +78,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) 前往 http://127.0.0.1:8000/redoc。 -你将会看到可选的自动生成文档 (由 ReDoc 提供): +你将会看到可选的自动生成文档 (由 ReDoc 提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -77,9 +92,9 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### API「模式」 -在这种场景下,OpenAPI 是一种规定如何定义 API 模式的规范。 +在这种场景下,OpenAPI 是一种规定如何定义 API 模式的规范。 -定义的 OpenAPI 模式将包括你的 API 路径,以及它们可能使用的参数等等。 +「模式」的定义包括你的 API 路径,以及它们可能使用的参数等等。 #### 数据「模式」 @@ -93,7 +108,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送 #### 查看 `openapi.json` -如果你对原始的 OpenAPI 模式长什么样子感到好奇,其实它只是一个自动生成的包含了所有 API 描述的 JSON。 +如果你对原始的 OpenAPI 模式长什么样子感到好奇,FastAPI 自动生成了包含所有 API 描述的 JSON(模式)。 你可以直接在:http://127.0.0.1:8000/openapi.json 看到它。 @@ -101,7 +116,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送 ```JSON { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" @@ -140,7 +155,7 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送 `FastAPI` 是直接从 `Starlette` 继承的类。 -你可以通过 `FastAPI` 使用所有的 Starlette 的功能。 +你可以通过 `FastAPI` 使用所有的 Starlette 的功能。 /// @@ -152,34 +167,6 @@ OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送 这个实例将是创建你所有 API 的主要交互对象。 -这个 `app` 同样在如下命令中被 `uvicorn` 所引用: - -
- -```console -$ uvicorn main:app --reload - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` - -
- -如果你像下面这样创建应用: - -{* ../../docs_src/first_steps/tutorial002.py hl[3] *} - -将代码放入 `main.py` 文件中,然后你可以像下面这样运行 `uvicorn`: - -
- -```console -$ uvicorn main:my_awesome_api --reload - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` - -
- ### 步骤 3:创建一个*路径操作* #### 路径 @@ -279,13 +266,13 @@ https://example.com/items/foo /// tip -您可以随意使用任何一个操作(HTTP方法)。 +你可以随意使用任何一个操作(HTTP方法)。 **FastAPI** 没有强制要求操作有任何特定的含义。 此处提供的信息仅作为指导,而不是要求。 -比如,当使用 GraphQL 时通常你所有的动作都通过 `post` 一种方法执行。 +比如,当使用 GraphQL 时通常你所有的动作都通过 `POST` 一种方法执行。 /// @@ -331,6 +318,6 @@ https://example.com/items/foo * 导入 `FastAPI`。 * 创建一个 `app` 实例。 -* 编写一个**路径操作装饰器**(如 `@app.get("/")`)。 -* 编写一个**路径操作函数**(如上面的 `def root(): ...`)。 -* 运行开发服务器(如 `uvicorn main:app --reload`)。 +* 编写一个**路径操作装饰器**,如 `@app.get("/")`。 +* 定义一个**路径操作函数**,如 `def root(): ...`。 +* 使用命令 `fastapi dev` 运行开发服务器。 From b58c2a31ed5eeaf0b0ca937fbd932044cd2cbf23 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 24 Mar 2025 21:10:05 +0000 Subject: [PATCH 035/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d09b7c0a0..4704bd53f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📝 Add External Link: Taiwanese talk on FastAPI with observability . PR [#13527](https://github.com/fastapi/fastapi/pull/13527) by [@blueswen](https://github.com/blueswen). +### Translations + +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#13348](https://github.com/fastapi/fastapi/pull/13348) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). + ## 0.115.12 ### Fixes From c12652b7858e70e57c6e65e264d1547a07ef2769 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 14:18:42 +0100 Subject: [PATCH 036/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#12986)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ⬆ [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.4 → v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.4...v0.11.2) * also bump in doc requirements --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: svlandeg Co-authored-by: Sofie Van Landeghem --- .pre-commit-config.yaml | 2 +- requirements-docs-tests.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 05c33a608..6aa7c458d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.4 + rev: v0.11.2 hooks: - id: ruff args: diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index e7718e61d..71f4a7ab9 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests httpx >=0.23.0,<0.28.0 # For linting and generating docs versions -ruff ==0.9.4 +ruff ==0.11.2 From c8a7552e29e369e4e52957d72c8dcbde605c56d6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 26 Mar 2025 13:19:03 +0000 Subject: [PATCH 037/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4704bd53f..e3a703ef9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,10 @@ hide: * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#13348](https://github.com/fastapi/fastapi/pull/13348) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12986](https://github.com/fastapi/fastapi/pull/12986) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + ## 0.115.12 ### Fixes From 031622a989833e9842d1200ab18088ef61424fc3 Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Wed, 26 Mar 2025 15:38:36 +0100 Subject: [PATCH 038/455] =?UTF-8?q?=F0=9F=94=A7=20Clean=20up=20`docs/en/mk?= =?UTF-8?q?docs.yml`=20configuration=20file=20(#13542)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/mkdocs.yml | 76 ++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 50 deletions(-) diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index e9a639d0b..bfa88c06e 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -6,7 +6,7 @@ theme: name: material custom_dir: ../en/overrides palette: - - media: "(prefers-color-scheme)" + - media: (prefers-color-scheme) toggle: icon: material/lightbulb-auto name: Switch to light mode @@ -27,7 +27,6 @@ theme: features: - content.code.annotate - content.code.copy - # - content.code.select - content.footnote.tooltips - content.tabs.link - content.tooltips @@ -35,7 +34,6 @@ theme: - navigation.indexes - navigation.instant - navigation.instant.prefetch - # - navigation.instant.preview - navigation.instant.progress - navigation.path - navigation.tabs @@ -46,7 +44,6 @@ theme: - search.share - search.suggest - toc.follow - icon: repo: fontawesome/brands/github-alt logo: img/icon-white.svg @@ -55,11 +52,7 @@ theme: repo_name: fastapi/fastapi repo_url: https://github.com/fastapi/fastapi plugins: - # Material for MkDocs - search: - # Configured in mkdocs.insiders.yml - # social: - # Other plugins + search: null macros: include_yaml: - external_links: ../en/data/external_links.yml @@ -103,7 +96,6 @@ plugins: signature_crossrefs: true show_symbol_type_heading: true show_symbol_type_toc: true - nav: - FastAPI: index.md - features.md @@ -258,33 +250,27 @@ nav: - benchmarks.md - management.md - release-notes.md - markdown_extensions: - # Python Markdown - abbr: - attr_list: - footnotes: - md_in_html: - tables: + abbr: null + attr_list: null + footnotes: null + md_in_html: null + tables: null toc: permalink: true - - # Python Markdown Extensions - pymdownx.betterem: - pymdownx.caret: + pymdownx.betterem: null + pymdownx.caret: null pymdownx.highlight: line_spans: __span - pymdownx.inlinehilite: - pymdownx.keys: - pymdownx.mark: + pymdownx.inlinehilite: null + pymdownx.keys: null + pymdownx.mark: null pymdownx.superfences: custom_fences: - name: mermaid class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format - pymdownx.tilde: - - # pymdownx blocks + format: !!python/name:pymdownx.superfences.fence_code_format '' + pymdownx.tilde: null pymdownx.blocks.admonition: types: - note @@ -295,17 +281,13 @@ markdown_extensions: - tip - hint - warning - # Custom types - info - check - pymdownx.blocks.details: + pymdownx.blocks.details: null pymdownx.blocks.tab: - alternate_style: True - - # Other extensions - mdx_include: - markdown_include_variants: - + alternate_style: true + mdx_include: null + markdown_include_variants: null extra: analytics: provider: google @@ -313,16 +295,14 @@ extra: feedback: title: Was this page helpful? ratings: - - icon: material/emoticon-happy-outline - name: This page was helpful - data: 1 - note: >- - Thanks for your feedback! - - icon: material/emoticon-sad-outline - name: This page could be improved - data: 0 - note: >- - Thanks for your feedback! + - icon: material/emoticon-happy-outline + name: This page was helpful + data: 1 + note: Thanks for your feedback! + - icon: material/emoticon-sad-outline + name: This page could be improved + data: 0 + note: Thanks for your feedback! social: - icon: fontawesome/brands/github-alt link: https://github.com/fastapi/fastapi @@ -338,7 +318,6 @@ extra: link: https://medium.com/@tiangolo - icon: fontawesome/solid/globe link: https://tiangolo.com - alternate: - link: / name: en - English @@ -390,14 +369,11 @@ extra: name: zh-hant - 繁體中文 - link: /em/ name: 😉 - extra_css: - css/termynal.css - css/custom.css - extra_javascript: - js/termynal.js - js/custom.js - hooks: - ../../scripts/mkdocs_hooks.py From b5bdc153a12716b45a55ff4b9a298a898d1502e0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 26 Mar 2025 14:39:00 +0000 Subject: [PATCH 039/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e3a703ef9..359ec4b49 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Internal +* 🔧 Clean up `docs/en/mkdocs.yml` configuration file. PR [#13542](https://github.com/fastapi/fastapi/pull/13542) by [@svlandeg](https://github.com/svlandeg). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12986](https://github.com/fastapi/fastapi/pull/12986) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). ## 0.115.12 From a49f69f074e334b0abf8cb4aeded213b9f371b9d Mon Sep 17 00:00:00 2001 From: Blueswen Date: Mon, 31 Mar 2025 03:23:32 +0800 Subject: [PATCH 040/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20talk=20infor?= =?UTF-8?q?mation=20typo=20(#13544)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/external_links.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/data/external_links.yml b/docs/en/data/external_links.yml index 00bb55422..50f84ecbf 100644 --- a/docs/en/data/external_links.yml +++ b/docs/en/data/external_links.yml @@ -412,7 +412,7 @@ Talks: link: https://www.youtube.com/watch?v=3DLwPcrE5mA title: 'PyCon UK 2019: FastAPI from the ground up' Taiwanese: - - author: Bluewen + - author: Blueswen author_link: https://github.com/blueswen link: https://www.youtube.com/watch?v=y3sumuoDq4w title: 'PyCon TW 2024: 全方位強化 Python 服務可觀測性:以 FastAPI 和 Grafana Stack 為例' From 4db37fdf954f24bf8e91d141a0ad675fdd9c90c8 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 30 Mar 2025 19:23:55 +0000 Subject: [PATCH 041/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 359ec4b49..bc122be5d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ✏️ Fix talk information typo. PR [#13544](https://github.com/fastapi/fastapi/pull/13544) by [@blueswen](https://github.com/blueswen). * 📝 Add External Link: Taiwanese talk on FastAPI with observability . PR [#13527](https://github.com/fastapi/fastapi/pull/13527) by [@blueswen](https://github.com/blueswen). ### Translations From 396ca6960300a34e4509f754e8d38be6707f3e49 Mon Sep 17 00:00:00 2001 From: Zhongheng Cheng Date: Mon, 31 Mar 2025 04:13:15 -0400 Subject: [PATCH 042/455] =?UTF-8?q?=F0=9F=8C=90=20Update=20Chinese=20trans?= =?UTF-8?q?lation=20for=20`docs/zh/docs/deployment/server-workers.md`=20(#?= =?UTF-8?q?13292)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/deployment/server-workers.md | 156 ++++++++-------------- 1 file changed, 55 insertions(+), 101 deletions(-) diff --git a/docs/zh/docs/deployment/server-workers.md b/docs/zh/docs/deployment/server-workers.md index eb0252a5c..e46ba7a09 100644 --- a/docs/zh/docs/deployment/server-workers.md +++ b/docs/zh/docs/deployment/server-workers.md @@ -1,4 +1,4 @@ -# Server Workers - Gunicorn with Uvicorn +# 服务器工作进程(Workers) - 使用 Uvicorn 的多工作进程模式 让我们回顾一下之前的部署概念: @@ -9,125 +9,79 @@ * 内存 * 启动前的先前步骤 -到目前为止,通过文档中的所有教程,您可能已经在**单个进程**上运行了像 Uvicorn 这样的**服务器程序**。 +到目前为止,在文档中的所有教程中,您可能一直是在运行一个**服务器程序**,例如使用 `fastapi` 命令来启动 Uvicorn,而它默认运行的是**单进程模式**。 -部署应用程序时,您可能希望进行一些**进程复制**,以利用**多核**并能够处理更多请求。 +部署应用程序时,您可能希望进行一些**进程复制**,以利用**多核** CPU 并能够处理更多请求。 正如您在上一章有关[部署概念](concepts.md){.internal-link target=_blank}中看到的,您可以使用多种策略。 -在这里我将向您展示如何将 **Gunicorn** 与 **Uvicorn worker 进程** 一起使用。 +在本章节中,我将向您展示如何使用 `fastapi` 命令或直接使用 `uvicorn` 命令以**多工作进程模式**运行 **Uvicorn**。 /// info 如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank}。 -特别是,当在 **Kubernetes** 上运行时,您可能**不想**使用 Gunicorn,而是运行 **每个容器一个 Uvicorn 进程**,但我将在本章后面告诉您这一点。 +比较特别的是,在 **Kubernetes** 环境中运行时,您通常**不需要**使用多个工作进程,而是**每个容器运行一个 Uvicorn 进程**。不过,我会在本章节的后续部分详细介绍这一点。 /// -## Gunicorn with Uvicorn Workers +## 多个工作进程 -**Gunicorn**主要是一个使用**WSGI标准**的应用服务器。 这意味着 Gunicorn 可以为 Flask 和 Django 等应用程序提供服务。 Gunicorn 本身与 **FastAPI** 不兼容,因为 FastAPI 使用最新的 **ASGI 标准**。 +您可以使用 `--workers` 命令行选项来启动多个工作进程: -但 Gunicorn 支持充当 **进程管理器** 并允许用户告诉它要使用哪个特定的 **worker类**。 然后 Gunicorn 将使用该类启动一个或多个 **worker进程**。 +//// tab | `fastapi` -**Uvicorn** 有一个 Gunicorn 兼容的worker类。 - -使用这种组合,Gunicorn 将充当 **进程管理器**,监听 **端口** 和 **IP**。 它会将通信**传输**到运行**Uvicorn类**的worker进程。 - -然后与Gunicorn兼容的**Uvicorn worker**类将负责将Gunicorn发送的数据转换为ASGI标准以供FastAPI使用。 - -## 安装 Gunicorn 和 Uvicorn +如果您使用 `fastapi` 命令:
```console -$ pip install "uvicorn[standard]" gunicorn +$ fastapi run --workers 4 main.py ----> 100% + FastAPI Starting production server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. ```
-这将安装带有`standard`扩展包(以获得高性能)的 Uvicorn 和 Gunicorn。 +//// -## Run Gunicorn with Uvicorn Workers +//// tab | `uvicorn` -接下来你可以通过以下命令运行Gunicorn: - -
- -```console -$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80 - -[19499] [INFO] Starting gunicorn 20.1.0 -[19499] [INFO] Listening at: http://0.0.0.0:80 (19499) -[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker -[19511] [INFO] Booting worker with pid: 19511 -[19513] [INFO] Booting worker with pid: 19513 -[19514] [INFO] Booting worker with pid: 19514 -[19515] [INFO] Booting worker with pid: 19515 -[19511] [INFO] Started server process [19511] -[19511] [INFO] Waiting for application startup. -[19511] [INFO] Application startup complete. -[19513] [INFO] Started server process [19513] -[19513] [INFO] Waiting for application startup. -[19513] [INFO] Application startup complete. -[19514] [INFO] Started server process [19514] -[19514] [INFO] Waiting for application startup. -[19514] [INFO] Application startup complete. -[19515] [INFO] Started server process [19515] -[19515] [INFO] Waiting for application startup. -[19515] [INFO] Application startup complete. -``` - -
- - -让我们看看每个选项的含义: - -* `main:app`:这与 Uvicorn 使用的语法相同,`main` 表示名为"`main`"的 Python 模块,因此是文件 `main.py`。 `app` 是 **FastAPI** 应用程序的变量名称。 - * 你可以想象 `main:app` 相当于一个 Python `import` 语句,例如: - - ```Python - from main import app - ``` - - * 因此,`main:app` 中的冒号相当于 `from main import app` 中的 Python `import` 部分。 - -* `--workers`:要使用的worker进程数量,每个进程将运行一个 Uvicorn worker进程,在本例中为 4 个worker进程。 - -* `--worker-class`:在worker进程中使用的与 Gunicorn 兼容的工作类。 - * 这里我们传递了 Gunicorn 可以导入和使用的类: - - ```Python - import uvicorn.workers.UvicornWorker - ``` - -* `--bind`:这告诉 Gunicorn 要监听的 IP 和端口,使用冒号 (`:`) 分隔 IP 和端口。 - * 如果您直接运行 Uvicorn,则可以使用`--host 0.0.0.0`和`--port 80`,而不是`--bind 0.0.0.0:80`(Gunicorn 选项)。 - - -在输出中,您可以看到它显示了每个进程的 **PID**(进程 ID)(它只是一个数字)。 - -你可以看到: - -* Gunicorn **进程管理器** 以 PID `19499` 开头(在您的情况下,它将是一个不同的数字)。 -* 然后它开始`Listening at: http://0.0.0.0:80`。 -* 然后它检测到它必须使用 `uvicorn.workers.UvicornWorker` 处的worker类。 -* 然后它启动**4个worker**,每个都有自己的PID:`19511`、`19513`、`19514`和`19515`。 - -Gunicorn 还将负责管理**死进程**和**重新启动**新进程(如果需要保持worker数量)。 因此,这在一定程度上有助于上面列表中**重启**的概念。 - -尽管如此,您可能还希望有一些外部的东西,以确保在必要时**重新启动 Gunicorn**,并且**在启动时运行它**等。 - -## Uvicorn with Workers - -Uvicorn 也有一个选项可以启动和运行多个 **worker进程**。 - -然而,到目前为止,Uvicorn 处理worker进程的能力比 Gunicorn 更有限。 因此,如果您想拥有这个级别(Python 级别)的进程管理器,那么最好尝试使用 Gunicorn 作为进程管理器。 - -无论如何,您都可以像这样运行它: +如果您更想要直接使用 `uvicorn` 命令:
@@ -151,13 +105,15 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
+//// + 这里唯一的新选项是 `--workers` 告诉 Uvicorn 启动 4 个工作进程。 -您还可以看到它显示了每个进程的 **PID**,父进程(这是 **进程管理器**)的 PID 为`27365`,每个工作进程的 PID 为:`27368`、`27369`, `27370`和`27367`。 +您还可以看到它显示了每个进程的 **PID**,父进程(这是**进程管理器**)的 PID 为`27365`,每个工作进程的 PID 为:`27368`、`27369`, `27370`和`27367`。 ## 部署概念 -在这里,您了解了如何使用 **Gunicorn**(或 Uvicorn)管理 **Uvicorn 工作进程**来**并行**应用程序的执行,利用 CPU 中的 **多核**,并 能够满足**更多请求**。 +在这里,您学习了如何使用多个**工作进程(workers)**来让应用程序的执行**并行化**,充分利用 CPU 的**多核性能**,并能够处理**更多的请求**。 从上面的部署概念列表来看,使用worker主要有助于**复制**部分,并对**重新启动**有一点帮助,但您仍然需要照顾其他部分: @@ -170,15 +126,13 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 ## 容器和 Docker -在关于 [容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank} 的下一章中,我将介绍一些可用于处理其他 **部署概念** 的策略。 +在关于 [容器中的 FastAPI - Docker](docker.md){.internal-link target=_blank} 的下一章中,我将介绍一些可用于处理其他**部署概念**的策略。 -我还将向您展示 **官方 Docker 镜像**,其中包括 **Gunicorn 和 Uvicorn worker** 以及一些对简单情况有用的默认配置。 - -在那里,我还将向您展示如何 **从头开始构建自己的镜像** 以运行单个 Uvicorn 进程(没有 Gunicorn)。 这是一个简单的过程,并且可能是您在使用像 **Kubernetes** 这样的分布式容器管理系统时想要做的事情。 +我将向您展示如何**从零开始构建自己的镜像**,以运行一个单独的 Uvicorn 进程。这个过程相对简单,并且在使用 **Kubernetes** 等分布式容器管理系统时,这通常是您需要采取的方法。 ## 回顾 -您可以使用**Gunicorn**(或Uvicorn)作为Uvicorn工作进程的进程管理器,以利用**多核CPU**,**并行运行多个进程**。 +您可以在使用 `fastapi` 或 `uvicorn` 命令时,通过 `--workers` CLI 选项启用多个工作进程(workers),以充分利用**多核 CPU**,以**并行运行多个进程**。 如果您要设置**自己的部署系统**,同时自己处理其他部署概念,则可以使用这些工具和想法。 From c5e2837e461ca037746b577dbc0306f8cb5bd5c6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 31 Mar 2025 08:13:40 +0000 Subject: [PATCH 043/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bc122be5d..617758cba 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* 🌐 Update Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#13292](https://github.com/fastapi/fastapi/pull/13292) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#13348](https://github.com/fastapi/fastapi/pull/13348) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). ### Internal From d0a247fc5a0d8b0edf1b2848396f765c3ffe74b9 Mon Sep 17 00:00:00 2001 From: Zhongheng Cheng Date: Mon, 31 Mar 2025 04:14:47 -0400 Subject: [PATCH 044/455] =?UTF-8?q?=F0=9F=8C=90=20Update=20Chinese=20trans?= =?UTF-8?q?lation=20for=20`docs/zh/docs/deployment/manually.md`=20(#13324)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/deployment/manually.md | 162 ++++++++++++++-------------- 1 file changed, 80 insertions(+), 82 deletions(-) diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index 30ee7a1e9..3dc5942e3 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -1,12 +1,62 @@ -# 手动运行服务器 - Uvicorn +# 手动运行服务器 -在远程服务器计算机上运行 **FastAPI** 应用程序所需的主要东西是 ASGI 服务器程序,例如 **Uvicorn**。 +## 使用 `fastapi run` 命令 -有 3 个主要可选方案: +简而言之,使用 `fastapi run` 来运行您的 FastAPI 应用程序: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +这在大多数情况下都能正常运行。😎 + +例如,您可以使用该命令在容器、服务器等环境中启动您的 **FastAPI** 应用。 + +## ASGI 服务器 + +让我们深入了解一些细节。 + +FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称为 ASGI。FastAPI 本质上是一个 ASGI Web 框架。 + +要在远程服务器上运行 **FastAPI** 应用(或任何其他 ASGI 应用),您需要一个 ASGI 服务器程序,例如 **Uvicorn**。它是 `fastapi` 命令默认使用的 ASGI 服务器。 + +除此之外,还有其他一些可选的 ASGI 服务器,例如: * Uvicorn:高性能 ASGI 服务器。 * Hypercorn:与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。 * Daphne:为 Django Channels 构建的 ASGI 服务器。 +* Granian:基于 Rust 的 HTTP 服务器,专为 Python 应用设计。 +* NGINX Unit:NGINX Unit 是一个轻量级且灵活的 Web 应用运行时环境。 ## 服务器主机和服务器程序 @@ -21,11 +71,13 @@ ## 安装服务器程序 -您可以使用以下命令安装 ASGI 兼容服务器: +当您安装 FastAPI 时,它自带一个生产环境服务器——Uvicorn,并且您可以使用 `fastapi run` 命令来启动它。 -//// tab | Uvicorn +不过,您也可以手动安装 ASGI 服务器。 -* Uvicorn,一个快如闪电 ASGI 服务器,基于 uvloop 和 httptools 构建。 +请确保您创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后再安装服务器应用程序。 + +例如,要安装 Uvicorn,可以运行以下命令:
@@ -37,39 +89,21 @@ $ pip install "uvicorn[standard]"
+类似的流程也适用于任何其他 ASGI 服务器程序。 + /// tip -通过添加`standard`,Uvicorn 将安装并使用一些推荐的额外依赖项。 +通过添加 `standard` 选项,Uvicorn 将安装并使用一些推荐的额外依赖项。 -其中包括`uvloop`,它是`asyncio`的高性能替代品,它提供了巨大的并发性能提升。 +其中包括 `uvloop`,这是 `asyncio` 的高性能替代方案,能够显著提升并发性能。 + +当您使用 `pip install "fastapi[standard]"` 安装 FastAPI 时,实际上也会安装 `uvicorn[standard]`。 /// -//// - -//// tab | Hypercorn - -* Hypercorn,一个也与 HTTP/2 兼容的 ASGI 服务器。 - -
- -```console -$ pip install hypercorn - ----> 100% -``` - -
- -...或任何其他 ASGI 服务器。 - -//// - ## 运行服务器程序 -您可以按照之前教程中的相同方式运行应用程序,但不使用`--reload`选项,例如: - -//// tab | Uvicorn +如果您手动安装了 ASGI 服务器,通常需要以特定格式传递一个导入字符串,以便服务器能够正确导入您的 FastAPI 应用:
@@ -81,79 +115,43 @@ $ uvicorn main:app --host 0.0.0.0 --port 80
-//// +/// note -//// tab | Hypercorn +命令 `uvicorn main:app` 的含义如下: -
+* `main`:指的是 `main.py` 文件(即 Python “模块”)。 +* `app`:指的是 `main.py` 文件中通过 `app = FastAPI()` 创建的对象。 -```console -$ hypercorn main:app --bind 0.0.0.0:80 +它等价于以下导入语句: -Running on 0.0.0.0:8080 over http (CTRL + C to quit) +```Python +from main import app ``` -
- -//// - -/// warning - -如果您正在使用`--reload`选项,请记住删除它。 - - `--reload` 选项消耗更多资源,并且更不稳定。 - - 它在**开发**期间有很大帮助,但您**不应该**在**生产环境**中使用它。 - /// -## Hypercorn with Trio +每种 ASGI 服务器程序通常都会有类似的命令,您可以在它们的官方文档中找到更多信息。 -Starlette 和 **FastAPI** 基于 AnyIO, 所以它们才能同时与 Python 的标准库 asyncioTrio 兼容。 +/// warning -尽管如此,Uvicorn 目前仅与 asyncio 兼容,并且通常使用 `uvloop`, 它是`asyncio`的高性能替代品。 +Uvicorn 和其他服务器支持 `--reload` 选项,该选项在开发过程中非常有用。 -但如果你想直接使用**Trio**,那么你可以使用**Hypercorn**,因为它支持它。 ✨ +但 `--reload` 选项会消耗更多资源,且相对不稳定。 -### 安装具有 Trio 的 Hypercorn +它对于**开发阶段**非常有帮助,但在**生产环境**中**不应该**使用。 -首先,您需要安装具有 Trio 支持的 Hypercorn: - -
- -```console -$ pip install "hypercorn[trio]" ----> 100% -``` - -
- -### Run with Trio - -然后你可以传递值`trio`给命令行选项`--worker-class`: - -
- -```console -$ hypercorn main:app --worker-class trio -``` - -
- -这将通过您的应用程序启动 Hypercorn,并使用 Trio 作为后端。 - -现在您可以在应用程序内部使用 Trio。 或者更好的是,您可以使用 AnyIO,使您的代码与 Trio 和 asyncio 兼容。 🎉 +/// ## 部署概念 -这些示例运行服务器程序(例如 Uvicorn),启动**单个进程**,在所有 IP(`0.0.0.0`)上监听预定义端口(例如`80`)。 +这些示例运行服务器程序(例如 Uvicorn),启动**单个进程**,在所有 IP(`0.0.0.0`)上监听预定义端口(例如`80`)。 这是基本思路。 但您可能需要处理一些其他事情,例如: * 安全性 - HTTPS * 启动时运行 * 重新启动 -* Replication(运行的进程数) +* 复制(运行的进程数) * 内存 * 开始前的步骤 From 94ae778082ce6d9ce22c0088f234cc19dc012d5a Mon Sep 17 00:00:00 2001 From: Zhongheng Cheng Date: Mon, 31 Mar 2025 04:15:11 -0400 Subject: [PATCH 045/455] =?UTF-8?q?=F0=9F=8C=90=20Update=20Chinese=20trans?= =?UTF-8?q?lation=20for=20`docs/zh/docs/tutorial/index.md`=20(#13374)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/tutorial/index.md | 80 +++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md index ab19f02c5..3ca927337 100644 --- a/docs/zh/docs/tutorial/index.md +++ b/docs/zh/docs/tutorial/index.md @@ -1,34 +1,58 @@ # 教程 - 用户指南 -本教程将一步步向你展示如何使用 **FastAPI** 的绝大部分特性。 +本教程将一步步向您展示如何使用 **FastAPI** 的绝大部分特性。 -各个章节的内容循序渐进,但是又围绕着单独的主题,所以你可以直接跳转到某个章节以解决你的特定需求。 +各个章节的内容循序渐进,但是又围绕着单独的主题,所以您可以直接跳转到某个章节以解决您的特定需求。 -本教程同样可以作为将来的参考手册。 - -你可以随时回到本教程并查阅你需要的内容。 +本教程同样可以作为将来的参考手册,所以您可以随时回到本教程并查阅您需要的内容。 ## 运行代码 所有代码片段都可以复制后直接使用(它们实际上是经过测试的 Python 文件)。 -要运行任何示例,请将代码复制到 `main.py` 文件中,然后使用以下命令启动 `uvicorn`: +要运行任何示例,请将代码复制到 `main.py` 文件中,然后使用以下命令启动 `fastapi dev`:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-强烈建议你在本地编写或复制代码,对其进行编辑并运行。 +**强烈建议**您在本地编写或复制代码,对其进行编辑并运行。 在编辑器中使用 FastAPI 会真正地展现出它的优势:只需要编写很少的代码,所有的类型检查,代码补全等等。 @@ -36,48 +60,34 @@ $ uvicorn main:app --reload ## 安装 FastAPI -第一个步骤是安装 FastAPI。 +第一个步骤是安装 FastAPI. -为了使用本教程,你可能需要安装所有的可选依赖及对应功能: +请确保您创建并激活一个[虚拟环境](../virtual-environments.md){.internal-link target=_blank},然后**安装 FastAPI**:
```console -$ pip install "fastapi[all]" +$ pip install "fastapi[standard]" ---> 100% ```
-......以上安装还包括了 `uvicorn`,你可以将其用作运行代码的服务器。 - /// note -你也可以分开来安装。 +当您使用 `pip install "fastapi[standard]"` 进行安装时,它会附带一些默认的可选标准依赖项。 -假如你想将应用程序部署到生产环境,你可能要执行以下操作: - -``` -pip install fastapi -``` - -并且安装`uvicorn`来作为服务器: - -``` -pip install "uvicorn[standard]" -``` - -然后对你想使用的每个可选依赖项也执行相同的操作。 +如果您不想安装这些可选依赖,可以选择安装 `pip install fastapi`。 /// ## 进阶用户指南 -在本**教程-用户指南**之后,你可以阅读**进阶用户指南**。 +在本**教程-用户指南**之后,您可以阅读**进阶用户指南**。 **进阶用户指南**以本教程为基础,使用相同的概念,并教授一些额外的特性。 -但是你应该先阅读**教程-用户指南**(即你现在正在阅读的内容)。 +但是您应该先阅读**教程-用户指南**(即您现在正在阅读的内容)。 -教程经过精心设计,使你可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据你的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。 +教程经过精心设计,使您可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据您的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。 From 4749ff586c5f4951aec9b3724bbc3fd163e46bdf Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 31 Mar 2025 08:16:12 +0000 Subject: [PATCH 046/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 617758cba..a869743d4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* 🌐 Update Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#13324](https://github.com/fastapi/fastapi/pull/13324) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#13292](https://github.com/fastapi/fastapi/pull/13292) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#13348](https://github.com/fastapi/fastapi/pull/13348) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). From 921e2e58816bc21555bfe5498912cc5fafe5f168 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 31 Mar 2025 08:16:36 +0000 Subject: [PATCH 047/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a869743d4..955bc6467 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/index.md`. PR [#13374](https://github.com/fastapi/fastapi/pull/13374) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#13324](https://github.com/fastapi/fastapi/pull/13324) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#13292](https://github.com/fastapi/fastapi/pull/13292) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#13348](https://github.com/fastapi/fastapi/pull/13348) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). From cfdcad1dd2ad6821129d8151b7d1171d4efa04aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82=D0=B8?= =?UTF-8?q?=D0=BD=20=D0=A0=D0=BE=D1=89=D1=83=D0=BF=D0=BA=D0=B8=D0=BD?= <53541518+minaton-ru@users.noreply.github.com> Date: Mon, 31 Mar 2025 11:20:29 +0300 Subject: [PATCH 048/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translat?= =?UTF-8?q?ion=20for=20`docs/ru/docs/tutorial/header-param-models.md`=20(#?= =?UTF-8?q?13526)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/docs/tutorial/header-param-models.md | 72 ++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 docs/ru/docs/tutorial/header-param-models.md diff --git a/docs/ru/docs/tutorial/header-param-models.md b/docs/ru/docs/tutorial/header-param-models.md new file mode 100644 index 000000000..4f54e3e15 --- /dev/null +++ b/docs/ru/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# Модели Header-параметров + +Если у вас есть группа связанных **header-параметров**, то вы можете объединить их в одну **Pydantic-модель**. + +Это позволит вам **переиспользовать модель** в **разных местах**, а также задать валидацию и метаданные сразу для всех параметров. 😎 + +/// note | Заметка + +Этот функционал доступен в FastAPI начиная с версии `0.115.0`. 🤓 + +/// + +## Header-параметры в виде Pydantic-модели + +Объявите нужные **header-параметры** в **Pydantic-модели** и затем аннотируйте параметр как `Header`: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +**FastAPI** **извлечёт** данные для **каждого поля** из **заголовков** запроса и выдаст заданную вами Pydantic-модель. + +## Проверьте документацию + +Вы можете посмотреть нужные header-параметры в графическом интерфейсе сгенерированной документации по пути `/docs`: + +
+ +
+ +## Как запретить дополнительные заголовки + +В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** заголовки, которые вы хотите получать. + +Вы можете использовать возможности конфигурации Pydantic-модели для того, чтобы запретить (`forbid`) любые дополнительные (`extra`) поля: + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Если клиент попробует отправить **дополнительные заголовки**, то в ответ он получит **ошибку**. + +Например, если клиент попытается отправить заголовок `tool` со значением `plumbus`, то в ответ он получит ошибку, сообщающую ему, что header-параметр `tool` не разрешен: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## Как отключить автоматическое преобразование подчеркиваний + +Как и в случае с обычными заголовками, если у вас в именах параметров имеются символы подчеркивания, они **автоматически преобразовываются в дефис**. + +Например, если в коде есть header-параметр `save_data`, то ожидаемый HTTP-заголовок будет `save-data` и именно так он будет отображаться в документации. + +Если по каким-то причинам вам нужно отключить данное автоматическое преобразование, это можно сделать и для Pydantic-моделей для header-параметров. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | Внимание + +Перед тем как устанавливать для параметра `convert_underscores` значение `False`, имейте в виду, что некоторые HTTP-прокси и серверы не разрешают использовать заголовки с символами подчеркивания. + +/// + +## Резюме + +Вы можете использовать **Pydantic-модели** для объявления **header-параметров** в **FastAPI**. 😎 From 1d434dec47e43e221bc10115bd1f0844956f9437 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 31 Mar 2025 08:21:02 +0000 Subject: [PATCH 049/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 955bc6467..264dfb2ab 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-param-models.md`. PR [#13526](https://github.com/fastapi/fastapi/pull/13526) by [@minaton-ru](https://github.com/minaton-ru). * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/index.md`. PR [#13374](https://github.com/fastapi/fastapi/pull/13374) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#13324](https://github.com/fastapi/fastapi/pull/13324) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#13292](https://github.com/fastapi/fastapi/pull/13292) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). From 6fefc17a84bed78378435ba492cde04cf979fc19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Apr 2025 21:33:35 +0200 Subject: [PATCH 050/455] =?UTF-8?q?=E2=AC=86=20Bump=20dirty-equals=20from?= =?UTF-8?q?=200.8.0=20to=200.9.0=20(#13561)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dirty-equals](https://github.com/samuelcolvin/dirty-equals) from 0.8.0 to 0.9.0. - [Release notes](https://github.com/samuelcolvin/dirty-equals/releases) - [Commits](https://github.com/samuelcolvin/dirty-equals/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: dirty-equals dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-tests.txt b/requirements-tests.txt index 6a870add6..013b9a35a 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -3,7 +3,7 @@ pytest >=7.1.3,<9.0.0 coverage[toml] >= 6.5.0,< 8.0 mypy ==1.8.0 -dirty-equals ==0.8.0 +dirty-equals ==0.9.0 sqlmodel==0.0.23 flask >=1.1.2,<4.0.0 anyio[trio] >=3.2.1,<5.0.0 From 77c8b5b3b9c5c1273bcb4b799b24ed2e04fd2c90 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Apr 2025 19:33:56 +0000 Subject: [PATCH 051/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 264dfb2ab..546e1d717 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Internal +* ⬆ Bump dirty-equals from 0.8.0 to 0.9.0. PR [#13561](https://github.com/fastapi/fastapi/pull/13561) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Clean up `docs/en/mkdocs.yml` configuration file. PR [#13542](https://github.com/fastapi/fastapi/pull/13542) by [@svlandeg](https://github.com/svlandeg). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12986](https://github.com/fastapi/fastapi/pull/12986) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 286f5a0c42e1817f0d64564afb4e8051ce85140c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 2 Apr 2025 21:47:36 +0200 Subject: [PATCH 052/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#13558)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/data/contributors.yml | 21 +-- docs/en/data/translation_reviewers.yml | 178 +++++++++++++++---------- docs/en/data/translators.yml | 49 ++++--- 3 files changed, 144 insertions(+), 104 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index c4364e923..1910854af 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,17 +1,17 @@ tiangolo: login: tiangolo - count: 723 + count: 730 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 94 + count: 98 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: login: alejsdev count: 47 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=843355286cea366cbb3a4fc3a14343bd4eceef55&v=4 url: https://github.com/alejsdev github-actions: login: github-actions @@ -25,7 +25,7 @@ Kludex: url: https://github.com/Kludex pre-commit-ci: login: pre-commit-ci - count: 22 + count: 23 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci dmontagu: @@ -70,7 +70,7 @@ vishnuvskvkl: url: https://github.com/vishnuvskvkl svlandeg: login: svlandeg - count: 6 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 url: https://github.com/svlandeg alissadb: @@ -171,7 +171,7 @@ hukkin: marcosmmb: login: marcosmmb count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/6181089?u=b8567a842b38c5570c315b2b7ca766fa7be6721e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/6181089?u=03c50eec631857d84df5232890780d00a3f76903&v=4 url: https://github.com/marcosmmb Serrones: login: Serrones @@ -311,7 +311,7 @@ dconathan: Jamim: login: Jamim count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=0cf3027bec78ba4f0b89802430c136bc69847d7a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=9ce0b6a6d1a5124e28b3c04d8d26827ca328713a&v=4 url: https://github.com/Jamim svalouch: login: svalouch @@ -366,7 +366,7 @@ sattosan: michaeloliverx: login: michaeloliverx count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/55017335?u=e606eb5cc397c07523be47637b1ee796904fbb59&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/55017335?u=efb0cb6e261ff64d862fafb91ee80fc2e1f8a2ed&v=4 url: https://github.com/michaeloliverx voegtlel: login: voegtlel @@ -528,3 +528,8 @@ DanielYang59: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/80093591?u=63873f701c7c74aac83c906800a1dddc0bc8c92f&v=4 url: https://github.com/DanielYang59 +blueswen: + login: blueswen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1564148?u=6d6b8cc8f2b5cef715e68d6175154a8a94d518ee&v=4 + url: https://github.com/blueswen diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 1a3c12988..5f1a89141 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -8,16 +8,16 @@ Xewus: count: 140 avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 url: https://github.com/Xewus +sodaMelon: + login: sodaMelon + count: 113 + avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 + url: https://github.com/sodaMelon ceb10n: login: ceb10n count: 112 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n -sodaMelon: - login: sodaMelon - count: 111 - avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 - url: https://github.com/sodaMelon tokusumi: login: tokusumi count: 104 @@ -33,6 +33,11 @@ hard-coders: count: 92 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders +alv2017: + login: alv2017 + count: 86 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 nazarepiedady: login: nazarepiedady count: 83 @@ -43,11 +48,6 @@ AlertRED: count: 81 avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4 url: https://github.com/AlertRED -alv2017: - login: alv2017 - count: 81 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 Alexandrhub: login: Alexandrhub count: 68 @@ -65,12 +65,12 @@ cassiobotaro: url: https://github.com/cassiobotaro mattwang44: login: mattwang44 - count: 58 + count: 59 avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4 url: https://github.com/mattwang44 tiangolo: login: tiangolo - count: 51 + count: 52 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo Laineyzhang55: @@ -88,16 +88,26 @@ komtaki: count: 45 avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 url: https://github.com/komtaki +rostik1410: + login: rostik1410 + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 + url: https://github.com/rostik1410 +svlandeg: + login: svlandeg + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg alperiox: login: alperiox count: 42 avatarUrl: https://avatars.githubusercontent.com/u/34214152?u=2c5acad3461d4dbc2d48371ba86cac56ae9b25cc&v=4 url: https://github.com/alperiox -rostik1410: - login: rostik1410 +Rishat-F: + login: Rishat-F count: 41 - avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 - url: https://github.com/rostik1410 + avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 + url: https://github.com/Rishat-F Winand: login: Winand count: 40 @@ -126,7 +136,7 @@ SwftAlpc: alejsdev: login: alejsdev count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=843355286cea366cbb3a4fc3a14343bd4eceef55&v=4 url: https://github.com/alejsdev timothy-jeong: login: timothy-jeong @@ -138,16 +148,6 @@ nilslindemann: count: 35 avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 url: https://github.com/nilslindemann -svlandeg: - login: svlandeg - count: 35 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg -Rishat-F: - login: Rishat-F - count: 35 - avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 - url: https://github.com/Rishat-F rjNemo: login: rjNemo count: 34 @@ -158,6 +158,11 @@ codingjenny: count: 34 avatarUrl: https://avatars.githubusercontent.com/u/103817302?u=3a042740dc0ff58615da0d8679230966fd7693e8&v=4 url: https://github.com/codingjenny +mezgoodle: + login: mezgoodle + count: 33 + avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4 + url: https://github.com/mezgoodle akarev0: login: akarev0 count: 33 @@ -178,6 +183,11 @@ LorhanSohaky: count: 30 avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 url: https://github.com/LorhanSohaky +Vincy1230: + login: Vincy1230 + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4 + url: https://github.com/Vincy1230 black-redoc: login: black-redoc count: 29 @@ -201,7 +211,7 @@ dedkot01: hsuanchi: login: hsuanchi count: 28 - avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=0b094ae292292fee093818e37ceb645c114d2bff&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=7d25a398e478b6e63503bf6f26c54efa9e0da07b&v=4 url: https://github.com/hsuanchi dpinezich: login: dpinezich @@ -228,16 +238,6 @@ junah201: count: 26 avatarUrl: https://avatars.githubusercontent.com/u/75025529?u=2451c256e888fa2a06bcfc0646d09b87ddb6a945&v=4 url: https://github.com/junah201 -mezgoodle: - login: mezgoodle - count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=e871bc26734eb2436d98c19c3fb57a4773e13c24&v=4 - url: https://github.com/mezgoodle -Vincy1230: - login: Vincy1230 - count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4 - url: https://github.com/Vincy1230 zy7y: login: zy7y count: 25 @@ -376,8 +376,13 @@ Joao-Pedro-P-Holanda: JaeHyuckSa: login: JaeHyuckSa count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/104830931?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/104830931?u=b19b3e24d6030f88d22bd3e953f9525d2f062da3&v=4 url: https://github.com/JaeHyuckSa +SofiiaTrufanova: + login: SofiiaTrufanova + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/63260929?u=483e0b64fabc76343b3be39b7e1dcb930a95e1bb&v=4 + url: https://github.com/SofiiaTrufanova Jedore: login: Jedore count: 15 @@ -411,8 +416,13 @@ BORA040126: mattkoehne: login: mattkoehne count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/80362153?u=6e1439582715693407b86182eb66263bb578a761&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4 url: https://github.com/mattkoehne +DianaTrufanova: + login: DianaTrufanova + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/119067607?u=1cd55f841b68b4a187fa6d06a7dafa5f070195aa&v=4 + url: https://github.com/DianaTrufanova jovicon: login: jovicon count: 13 @@ -706,7 +716,7 @@ KimJoonSeo: MinLee0210: login: MinLee0210 count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=7def7c0654ad82f43b46d6dfc3b51c4d2be15011&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=25f979af418692b95e907df93607a09117e14b53&v=4 url: https://github.com/MinLee0210 camigomezdev: login: camigomezdev @@ -718,6 +728,11 @@ maru0123-2004: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 url: https://github.com/maru0123-2004 +minaton-ru: + login: minaton-ru + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/53541518?u=67336ca11a85493f75031508aade588dad3b9910&v=4 + url: https://github.com/minaton-ru Serrones: login: Serrones count: 7 @@ -873,16 +888,11 @@ bankofsardine: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/44944207?u=0368e1b698ffab6bf29e202f9fd2dddd352429f1&v=4 url: https://github.com/bankofsardine -SofiiaTrufanova: - login: SofiiaTrufanova +valentinDruzhinin: + login: valentinDruzhinin count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/63260929?v=4 - url: https://github.com/SofiiaTrufanova -DianaTrufanova: - login: DianaTrufanova - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/119067607?v=4 - url: https://github.com/DianaTrufanova + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin rsip22: login: rsip22 count: 5 @@ -911,7 +921,7 @@ TemaSpb: BugLight: login: BugLight count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/13618366?u=57572e544e40c2a491db5bf7255bd24886d2cb09&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/13618366?u=7d733749f80e5f7e66a434cf42aedcfc60340f43&v=4 url: https://github.com/BugLight 0x4Dark: login: 0x4Dark @@ -998,6 +1008,11 @@ devluisrodrigues: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/103431660?u=d9674a3249edc4601d2c712cdebf899918503c3a&v=4 url: https://github.com/devluisrodrigues +Zerohertz: + login: Zerohertz + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=c6acda352c866b1747921e0ff8782b58571d849e&v=4 + url: https://github.com/Zerohertz 11kkw: login: 11kkw count: 5 @@ -1033,6 +1048,11 @@ FelipeSilva93: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/66804965?u=e7cb4b580e46f2e04ecb4cd4d7a12acdddd3c6c1&v=4 url: https://github.com/FelipeSilva93 +peacekimjapan: + login: peacekimjapan + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/33534175?u=e4219bcebc3773a7068cc34c3eb268ef77cec31b&v=4 + url: https://github.com/peacekimjapan bas-baskara: login: bas-baskara count: 4 @@ -1061,7 +1081,7 @@ aminalaee: erfan-rfmhr: login: erfan-rfmhr count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/98986056?u=6c4f9218fe5bb04780dd92bfced360c55e2009f0&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/98986056?u=b1559d684b1ced11b2204546fa3cf28addf665a8&v=4 url: https://github.com/erfan-rfmhr Scorpionchiques: login: Scorpionchiques @@ -1123,11 +1143,11 @@ gerry-sabar: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 url: https://github.com/gerry-sabar -valentinDruzhinin: - login: valentinDruzhinin +cookie-byte217: + login: cookie-byte217 count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin + avatarUrl: https://avatars.githubusercontent.com/u/57880178?v=4 + url: https://github.com/cookie-byte217 tyronedamasceno: login: tyronedamasceno count: 3 @@ -1206,7 +1226,7 @@ RuslanTer: FedorGN: login: FedorGN count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66411909?u=1c6734e92f50c7d66f130ef7d394e72b53770fe6&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66411909?u=22382380e7d66ee57ffbfc2ae6bd5efd0cdb672e&v=4 url: https://github.com/FedorGN rafsaf: login: rafsaf @@ -1328,6 +1348,11 @@ kohiry: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/57669492?u=f6ab0a062740261e882879269a41a47788c84043&v=4 url: https://github.com/kohiry +ptt3199: + login: ptt3199 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=2c3d947a80283e32bf616d4c3af139a6be69680f&v=4 + url: https://github.com/ptt3199 arynoot: login: arynoot count: 3 @@ -1353,16 +1378,21 @@ RyaWcksn: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/42831964?u=0cb4265faf3e3425a89e59b6fddd3eb2de180af0&v=4 url: https://github.com/RyaWcksn -Zerohertz: - login: Zerohertz - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=c6acda352c866b1747921e0ff8782b58571d849e&v=4 - url: https://github.com/Zerohertz tienduong-21: login: tienduong-21 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/80129618?v=4 url: https://github.com/tienduong-21 +jameselite: + login: jameselite + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=6964d633449bf7d4a83d0fa0198f81f9ee5cfcd0&v=4 + url: https://github.com/jameselite +zbellos: + login: zbellos + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/204500646?v=4 + url: https://github.com/zbellos blaisep: login: blaisep count: 2 @@ -1468,11 +1498,6 @@ lindsayzhou: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/26602940?u=3c52ce6393bb547c97e6380ccdee03e0c64152c6&v=4 url: https://github.com/0xflotus -peacekimjapan: - login: peacekimjapan - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/33534175?u=e4219bcebc3773a7068cc34c3eb268ef77cec31b&v=4 - url: https://github.com/peacekimjapan jonatasoli: login: jonatasoli count: 2 @@ -1656,7 +1681,7 @@ zhiquanchi: Jamim: login: Jamim count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=0cf3027bec78ba4f0b89802430c136bc69847d7a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=9ce0b6a6d1a5124e28b3c04d8d26827ca328713a&v=4 url: https://github.com/Jamim alvinkhalil: login: alvinkhalil @@ -1666,7 +1691,7 @@ alvinkhalil: leylaeminova: login: leylaeminova count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/100516839?u=35a9ce14bb86d7d7faa25d432f61dec2984cb818&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/100516839?u=0b0dab9e31742076b22812b14a39b4e6d8f6de4a&v=4 url: https://github.com/leylaeminova UN-9BOT: login: UN-9BOT @@ -1678,11 +1703,6 @@ flasonme: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/30571019?v=4 url: https://github.com/flasonme -ptt3199: - login: ptt3199 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=ccf51f8820787e17983954f26b06acf226cba293&v=4 - url: https://github.com/ptt3199 gustavoprezoto: login: gustavoprezoto count: 2 @@ -1733,3 +1753,13 @@ J-Fuji: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/101452903?v=4 url: https://github.com/J-Fuji +MrL8199: + login: MrL8199 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/39489075?u=3fc4f89c86973e40b5970d838c801bdbc13ac828&v=4 + url: https://github.com/MrL8199 +ivintoiu: + login: ivintoiu + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 + url: https://github.com/ivintoiu diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 9874afa56..f79bb300a 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -33,6 +33,11 @@ waynerv: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv +valentinDruzhinin: + login: valentinDruzhinin + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin AlertRED: login: AlertRED count: 16 @@ -53,16 +58,16 @@ codingjenny: count: 14 avatarUrl: https://avatars.githubusercontent.com/u/103817302?u=3a042740dc0ff58615da0d8679230966fd7693e8&v=4 url: https://github.com/codingjenny -valentinDruzhinin: - login: valentinDruzhinin - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin Xewus: login: Xewus count: 13 avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 url: https://github.com/Xewus +Zhongheng-Cheng: + login: Zhongheng-Cheng + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 + url: https://github.com/Zhongheng-Cheng Smlep: login: Smlep count: 11 @@ -83,11 +88,6 @@ Vincy1230: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4 url: https://github.com/Vincy1230 -Zhongheng-Cheng: - login: Zhongheng-Cheng - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 - url: https://github.com/Zhongheng-Cheng rjNemo: login: rjNemo count: 8 @@ -103,6 +103,11 @@ pablocm83: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 url: https://github.com/pablocm83 +ptt3199: + login: ptt3199 + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=2c3d947a80283e32bf616d4c3af139a6be69680f&v=4 + url: https://github.com/ptt3199 batlopes: login: batlopes count: 6 @@ -118,11 +123,6 @@ Alexandrhub: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4 url: https://github.com/Alexandrhub -ptt3199: - login: ptt3199 - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=ccf51f8820787e17983954f26b06acf226cba293&v=4 - url: https://github.com/ptt3199 Serrones: login: Serrones count: 5 @@ -203,6 +203,11 @@ kwang1215: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/74170199?u=2a63ff6692119dde3f5e5693365b9fcd6f977b08&v=4 url: https://github.com/kwang1215 +k94-ishi: + login: k94-ishi + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 + url: https://github.com/k94-ishi jfunez: login: jfunez count: 3 @@ -271,12 +276,12 @@ mojtabapaso: hsuanchi: login: hsuanchi count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=0b094ae292292fee093818e37ceb645c114d2bff&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=7d25a398e478b6e63503bf6f26c54efa9e0da07b&v=4 url: https://github.com/hsuanchi alejsdev: login: alejsdev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=843355286cea366cbb3a4fc3a14343bd4eceef55&v=4 url: https://github.com/alejsdev riroan: login: riroan @@ -333,11 +338,6 @@ gerry-sabar: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 url: https://github.com/gerry-sabar -k94-ishi: - login: k94-ishi - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 - url: https://github.com/k94-ishi Rishat-F: login: Rishat-F count: 3 @@ -513,3 +513,8 @@ timothy-jeong: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4 url: https://github.com/11kkw +yes0ng: + login: yes0ng + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/25501794?u=3aed18b0d491e0220a167a1e9e58bea3638c6707&v=4 + url: https://github.com/yes0ng From 1abef20dbddde878ef6844f219ab6e1d84444248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 2 Apr 2025 21:47:46 +0200 Subject: [PATCH 053/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Sponsors=20(#13559)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 109 +++++++++++++++---------------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 805d72b73..de6d44f96 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -9,11 +9,8 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 url: https://github.com/Nixtla - login: andrew-propelauth - avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=1188c27cb744bbec36447a2cfd4453126b2ddb5c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4 url: https://github.com/andrew-propelauth - - login: liblaber - avatarUrl: https://avatars.githubusercontent.com/u/100821118?v=4 - url: https://github.com/liblaber - login: zanfaruqui avatarUrl: https://avatars.githubusercontent.com/u/104461687?v=4 url: https://github.com/zanfaruqui @@ -71,7 +68,10 @@ sponsors: - login: acsone avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4 url: https://github.com/acsone -- - login: Trivie +- - login: ecosyste-ms + avatarUrl: https://avatars.githubusercontent.com/u/98474690?v=4 + url: https://github.com/ecosyste-ms + - login: Trivie avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 url: https://github.com/Trivie - - login: takashi-yoneya @@ -86,6 +86,9 @@ sponsors: - login: yasyf avatarUrl: https://avatars.githubusercontent.com/u/709645?u=f36736b3c6a85f578886ecc42a740e7b436e7a01&v=4 url: https://github.com/yasyf +- - login: alixlahuec + avatarUrl: https://avatars.githubusercontent.com/u/29543316?u=44357eb2a93bccf30fb9d389b8befe94a3d00985&v=4 + url: https://github.com/alixlahuec - - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io @@ -101,27 +104,27 @@ sponsors: - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - - login: vincentkoc - avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 - url: https://github.com/vincentkoc - - login: ddilidili - avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4 - url: https://github.com/ddilidili + - login: ProteinQure + avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 + url: https://github.com/ProteinQure - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky - login: ramonalmeidam avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 url: https://github.com/ramonalmeidam + - login: mjohnsey + avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 + url: https://github.com/mjohnsey + - login: ashi-agrawal + avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 + url: https://github.com/ashi-agrawal - login: sepsi77 avatarUrl: https://avatars.githubusercontent.com/u/18682303?v=4 url: https://github.com/sepsi77 - login: RaamEEIL avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 url: https://github.com/RaamEEIL - - login: jhundman - avatarUrl: https://avatars.githubusercontent.com/u/24263908?v=4 - url: https://github.com/jhundman - login: b-rad-c avatarUrl: https://avatars.githubusercontent.com/u/25362581?u=5bb10629f4015b62bec1f9a366675d5085551af9&v=4 url: https://github.com/b-rad-c @@ -137,15 +140,6 @@ sponsors: - login: Leay15 avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 url: https://github.com/Leay15 - - login: BoYanZh - avatarUrl: https://avatars.githubusercontent.com/u/32470225?u=55b174d080382822759d74307f8a0355fa86e808&v=4 - url: https://github.com/BoYanZh - - login: ygorpontelo - avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4 - url: https://github.com/ygorpontelo - - login: ProteinQure - avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 - url: https://github.com/ProteinQure - login: chickenandstats avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4 url: https://github.com/chickenandstats @@ -212,12 +206,9 @@ sponsors: - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 url: https://github.com/gorhack - - login: Ryandaydev - avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=48f68868db8886fce31a1d802c1003914c6cd7c6&v=4 - url: https://github.com/Ryandaydev - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog + - login: vincentkoc + avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 + url: https://github.com/vincentkoc - login: jstanden avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 url: https://github.com/jstanden @@ -272,12 +263,12 @@ sponsors: - login: khadrawy avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4 url: https://github.com/khadrawy - - login: mjohnsey - avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 - url: https://github.com/mjohnsey - - login: ashi-agrawal - avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 - url: https://github.com/ashi-agrawal + - login: Ryandaydev + avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 + url: https://github.com/Ryandaydev + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog - login: oliverxchen avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 url: https://github.com/oliverxchen @@ -299,6 +290,9 @@ sponsors: - login: hiancdtrsnm avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4 url: https://github.com/hiancdtrsnm +- - login: jpizquierdo + avatarUrl: https://avatars.githubusercontent.com/u/6716239?v=4 + url: https://github.com/jpizquierdo - - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy @@ -308,6 +302,9 @@ sponsors: - login: petercool avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=81c525232bb35780945a68e88afd96bb2cdad9c4&v=4 url: https://github.com/petercool + - login: diegopenilla + avatarUrl: https://avatars.githubusercontent.com/u/42318333?v=4 + url: https://github.com/diegopenilla - login: siavashyj avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4 url: https://github.com/siavashyj @@ -317,9 +314,9 @@ sponsors: - login: ArtyomVancyan avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4 url: https://github.com/ArtyomVancyan - - login: caviri - avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 - url: https://github.com/caviri + - login: joshuatz + avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 + url: https://github.com/joshuatz - login: SebTota avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 url: https://github.com/SebTota @@ -341,6 +338,9 @@ sponsors: - login: engineerjoe440 avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 url: https://github.com/engineerjoe440 + - login: caviri + avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 + url: https://github.com/caviri - login: hgalytoby avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 url: https://github.com/hgalytoby @@ -356,6 +356,9 @@ sponsors: - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ + - login: tochikuji + avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 + url: https://github.com/tochikuji - login: browniebroke avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 url: https://github.com/browniebroke @@ -386,9 +389,9 @@ sponsors: - login: ceb10n avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n - - login: tochikuji - avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 - url: https://github.com/tochikuji + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 - login: msehnout avatarUrl: https://avatars.githubusercontent.com/u/9369632?u=8c988f1b008a3f601385a3616f9327820f66e3a5&v=4 url: https://github.com/msehnout @@ -419,9 +422,6 @@ sponsors: - login: TheR1D avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4 url: https://github.com/TheR1D - - login: joshuatz - avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 - url: https://github.com/joshuatz - login: danielunderwood avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 url: https://github.com/danielunderwood @@ -449,9 +449,6 @@ sponsors: - login: hcristea avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=19092923a4ea5b338567961c8270b9206a6d81bb&v=4 url: https://github.com/hcristea - - login: moonape1226 - avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 - url: https://github.com/moonape1226 - - login: larsyngvelundin avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 url: https://github.com/larsyngvelundin @@ -461,9 +458,9 @@ sponsors: - login: rwxd avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 url: https://github.com/rwxd - - login: morzan1001 - avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 - url: https://github.com/morzan1001 + - login: kenkanayama + avatarUrl: https://avatars.githubusercontent.com/u/44771224?u=f68870c20c0f069491411aea8693c4714b40ecf0&v=4 + url: https://github.com/kenkanayama - login: sadikkuzu avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 url: https://github.com/sadikkuzu @@ -473,12 +470,12 @@ sponsors: - login: FabulousCodingFox avatarUrl: https://avatars.githubusercontent.com/u/78906517?u=924a27cbee3db7e0ece5cc1509921402e1445e74&v=4 url: https://github.com/FabulousCodingFox - - login: anqorithm - avatarUrl: https://avatars.githubusercontent.com/u/61029571?u=468256fa4e2d9ce2870b608299724bebb7a33f18&v=4 - url: https://github.com/anqorithm - - login: Materacl - avatarUrl: https://avatars.githubusercontent.com/u/70155818?u=ae11d084518856127cca483816a91a187e3124ee&v=4 - url: https://github.com/Materacl + - login: morzan1001 + avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 + url: https://github.com/morzan1001 + - login: BrianCurliss + avatarUrl: https://avatars.githubusercontent.com/u/1222949?v=4 + url: https://github.com/BrianCurliss - login: Toothwitch avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 url: https://github.com/Toothwitch From f0576e8ffdc6b6b1b6fdd82b7802797d660deb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 2 Apr 2025 21:47:54 +0200 Subject: [PATCH 054/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#13565)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/topic_repos.yml | 384 +++++++++++++++++------------------ 1 file changed, 192 insertions(+), 192 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 633b0aee3..7452088db 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,251 +1,251 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 30645 + stars: 31581 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 28690 + stars: 29256 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21356 + stars: 21487 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 15312 + stars: 15521 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 14957 + stars: 15353 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 11192 + stars: 11719 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 10501 + stars: 11129 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 9193 + stars: 9387 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8721 + stars: 8787 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 6433 + stars: 6596 owner_login: nonebot owner_html_url: https://github.com/nonebot -- name: serge - html_url: https://github.com/serge-chat/serge - stars: 5699 - owner_login: serge-chat - owner_html_url: https://github.com/serge-chat - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 5534 + stars: 6302 owner_login: vastsa owner_html_url: https://github.com/vastsa +- name: serge + html_url: https://github.com/serge-chat/serge + stars: 5707 + owner_login: serge-chat + owner_html_url: https://github.com/serge-chat - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 4921 + stars: 5045 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: polar html_url: https://github.com/polarsource/polar - stars: 4598 + stars: 4870 owner_login: polarsource owner_html_url: https://github.com/polarsource - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 4585 + stars: 4658 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4318 + stars: 4310 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4180 + stars: 4217 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4114 + stars: 4111 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 3904 + stars: 3936 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: poem html_url: https://github.com/poem-web/poem - stars: 3781 + stars: 3882 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3190 + stars: 3248 owner_login: rashadphz owner_html_url: https://github.com/rashadphz -- name: opyrator - html_url: https://github.com/ml-tooling/opyrator - stars: 3119 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3086 + stars: 3130 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin -- name: docarray - html_url: https://github.com/docarray/docarray - stars: 3021 - owner_login: docarray - owner_html_url: https://github.com/docarray +- name: opyrator + html_url: https://github.com/ml-tooling/opyrator + stars: 3116 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 2988 + stars: 3054 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi +- name: docarray + html_url: https://github.com/docarray/docarray + stars: 3033 + owner_login: docarray + owner_html_url: https://github.com/docarray - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 2863 + stars: 3019 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI -- name: fastapi-realworld-example-app - html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2850 - owner_login: nsidnev - owner_html_url: https://github.com/nsidnev - name: logfire html_url: https://github.com/pydantic/logfire - stars: 2757 + stars: 2909 owner_login: pydantic owner_html_url: https://github.com/pydantic -- name: uvicorn-gunicorn-fastapi-docker - html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker - stars: 2731 - owner_login: tiangolo - owner_html_url: https://github.com/tiangolo +- name: fastapi-realworld-example-app + html_url: https://github.com/nsidnev/fastapi-realworld-example-app + stars: 2863 + owner_login: nsidnev + owner_html_url: https://github.com/nsidnev - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 2700 + stars: 2861 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor +- name: uvicorn-gunicorn-fastapi-docker + html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker + stars: 2736 + owner_login: tiangolo + owner_html_url: https://github.com/tiangolo - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 2539 + stars: 2556 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2460 + stars: 2485 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2401 + stars: 2409 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2315 + stars: 2337 owner_login: Buuntu owner_html_url: https://github.com/Buuntu - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2266 + stars: 2271 owner_login: dot-agent owner_html_url: https://github.com/dot-agent -- name: 30-Days-of-Python - html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2163 - owner_login: codingforentrepreneurs - owner_html_url: https://github.com/codingforentrepreneurs - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2156 + stars: 2223 owner_login: s3rius owner_html_url: https://github.com/s3rius +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 2191 + owner_login: remsky + owner_html_url: https://github.com/remsky +- name: 30-Days-of-Python + html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python + stars: 2172 + owner_login: codingforentrepreneurs + owner_html_url: https://github.com/codingforentrepreneurs - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2051 + stars: 2090 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2025 + stars: 2055 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2021 + stars: 2040 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: solara html_url: https://github.com/widgetti/solara - stars: 1980 + stars: 2005 owner_login: widgetti owner_html_url: https://github.com/widgetti - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 1874 + stars: 1936 owner_login: supabase owner_html_url: https://github.com/supabase -- name: python-week-2022 - html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1829 - owner_login: rochacbruno - owner_html_url: https://github.com/rochacbruno - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1820 + stars: 1852 owner_login: Kludex owner_html_url: https://github.com/Kludex -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 1771 - owner_login: remsky - owner_html_url: https://github.com/remsky +- name: python-week-2022 + html_url: https://github.com/rochacbruno/python-week-2022 + stars: 1828 + owner_login: rochacbruno + owner_html_url: https://github.com/rochacbruno - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1719 + stars: 1730 owner_login: ycd owner_html_url: https://github.com/ycd - name: ormar html_url: https://github.com/collerek/ormar - stars: 1710 + stars: 1722 owner_login: collerek owner_html_url: https://github.com/collerek - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1658 + stars: 1715 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1618 + stars: 1625 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: termpair html_url: https://github.com/cs01/termpair - stars: 1611 + stars: 1610 owner_login: cs01 owner_html_url: https://github.com/cs01 - name: coronavirus-tracker-api @@ -255,241 +255,241 @@ owner_html_url: https://github.com/ExpDev07 - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1546 + stars: 1568 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1478 + stars: 1526 owner_login: long2ice owner_html_url: https://github.com/long2ice - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1467 + stars: 1504 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1462 + stars: 1476 owner_login: awtkns owner_html_url: https://github.com/awtkns - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1418 + stars: 1433 owner_login: Kludex owner_html_url: https://github.com/Kludex -- name: awesome-python-resources - html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1383 - owner_login: DjangoEx - owner_html_url: https://github.com/DjangoEx - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1363 + stars: 1408 owner_login: laurentS owner_html_url: https://github.com/laurentS +- name: awesome-python-resources + html_url: https://github.com/DjangoEx/awesome-python-resources + stars: 1386 + owner_login: DjangoEx + owner_html_url: https://github.com/DjangoEx - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1344 + stars: 1343 owner_login: ebhy owner_html_url: https://github.com/ebhy - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1284 + stars: 1309 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1234 + stars: 1262 owner_login: teamhide owner_html_url: https://github.com/teamhide - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1181 + stars: 1203 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1164 + stars: 1195 owner_login: amisadmin owner_html_url: https://github.com/amisadmin +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 1169 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1132 + stars: 1157 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1130 + stars: 1143 owner_login: slackapi owner_html_url: https://github.com/slackapi - name: langchain-extract html_url: https://github.com/langchain-ai/langchain-extract - stars: 1110 + stars: 1122 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai -- name: odmantic - html_url: https://github.com/art049/odmantic - stars: 1104 - owner_login: art049 - owner_html_url: https://github.com/art049 - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1093 + stars: 1112 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov -- name: SurfSense - html_url: https://github.com/MODSetter/SurfSense - stars: 1081 - owner_login: MODSetter - owner_html_url: https://github.com/MODSetter -- name: fastapi-alembic-sqlmodel-async - html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1063 - owner_login: jonra1993 - owner_html_url: https://github.com/jonra1993 +- name: odmantic + html_url: https://github.com/art049/odmantic + stars: 1109 + owner_login: art049 + owner_html_url: https://github.com/art049 - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1059 + stars: 1091 owner_login: trallnag owner_html_url: https://github.com/trallnag -- name: bedrock-claude-chat - html_url: https://github.com/aws-samples/bedrock-claude-chat - stars: 1039 - owner_login: aws-samples - owner_html_url: https://github.com/aws-samples -- name: runhouse - html_url: https://github.com/run-house/runhouse - stars: 1005 - owner_login: run-house - owner_html_url: https://github.com/run-house - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 987 + stars: 1086 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao +- name: bedrock-claude-chat + html_url: https://github.com/aws-samples/bedrock-claude-chat + stars: 1075 + owner_login: aws-samples + owner_html_url: https://github.com/aws-samples +- name: fastapi-alembic-sqlmodel-async + html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async + stars: 1074 + owner_login: jonra1993 + owner_html_url: https://github.com/jonra1993 +- name: runhouse + html_url: https://github.com/run-house/runhouse + stars: 1016 + owner_login: run-house + owner_html_url: https://github.com/run-house +- name: restish + html_url: https://github.com/danielgtaylor/restish + stars: 1012 + owner_login: danielgtaylor + owner_html_url: https://github.com/danielgtaylor - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 986 + stars: 988 owner_login: ajndkr owner_html_url: https://github.com/ajndkr - name: autollm html_url: https://github.com/viddexa/autollm - stars: 986 + stars: 987 owner_login: viddexa owner_html_url: https://github.com/viddexa -- name: restish - html_url: https://github.com/danielgtaylor/restish - stars: 984 - owner_login: danielgtaylor - owner_html_url: https://github.com/danielgtaylor - name: fastcrud html_url: https://github.com/igorbenav/fastcrud - stars: 964 + stars: 985 owner_login: igorbenav owner_html_url: https://github.com/igorbenav - name: secure html_url: https://github.com/TypeError/secure - stars: 928 + stars: 930 owner_login: TypeError owner_html_url: https://github.com/TypeError - name: langcorn html_url: https://github.com/msoedov/langcorn - stars: 916 + stars: 924 owner_login: msoedov owner_html_url: https://github.com/msoedov +- name: fastapi_best_architecture + html_url: https://github.com/fastapi-practices/fastapi_best_architecture + stars: 921 + owner_login: fastapi-practices + owner_html_url: https://github.com/fastapi-practices - name: energy-forecasting html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 898 + stars: 903 owner_login: iusztinpaul owner_html_url: https://github.com/iusztinpaul - name: authx html_url: https://github.com/yezz123/authx - stars: 874 + stars: 900 owner_login: yezz123 owner_html_url: https://github.com/yezz123 -- name: titiler - html_url: https://github.com/developmentseed/titiler - stars: 841 - owner_login: developmentseed - owner_html_url: https://github.com/developmentseed - name: FastAPI-boilerplate html_url: https://github.com/igorbenav/FastAPI-boilerplate - stars: 820 + stars: 877 owner_login: igorbenav owner_html_url: https://github.com/igorbenav +- name: titiler + html_url: https://github.com/developmentseed/titiler + stars: 853 + owner_login: developmentseed + owner_html_url: https://github.com/developmentseed +- name: ludic + html_url: https://github.com/getludic/ludic + stars: 831 + owner_login: getludic + owner_html_url: https://github.com/getludic - name: marker-api html_url: https://github.com/adithya-s-k/marker-api - stars: 813 + stars: 829 owner_login: adithya-s-k owner_html_url: https://github.com/adithya-s-k -- name: fastapi_best_architecture - html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 802 - owner_login: fastapi-practices - owner_html_url: https://github.com/fastapi-practices +- name: fastapi-observability + html_url: https://github.com/blueswen/fastapi-observability + stars: 771 + owner_login: blueswen + owner_html_url: https://github.com/blueswen - name: fastapi-do-zero html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 745 + stars: 767 owner_login: dunossauro owner_html_url: https://github.com/dunossauro - name: fastapi-mail html_url: https://github.com/sabuhish/fastapi-mail - stars: 744 + stars: 759 owner_login: sabuhish owner_html_url: https://github.com/sabuhish -- name: fastapi-observability - html_url: https://github.com/blueswen/fastapi-observability - stars: 743 - owner_login: blueswen - owner_html_url: https://github.com/blueswen - name: lccn_predictor html_url: https://github.com/baoliay2008/lccn_predictor - stars: 741 + stars: 749 owner_login: baoliay2008 owner_html_url: https://github.com/baoliay2008 -- name: annotated-py-projects - html_url: https://github.com/hhstore/annotated-py-projects - stars: 727 - owner_login: hhstore - owner_html_url: https://github.com/hhstore -- name: learn-generative-ai - html_url: https://github.com/panaverse/learn-generative-ai - stars: 714 - owner_login: panaverse - owner_html_url: https://github.com/panaverse +- name: flock + html_url: https://github.com/Onelevenvy/flock + stars: 746 + owner_login: Onelevenvy + owner_html_url: https://github.com/Onelevenvy - name: starlette-admin html_url: https://github.com/jowilf/starlette-admin - stars: 713 + stars: 737 owner_login: jowilf owner_html_url: https://github.com/jowilf +- name: annotated-py-projects + html_url: https://github.com/hhstore/annotated-py-projects + stars: 729 + owner_login: hhstore + owner_html_url: https://github.com/hhstore +- name: KonomiTV + html_url: https://github.com/tsukumijima/KonomiTV + stars: 727 + owner_login: tsukumijima + owner_html_url: https://github.com/tsukumijima +- name: learn-generative-ai + html_url: https://github.com/panaverse/learn-generative-ai + stars: 725 + owner_login: panaverse + owner_html_url: https://github.com/panaverse +- name: FastAPI-Backend-Template + html_url: https://github.com/Aeternalis-Ingenium/FastAPI-Backend-Template + stars: 719 + owner_login: Aeternalis-Ingenium + owner_html_url: https://github.com/Aeternalis-Ingenium - name: chatGPT-web html_url: https://github.com/mic1on/chatGPT-web stars: 712 owner_login: mic1on owner_html_url: https://github.com/mic1on -- name: FastAPI-Backend-Template - html_url: https://github.com/Aeternalis-Ingenium/FastAPI-Backend-Template - stars: 709 - owner_login: Aeternalis-Ingenium - owner_html_url: https://github.com/Aeternalis-Ingenium - name: linbing html_url: https://github.com/taomujian/linbing stars: 698 owner_login: taomujian owner_html_url: https://github.com/taomujian -- name: KonomiTV - html_url: https://github.com/tsukumijima/KonomiTV - stars: 687 - owner_login: tsukumijima - owner_html_url: https://github.com/tsukumijima -- name: fastapi-jwt-auth - html_url: https://github.com/IndominusByte/fastapi-jwt-auth - stars: 685 - owner_login: IndominusByte - owner_html_url: https://github.com/IndominusByte -- name: pity - html_url: https://github.com/wuranxu/pity - stars: 667 - owner_login: wuranxu - owner_html_url: https://github.com/wuranxu From f4583c58b9896135fc10395880d9aadbb10422c1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Apr 2025 19:48:02 +0000 Subject: [PATCH 055/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 546e1d717..96afc63ea 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#13558](https://github.com/fastapi/fastapi/pull/13558) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump dirty-equals from 0.8.0 to 0.9.0. PR [#13561](https://github.com/fastapi/fastapi/pull/13561) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Clean up `docs/en/mkdocs.yml` configuration file. PR [#13542](https://github.com/fastapi/fastapi/pull/13542) by [@svlandeg](https://github.com/svlandeg). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12986](https://github.com/fastapi/fastapi/pull/12986) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 8bf01245b17fac4d93f0022b1ccfb907520e5f1e Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Apr 2025 19:48:09 +0000 Subject: [PATCH 056/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 96afc63ea..e8ef0999a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Sponsors. PR [#13559](https://github.com/fastapi/fastapi/pull/13559) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13558](https://github.com/fastapi/fastapi/pull/13558) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump dirty-equals from 0.8.0 to 0.9.0. PR [#13561](https://github.com/fastapi/fastapi/pull/13561) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Clean up `docs/en/mkdocs.yml` configuration file. PR [#13542](https://github.com/fastapi/fastapi/pull/13542) by [@svlandeg](https://github.com/svlandeg). From 8032e21418bfa9addfd2e3c14c5b2b7ed6677455 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Apr 2025 19:48:32 +0000 Subject: [PATCH 057/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e8ef0999a..9ebed0a24 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#13565](https://github.com/fastapi/fastapi/pull/13565) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13559](https://github.com/fastapi/fastapi/pull/13559) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13558](https://github.com/fastapi/fastapi/pull/13558) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump dirty-equals from 0.8.0 to 0.9.0. PR [#13561](https://github.com/fastapi/fastapi/pull/13561) by [@dependabot[bot]](https://github.com/apps/dependabot). From 7b7ec90308d21fd61fd55f0588f2e7a714822052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 3 Apr 2025 21:48:09 +0200 Subject: [PATCH 058/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#13568)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/people.yml | 390 ++++++++++++++++++++-------------------- 1 file changed, 191 insertions(+), 199 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 4afce19b5..02a91ed19 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -13,7 +13,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 url: https://github.com/apps/github-actions - login: Kludex - count: 654 + count: 655 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: jgould22 @@ -76,6 +76,10 @@ experts: count: 59 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben +- login: luzzodev + count: 54 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: acidjunk count: 50 avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 @@ -88,10 +92,6 @@ experts: count: 49 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen -- login: luzzodev - count: 48 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev - login: adriangb count: 46 avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 @@ -104,14 +104,14 @@ experts: count: 45 avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 url: https://github.com/Dustyposa -- login: frankie567 - count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4 - url: https://github.com/frankie567 - login: odiseo0 count: 43 avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 url: https://github.com/odiseo0 +- login: frankie567 + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4 + url: https://github.com/frankie567 - login: sinisaos count: 40 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 @@ -156,6 +156,10 @@ experts: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 url: https://github.com/SirTelemak +- login: alv2017 + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: nymous count: 22 avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 @@ -216,10 +220,6 @@ experts: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=e19427d8dc296d6950e9c424adacc92d37496fe9&v=4 url: https://github.com/nkhitrov -- login: alv2017 - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 - login: jonatasoli count: 16 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 @@ -245,71 +245,79 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/33907262?u=2721fb37014d50daf473267c808aa678ecaefe09&v=4 url: https://github.com/simondale00 last_month_experts: -- login: jgould22 - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 - login: alv2017 - count: 10 + count: 12 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 - login: luzzodev - count: 8 + count: 9 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev -- login: YuriiMotov - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov -- login: Kludex - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex +- login: yauhen-sobaleu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 + url: https://github.com/yauhen-sobaleu - login: JavierSanchezCastro - count: 4 + count: 3 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: tiangolo - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo +- login: marsboy02 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 + url: https://github.com/marsboy02 - login: Ale-Cas count: 2 avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 url: https://github.com/Ale-Cas -- login: vtgn +- login: EverStarck count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 - url: https://github.com/vtgn -three_months_experts: + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: jgould22 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 +- login: Kludex + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: YuriiMotov - count: 31 + count: 2 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov +three_months_experts: - login: Kludex count: 25 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex +- login: YuriiMotov + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov - login: luzzodev - count: 19 + count: 22 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: alv2017 - count: 16 + count: 22 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 - login: jgould22 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: sehraramiz - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz +- login: yauhen-sobaleu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 + url: https://github.com/yauhen-sobaleu - login: JavierSanchezCastro count: 8 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: sehraramiz + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz - login: tiangolo count: 4 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 @@ -318,26 +326,10 @@ three_months_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste -- login: viniciusCalcantara - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 - url: https://github.com/viniciusCalcantara - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe -- login: Ale-Cas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: vtgn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 - url: https://github.com/vtgn -- login: Trinkes - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 - url: https://github.com/Trinkes - login: PREPONDERANCE count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 @@ -346,6 +338,26 @@ three_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 url: https://github.com/nbx3 +- login: marsboy02 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 + url: https://github.com/marsboy02 +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: EverStarck + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: vtgn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 + url: https://github.com/vtgn +- login: Trinkes + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 + url: https://github.com/Trinkes - login: XiaoXinYo count: 2 avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 @@ -356,45 +368,49 @@ three_months_experts: url: https://github.com/iloveitaly six_months_experts: - login: YuriiMotov - count: 63 + count: 61 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 48 + count: 54 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: Kludex - count: 48 + count: 40 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex -- login: sinisaos - count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos +- login: alv2017 + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: jgould22 count: 17 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: JavierSanchezCastro - count: 17 + count: 13 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: alv2017 - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: Kfir-G - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 - url: https://github.com/Kfir-G +- login: sinisaos + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos - login: sehraramiz count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz -- login: ceb10n +- login: Kfir-G + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 + url: https://github.com/Kfir-G +- login: yauhen-sobaleu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 + url: https://github.com/yauhen-sobaleu +- login: yvallois count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n + avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 + url: https://github.com/yvallois - login: estebanx64 count: 7 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 @@ -403,18 +419,10 @@ six_months_experts: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: yvallois - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois - login: yokwejuste count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste -- login: n8sty - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 @@ -431,26 +439,6 @@ six_months_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 url: https://github.com/dbfreem -- login: Isuxiz - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 - url: https://github.com/Isuxiz -- login: Minibrams - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 - url: https://github.com/Minibrams -- login: Ale-Cas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: vtgn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 - url: https://github.com/vtgn -- login: Trinkes - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 - url: https://github.com/Trinkes - login: PREPONDERANCE count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 @@ -459,6 +447,30 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 url: https://github.com/nbx3 +- login: marsboy02 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 + url: https://github.com/marsboy02 +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: EverStarck + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: n8sty + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty +- login: vtgn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 + url: https://github.com/vtgn +- login: Trinkes + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 + url: https://github.com/Trinkes - login: XiaoXinYo count: 2 avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 @@ -479,10 +491,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 url: https://github.com/gelezo43 -- login: christiansicari - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/29756552?v=4 - url: https://github.com/christiansicari - login: 1001pepi count: 2 avatarUrl: https://avatars.githubusercontent.com/u/82064861?u=8c6ffdf2275d6970a07294752c545cd2702c57d3&v=4 @@ -503,14 +511,10 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 url: https://github.com/iiotsrc -- login: simondale00 +- login: Isuxiz count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/33907262?u=2721fb37014d50daf473267c808aa678ecaefe09&v=4 - url: https://github.com/simondale00 -- login: jd-solanki - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/47495003?u=6e225cb42c688d0cd70e65c6baedb9f5922b1178&v=4 - url: https://github.com/jd-solanki + avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 + url: https://github.com/Isuxiz - login: Reemyos count: 2 avatarUrl: https://avatars.githubusercontent.com/u/44867003?v=4 @@ -519,33 +523,21 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 url: https://github.com/deight93 -- login: PhysicallyActive - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 - url: https://github.com/PhysicallyActive - login: Jkrox count: 2 avatarUrl: https://avatars.githubusercontent.com/u/83181939?u=d6a922d97129f7f3916d6a1c166bc011b3a72b7f&v=4 url: https://github.com/Jkrox -- login: jfeaver - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1091338?u=0bcba366447d8fadad63f6705a52d128da4c7ec2&v=4 - url: https://github.com/jfeaver -- login: tristan - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1412?u=aab8aaa4cc0f1210ac45fc93873a5909d314c965&v=4 - url: https://github.com/tristan one_year_experts: - login: YuriiMotov - count: 214 + count: 196 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov - login: Kludex - count: 66 + count: 65 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: luzzodev - count: 48 + count: 54 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: sinisaos @@ -553,11 +545,11 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos - login: JavierSanchezCastro - count: 39 + count: 37 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: jgould22 - count: 35 + count: 32 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: tiangolo @@ -565,7 +557,7 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: alv2017 - count: 16 + count: 22 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 - login: n8sty @@ -584,38 +576,38 @@ one_year_experts: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz -- login: PhysicallyActive - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 - url: https://github.com/PhysicallyActive - login: Kfir-G count: 13 avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 url: https://github.com/Kfir-G +- login: PhysicallyActive + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 + url: https://github.com/PhysicallyActive - login: mattmess1221 count: 11 avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 url: https://github.com/mattmess1221 -- login: hasansezertasan +- login: yauhen-sobaleu count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 - url: https://github.com/hasansezertasan + avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 + url: https://github.com/yauhen-sobaleu - login: AIdjis count: 8 avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 url: https://github.com/AIdjis - login: yvallois - count: 6 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 url: https://github.com/yvallois +- login: hasansezertasan + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 + url: https://github.com/hasansezertasan - login: PREPONDERANCE count: 5 avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 url: https://github.com/PREPONDERANCE -- login: pythonweb2 - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 - login: gustavosett count: 5 avatarUrl: https://avatars.githubusercontent.com/u/99373133?u=1382fe27034a0179f07cf989f63c4f23017f043c&v=4 @@ -624,6 +616,10 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/32629225?u=3b7c30e8a09426a1b9284f6e8a0ae53a525596bf&v=4 url: https://github.com/chyok +- login: acidjunk + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk - login: svlandeg count: 4 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 @@ -636,10 +632,6 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste -- login: acidjunk - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk - login: bertomaniac count: 4 avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 @@ -648,6 +640,14 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/8213913?u=22b68b7a0d5bf5e09c02084c0f5f53d7503114cd&v=4 url: https://github.com/binbjz +- login: CharlesPerrotMinotHCHB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/112571330?u=a9628848d6096b491135727435a2a253152995a1&v=4 + url: https://github.com/CharlesPerrotMinotHCHB +- login: ryanisn + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/53449841?v=4 + url: https://github.com/ryanisn - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 @@ -656,6 +656,10 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe +- login: pythonweb2 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 + url: https://github.com/pythonweb2 - login: DeoLeung count: 3 avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 @@ -684,18 +688,46 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 url: https://github.com/Minibrams -- login: ryanisn - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/53449841?v=4 - url: https://github.com/ryanisn - login: alexandercronin count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8014288?u=69580504c51a0cdd756fc47b23bb7f404bd694e7&v=4 url: https://github.com/alexandercronin -- login: omarcruzpantoja - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/15116058?u=4b64c643fad49225d854e1aaecd1ffc6f9071a1b&v=4 - url: https://github.com/omarcruzpantoja +- login: nbx3 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 + url: https://github.com/nbx3 +- login: marsboy02 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 + url: https://github.com/marsboy02 +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: patrick91 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/667029?u=e35958a75ac1f99c81b4bc99e22db8cd665ae7f0&v=4 + url: https://github.com/patrick91 +- login: EverStarck + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: rustonaut + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7632017?u=652bb86c1399727082c929fd4666fd7fa65923b1&v=4 + url: https://github.com/rustonaut +- login: Trolldemorted + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10261186?v=4 + url: https://github.com/Trolldemorted +- login: anantgupta129 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66518357?u=6e25dcd84638f17d2c6df5dc26f07fd7c6dc118e&v=4 + url: https://github.com/anantgupta129 +- login: slafs + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 + url: https://github.com/slafs - login: Wyko count: 2 avatarUrl: https://avatars.githubusercontent.com/u/467094?v=4 @@ -704,14 +736,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 url: https://github.com/ddahan -- login: Ale-Cas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: Trolldemorted - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/10261186?v=4 - url: https://github.com/Trolldemorted - login: vtgn count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 @@ -720,10 +744,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/72403396?v=4 url: https://github.com/SDAravind -- login: slafs - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs - login: redb0 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/30475117?v=4 @@ -748,31 +768,3 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 url: https://github.com/Trinkes -- login: anantgupta129 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/66518357?u=6e25dcd84638f17d2c6df5dc26f07fd7c6dc118e&v=4 - url: https://github.com/anantgupta129 -- login: nbx3 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: yanggeorge - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 - url: https://github.com/yanggeorge -- login: XiaoXinYo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/XiaoXinYo -- login: monchin - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18521800?v=4 - url: https://github.com/monchin -- login: AmirHmZz - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/38752106?u=07f80e451bda00a9492bbc764e49d24ad3ada8cc&v=4 - url: https://github.com/AmirHmZz -- login: iloveitaly - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly From 76b324d95bc033740217ba913ae2bbaf95ec1d78 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 3 Apr 2025 19:48:31 +0000 Subject: [PATCH 059/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9ebed0a24..04ea50593 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#13568](https://github.com/fastapi/fastapi/pull/13568) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#13565](https://github.com/fastapi/fastapi/pull/13565) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13559](https://github.com/fastapi/fastapi/pull/13559) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13558](https://github.com/fastapi/fastapi/pull/13558) by [@tiangolo](https://github.com/tiangolo). From 5f9c7a31852315b3f8f3287424cde16842c515e3 Mon Sep 17 00:00:00 2001 From: Elliot Ford Date: Sun, 6 Apr 2025 17:33:24 +0100 Subject: [PATCH 060/455] =?UTF-8?q?=F0=9F=93=9D=20Fix=20liblab=20client=20?= =?UTF-8?q?generation=20doc=20link=20(#13571)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/generate-clients.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 3b9dc83f0..b2aef5037 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -24,7 +24,7 @@ For example, you might want to try: * Speakeasy * Stainless -* liblab +* liblab There are also several other companies offering similar services that you can search and find online. 🤓 From bd3e47ec592b3fe3b01ab2087d790bccd07cb5ed Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 6 Apr 2025 16:33:45 +0000 Subject: [PATCH 061/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 04ea50593..339b33581 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Fix liblab client generation doc link. PR [#13571](https://github.com/fastapi/fastapi/pull/13571) by [@EFord36](https://github.com/EFord36). * ✏️ Fix talk information typo. PR [#13544](https://github.com/fastapi/fastapi/pull/13544) by [@blueswen](https://github.com/blueswen). * 📝 Add External Link: Taiwanese talk on FastAPI with observability . PR [#13527](https://github.com/fastapi/fastapi/pull/13527) by [@blueswen](https://github.com/blueswen). From d1962bb22ff3c3b55bd7d09dd82ef62b72e3217d Mon Sep 17 00:00:00 2001 From: Hotah Ma Date: Fri, 11 Apr 2025 23:58:47 +0800 Subject: [PATCH 062/455] =?UTF-8?q?=F0=9F=93=9D=20Fix=20typo=20in=20docume?= =?UTF-8?q?ntation=20(#13599)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/deployment/concepts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/deployment/concepts.md b/docs/en/docs/deployment/concepts.md index e71a7487a..ed13bc28d 100644 --- a/docs/en/docs/deployment/concepts.md +++ b/docs/en/docs/deployment/concepts.md @@ -65,7 +65,7 @@ The word **program** is commonly used to describe many things: * The **code** that you write, the **Python files**. * The **file** that can be **executed** by the operating system, for example: `python`, `python.exe` or `uvicorn`. -* A particular program while it is **running** on the operating system, using the CPU, and storing things on memory. This is also called a **process**. +* A particular program while it is **running** on the operating system, using the CPU, and storing things in memory. This is also called a **process**. ### What is a Process From a8c1333b4dedcdffd1b146bd047f5deaee6cf689 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 11 Apr 2025 15:59:09 +0000 Subject: [PATCH 063/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 339b33581..797619354 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Fix typo in documentation. PR [#13599](https://github.com/fastapi/fastapi/pull/13599) by [@Taoup](https://github.com/Taoup). * 📝 Fix liblab client generation doc link. PR [#13571](https://github.com/fastapi/fastapi/pull/13571) by [@EFord36](https://github.com/EFord36). * ✏️ Fix talk information typo. PR [#13544](https://github.com/fastapi/fastapi/pull/13544) by [@blueswen](https://github.com/blueswen). * 📝 Add External Link: Taiwanese talk on FastAPI with observability . PR [#13527](https://github.com/fastapi/fastapi/pull/13527) by [@blueswen](https://github.com/blueswen). From 024d5d33183e54fa1133bda2bb23f479a63cda96 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 11 Apr 2025 18:02:43 +0200 Subject: [PATCH 064/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13594)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.2 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6aa7c458d..41ca9aa99 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.2 + rev: v0.11.4 hooks: - id: ruff args: From 4ec5e0a90a15490bd8d5b47850a83ed2dbe7d5f3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 11 Apr 2025 16:03:08 +0000 Subject: [PATCH 065/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 797619354..3819e8857 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13594](https://github.com/fastapi/fastapi/pull/13594) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Experts. PR [#13568](https://github.com/fastapi/fastapi/pull/13568) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#13565](https://github.com/fastapi/fastapi/pull/13565) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13559](https://github.com/fastapi/fastapi/pull/13559) by [@tiangolo](https://github.com/tiangolo). From 9d937964ba250fd1231f188cafa189195881656c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 10:03:45 +0200 Subject: [PATCH 066/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13619)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.4 → v0.11.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.4...v0.11.5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 41ca9aa99..58b0080a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.4 + rev: v0.11.5 hooks: - id: ruff args: From 7c75b555804388e885d991497942be777fa8af3a Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 15 Apr 2025 08:04:06 +0000 Subject: [PATCH 067/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3819e8857..fd43585c2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13594](https://github.com/fastapi/fastapi/pull/13594) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Experts. PR [#13568](https://github.com/fastapi/fastapi/pull/13568) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#13565](https://github.com/fastapi/fastapi/pull/13565) by [@tiangolo](https://github.com/tiangolo). From 1d21c7f74833e68a2a75c9ef43b09103f54210ea Mon Sep 17 00:00:00 2001 From: Gaurav Sheni Date: Mon, 21 Apr 2025 09:30:38 -0400 Subject: [PATCH 068/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20syntax=20err?= =?UTF-8?q?or=20in=20`docs/en/docs/tutorial/handling-errors.md`=20(#13623)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/handling-errors.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/tutorial/handling-errors.md b/docs/en/docs/tutorial/handling-errors.md index 4d969747f..5b8e677e4 100644 --- a/docs/en/docs/tutorial/handling-errors.md +++ b/docs/en/docs/tutorial/handling-errors.md @@ -35,7 +35,7 @@ Because it's a Python exception, you don't `return` it, you `raise` it. This also means that if you are inside a utility function that you are calling inside of your *path operation function*, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the *path operation function*, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client. -The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security. +The benefit of raising an exception over returning a value will be more evident in the section about Dependencies and Security. In this example, when the client requests an item by an ID that doesn't exist, raise an exception with a status code of `404`: @@ -252,4 +252,4 @@ If you want to use the exception along with the same default exception handlers {* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *} -In this example you are just `print`ing the error with a very expressive message, but you get the idea. You can use the exception and then just reuse the default exception handlers. +In this example you are just printing the error with a very expressive message, but you get the idea. You can use the exception and then just reuse the default exception handlers. From 601d678e0757c13187051eaa1f037e76951a2e86 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 21 Apr 2025 13:30:58 +0000 Subject: [PATCH 069/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fd43585c2..10255fe0f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ✏️ Fix syntax error in `docs/en/docs/tutorial/handling-errors.md`. PR [#13623](https://github.com/fastapi/fastapi/pull/13623) by [@gsheni](https://github.com/gsheni). * 📝 Fix typo in documentation. PR [#13599](https://github.com/fastapi/fastapi/pull/13599) by [@Taoup](https://github.com/Taoup). * 📝 Fix liblab client generation doc link. PR [#13571](https://github.com/fastapi/fastapi/pull/13571) by [@EFord36](https://github.com/EFord36). * ✏️ Fix talk information typo. PR [#13544](https://github.com/fastapi/fastapi/pull/13544) by [@blueswen](https://github.com/blueswen). From 9c03b8fd64d52aec575069094244456c92728128 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 20:09:18 +0200 Subject: [PATCH 070/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13634)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.5 → v0.11.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.5...v0.11.6) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 58b0080a5..51ca24ba5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.5 + rev: v0.11.6 hooks: - id: ruff args: From fe0c643e90543455ed62ce5ecdef1cce939db6b0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 21 Apr 2025 18:09:43 +0000 Subject: [PATCH 071/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 10255fe0f..688c6f434 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -25,6 +25,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13594](https://github.com/fastapi/fastapi/pull/13594) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Experts. PR [#13568](https://github.com/fastapi/fastapi/pull/13568) by [@tiangolo](https://github.com/tiangolo). From c2fb5cc109ebb06ff56cb1a8732c8d9bff3111ac Mon Sep 17 00:00:00 2001 From: OA Date: Sat, 26 Apr 2025 18:00:32 +0200 Subject: [PATCH 072/455] =?UTF-8?q?=F0=9F=93=9D=20Remove=20unnecessary=20b?= =?UTF-8?q?ullet=20from=20docs=20(#13641)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/en/docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a1260b90..a7a069cce 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ $ pip install "fastapi[standard]" ### Create it -* Create a file `main.py` with: +Create a file `main.py` with: ```Python from typing import Union diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 4a2777f25..0f3623ed5 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -146,7 +146,7 @@ $ pip install "fastapi[standard]" ### Create it -* Create a file `main.py` with: +Create a file `main.py` with: ```Python from typing import Union From ba8d85fbe8787be7f4cb8ff619ab411be0d0674d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Apr 2025 18:00:46 +0200 Subject: [PATCH 073/455] =?UTF-8?q?=E2=AC=86=20Bump=20astral-sh/setup-uv?= =?UTF-8?q?=20from=205=20to=206=20(#13648)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5 to 6. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/v5...v6) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 4 ++-- .github/workflows/contributors.yml | 2 +- .github/workflows/deploy-docs.yml | 2 +- .github/workflows/label-approved.yml | 2 +- .github/workflows/notify-translations.yml | 2 +- .github/workflows/people.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- .github/workflows/sponsors.yml | 2 +- .github/workflows/test.yml | 6 +++--- .github/workflows/topic-repos.yml | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 6ecdf487c..e84e4e4ab 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -53,7 +53,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -95,7 +95,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 87abfe3a1..34b54b452 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -30,7 +30,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index aec327f48..9ca69b208 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -29,7 +29,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 02070146c..908a9453d 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -26,7 +26,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index c96992689..621d1253a 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -34,7 +34,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index 6ec3c1ad2..11931a05a 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -30,7 +30,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index a0ffd55e6..d8a5dfb30 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -26,7 +26,7 @@ jobs: with: python-version: '3.9' - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index a5230c834..6da4d90e1 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -30,7 +30,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e8092641..c3940be01 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -67,7 +67,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -112,7 +112,7 @@ jobs: with: python-version: '3.8' - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index 3c5c881f1..433aeb00b 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -25,7 +25,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true From 9fa8050e01b26f58f5789375e9eb5e96e3bd3cfc Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Apr 2025 16:00:54 +0000 Subject: [PATCH 074/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 688c6f434..16375c04a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc). * ✏️ Fix syntax error in `docs/en/docs/tutorial/handling-errors.md`. PR [#13623](https://github.com/fastapi/fastapi/pull/13623) by [@gsheni](https://github.com/gsheni). * 📝 Fix typo in documentation. PR [#13599](https://github.com/fastapi/fastapi/pull/13599) by [@Taoup](https://github.com/Taoup). * 📝 Fix liblab client generation doc link. PR [#13571](https://github.com/fastapi/fastapi/pull/13571) by [@EFord36](https://github.com/EFord36). From 79bc96647bf53b2e969233122e5ad3c9ed896a61 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Apr 2025 16:01:11 +0000 Subject: [PATCH 075/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 16375c04a..553546258 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -26,6 +26,7 @@ hide: ### Internal +* ⬆ Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13594](https://github.com/fastapi/fastapi/pull/13594) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From ea42ebda809a06108115dbed1c010ac7e5e7ef1d Mon Sep 17 00:00:00 2001 From: Frank Hoffmann Date: Mon, 28 Apr 2025 09:13:56 +0200 Subject: [PATCH 076/455] =?UTF-8?q?=E2=9C=85=20Use=20`inline-snapshot`=20t?= =?UTF-8?q?o=20support=20different=20Pydantic=20versions=20in=20the=20test?= =?UTF-8?q?=20suite=20(#12534)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: svlandeg Co-authored-by: Sofie Van Landeghem --- requirements-tests.txt | 2 +- .../test_tutorial002.py | 48 +++++++++++-------- .../test_sql_databases/test_tutorial002.py | 6 +-- tests/utils.py | 23 +++++++++ 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/requirements-tests.txt b/requirements-tests.txt index 013b9a35a..f722825dd 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -10,7 +10,7 @@ anyio[trio] >=3.2.1,<5.0.0 PyJWT==2.8.0 pyyaml >=5.3.1,<7.0.0 passlib[bcrypt] >=1.7.2,<2.0.0 -inline-snapshot==0.19.3 +inline-snapshot>=0.21.1 # types types-ujson ==5.10.0.20240515 types-orjson ==3.6.2 diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py index 30adadc8a..cef6f6630 100644 --- a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py @@ -5,7 +5,13 @@ from dirty_equals import IsDict from fastapi.testclient import TestClient from inline_snapshot import snapshot -from tests.utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2 +from tests.utils import ( + needs_py39, + needs_py310, + needs_pydanticv1, + needs_pydanticv2, + pydantic_snapshot, +) @pytest.fixture( @@ -59,8 +65,8 @@ def test_cookie_param_model_defaults(client: TestClient): def test_cookie_param_model_invalid(client: TestClient): response = client.get("/items/") assert response.status_code == 422 - assert response.json() == snapshot( - IsDict( + assert response.json() == pydantic_snapshot( + v2=snapshot( { "detail": [ { @@ -71,9 +77,8 @@ def test_cookie_param_model_invalid(client: TestClient): } ] } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 + ), + v1=snapshot( { "detail": [ { @@ -83,7 +88,7 @@ def test_cookie_param_model_invalid(client: TestClient): } ] } - ) + ), ) @@ -144,18 +149,23 @@ def test_openapi_schema(client: TestClient): "name": "fatebook_tracker", "in": "cookie", "required": False, - "schema": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Fatebook Tracker", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "type": "string", - "title": "Fatebook Tracker", - } + "schema": pydantic_snapshot( + v2=snapshot( + { + "anyOf": [ + {"type": "string"}, + {"type": "null"}, + ], + "title": "Fatebook Tracker", + } + ), + v1=snapshot( + # TODO: remove when deprecating Pydantic v1 + { + "type": "string", + "title": "Fatebook Tracker", + } + ), ), }, { diff --git a/tests/test_tutorial/test_sql_databases/test_tutorial002.py b/tests/test_tutorial/test_sql_databases/test_tutorial002.py index 79e48c1c3..8a98f9a2d 100644 --- a/tests/test_tutorial/test_sql_databases/test_tutorial002.py +++ b/tests/test_tutorial/test_sql_databases/test_tutorial002.py @@ -4,7 +4,7 @@ import warnings import pytest from dirty_equals import IsDict, IsInt from fastapi.testclient import TestClient -from inline_snapshot import snapshot +from inline_snapshot import Is, snapshot from sqlalchemy import StaticPool from sqlmodel import SQLModel, create_engine from sqlmodel.main import default_registry @@ -117,14 +117,14 @@ def test_crud_app(client: TestClient): ) assert response.status_code == 200, response.text assert response.json() == snapshot( - {"name": "Dog Pond", "age": None, "id": hero_id} + {"name": "Dog Pond", "age": None, "id": Is(hero_id)} ) # Get updated hero response = client.get(f"/heroes/{hero_id}") assert response.status_code == 200, response.text assert response.json() == snapshot( - {"name": "Dog Pond", "age": None, "id": hero_id} + {"name": "Dog Pond", "age": None, "id": Is(hero_id)} ) # Delete a hero diff --git a/tests/utils.py b/tests/utils.py index 460c028f7..ae9543e3b 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,6 +2,7 @@ import sys import pytest from fastapi._compat import PYDANTIC_V2 +from inline_snapshot import Snapshot needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+") needs_py310 = pytest.mark.skipif( @@ -9,3 +10,25 @@ needs_py310 = pytest.mark.skipif( ) needs_pydanticv2 = pytest.mark.skipif(not PYDANTIC_V2, reason="requires Pydantic v2") needs_pydanticv1 = pytest.mark.skipif(PYDANTIC_V2, reason="requires Pydantic v1") + + +def pydantic_snapshot( + *, + v2: Snapshot, + v1: Snapshot, # TODO: remove v1 argument when deprecating Pydantic v1 +): + """ + This function should be used like this: + + >>> assert value == pydantic_snapshot(v2=snapshot(),v1=snapshot()) + + inline-snapshot will create the snapshots when pytest is executed for each versions of pydantic. + + It is also possible to use the function inside snapshots for version-specific values. + + >>> assert value == snapshot({ + "data": "some data", + "version_specific": pydantic_snapshot(v2=snapshot(),v1=snapshot()), + }) + """ + return v2 if PYDANTIC_V2 else v1 From 419917297738c6ee2cb68ddf9f9cb2f5ec61df2c Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 28 Apr 2025 07:14:30 +0000 Subject: [PATCH 077/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 553546258..d606d2eef 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -26,6 +26,7 @@ hide: ### Internal +* ✅ Use `inline-snapshot` to support different Pydantic versions in the test suite. PR [#12534](https://github.com/fastapi/fastapi/pull/12534) by [@15r10nk](https://github.com/15r10nk). * ⬆ Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 8fa56b46a16859aaa6dd9d3eef140ef0682253f4 Mon Sep 17 00:00:00 2001 From: Joakim Nordling Date: Mon, 28 Apr 2025 21:31:44 +0300 Subject: [PATCH 078/455] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20ReDoc=20t?= =?UTF-8?q?o=20version=202.x=20(#9700)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: svlandeg Co-authored-by: Sebastián Ramírez Co-authored-by: Sofie Van Landeghem --- docs/de/docs/how-to/custom-docs-ui-assets.md | 12 +++--------- docs/en/docs/how-to/custom-docs-ui-assets.md | 12 +++--------- docs/es/docs/how-to/custom-docs-ui-assets.md | 12 +++--------- docs/pt/docs/how-to/custom-docs-ui-assets.md | 12 +++--------- docs_src/custom_docs_ui/tutorial001.py | 2 +- fastapi/openapi/docs.py | 2 +- tests/test_application.py | 2 +- .../test_custom_docs_ui/test_tutorial001.py | 2 +- 8 files changed, 16 insertions(+), 40 deletions(-) diff --git a/docs/de/docs/how-to/custom-docs-ui-assets.md b/docs/de/docs/how-to/custom-docs-ui-assets.md index ab8cd9f6b..f68902b99 100644 --- a/docs/de/docs/how-to/custom-docs-ui-assets.md +++ b/docs/de/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ Sie können wahrscheinlich mit der rechten Maustaste auf jeden Link klicken und Und **ReDoc** verwendet diese Datei: -* `redoc.standalone.js` +* `redoc.standalone.js` Danach könnte Ihre Dateistruktur wie folgt aussehen: @@ -129,14 +129,8 @@ Sie sollten eine sehr lange JavaScript-Datei für **ReDoc** sehen. Sie könnte beginnen mit etwas wie: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs/en/docs/how-to/custom-docs-ui-assets.md b/docs/en/docs/how-to/custom-docs-ui-assets.md index f717c98fa..9d2238e4f 100644 --- a/docs/en/docs/how-to/custom-docs-ui-assets.md +++ b/docs/en/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ You can probably right-click each link and select an option similar to `Save lin And **ReDoc** uses the file: -* `redoc.standalone.js` +* `redoc.standalone.js` After that, your file structure could look like: @@ -129,14 +129,8 @@ You should see a very long JavaScript file for **ReDoc**. It could start with something like: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs/es/docs/how-to/custom-docs-ui-assets.md b/docs/es/docs/how-to/custom-docs-ui-assets.md index 444cf167e..0a03ff330 100644 --- a/docs/es/docs/how-to/custom-docs-ui-assets.md +++ b/docs/es/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ Probablemente puedas hacer clic derecho en cada enlace y seleccionar una opción Y **ReDoc** utiliza el archivo: -* `redoc.standalone.js` +* `redoc.standalone.js` Después de eso, tu estructura de archivos podría verse así: @@ -129,14 +129,8 @@ Deberías ver un archivo JavaScript muy largo de **ReDoc**. Podría comenzar con algo como: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs/pt/docs/how-to/custom-docs-ui-assets.md b/docs/pt/docs/how-to/custom-docs-ui-assets.md index 3adc7529e..b7de6c8bd 100644 --- a/docs/pt/docs/how-to/custom-docs-ui-assets.md +++ b/docs/pt/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ Você provavelmente pode clicar com o botão direito em cada link e selecionar u E o **ReDoc** usa os arquivos: -* `redoc.standalone.js` +* `redoc.standalone.js` Depois disso, sua estrutura de arquivos deve se parecer com: @@ -129,14 +129,8 @@ Você deverá ver um arquivo JavaScript muito longo para o **ReDoc**. Esse arquivo pode começar com algo como: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs_src/custom_docs_ui/tutorial001.py b/docs_src/custom_docs_ui/tutorial001.py index f7ceb0c2f..1cfcce19a 100644 --- a/docs_src/custom_docs_ui/tutorial001.py +++ b/docs_src/custom_docs_ui/tutorial001.py @@ -29,7 +29,7 @@ async def redoc_html(): return get_redoc_html( openapi_url=app.openapi_url, title=app.title + " - ReDoc", - redoc_js_url="https://unpkg.com/redoc@next/bundles/redoc.standalone.js", + redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js", ) diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index c2ec358d2..f181b43c1 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -188,7 +188,7 @@ def get_redoc_html( It is normally set to a CDN URL. """ ), - ] = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js", + ] = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js", redoc_favicon_url: Annotated[ str, Doc( diff --git a/tests/test_application.py b/tests/test_application.py index 5c62f5f6e..a7d50ea72 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -43,7 +43,7 @@ def test_redoc(): response = client.get("/redoc") assert response.status_code == 200, response.text assert response.headers["content-type"] == "text/html; charset=utf-8" - assert "redoc@next" in response.text + assert "redoc@2" in response.text def test_enum_status_code_response(): diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py index aff070d74..cb8e8c224 100644 --- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py @@ -33,7 +33,7 @@ def test_swagger_ui_oauth2_redirect_html(client: TestClient): def test_redoc_html(client: TestClient): response = client.get("/redoc") assert response.status_code == 200, response.text - assert "https://unpkg.com/redoc@next/bundles/redoc.standalone.js" in response.text + assert "https://unpkg.com/redoc@2/bundles/redoc.standalone.js" in response.text def test_api(client: TestClient): From 4025751afb7e5403cbc944a49b2fdc8a02cee2bd Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 28 Apr 2025 18:32:06 +0000 Subject: [PATCH 079/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d606d2eef..31f35431f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Upgrades + +* ⬆️ Update ReDoc to version 2.x. PR [#9700](https://github.com/fastapi/fastapi/pull/9700) by [@joakimnordling](https://github.com/joakimnordling). + ### Docs * 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc). From 26dc148cb91f9ec679b7cf1a74f5a6d6747e7e00 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 20:37:31 +0200 Subject: [PATCH 080/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13656)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.6 → v0.11.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.6...v0.11.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 51ca24ba5..b1429a562 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.6 + rev: v0.11.7 hooks: - id: ruff args: From 699717cf7fa51f7f9555efec82cae040020c8cb1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 28 Apr 2025 18:37:55 +0000 Subject: [PATCH 081/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 31f35431f..08f8ecbbc 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13656](https://github.com/fastapi/fastapi/pull/13656) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ✅ Use `inline-snapshot` to support different Pydantic versions in the test suite. PR [#12534](https://github.com/fastapi/fastapi/pull/12534) by [@15r10nk](https://github.com/15r10nk). * ⬆ Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 9b5b2dd7a241bbfaaf85e16ae35a48b3257c4ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 1 May 2025 13:32:33 +0200 Subject: [PATCH 082/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#13662)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/contributors.yml | 32 +++-- docs/en/data/translation_reviewers.yml | 158 +++++++++++++------------ docs/en/data/translators.yml | 9 +- 3 files changed, 107 insertions(+), 92 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index 1910854af..7da07d8a1 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,18 +1,23 @@ tiangolo: login: tiangolo - count: 730 + count: 734 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 98 + count: 100 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: login: alejsdev count: 47 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=843355286cea366cbb3a4fc3a14343bd4eceef55&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 url: https://github.com/alejsdev +pre-commit-ci: + login: pre-commit-ci + count: 27 + avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 + url: https://github.com/apps/pre-commit-ci github-actions: login: github-actions count: 26 @@ -23,11 +28,6 @@ Kludex: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex -pre-commit-ci: - login: pre-commit-ci - count: 23 - avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 - url: https://github.com/apps/pre-commit-ci dmontagu: login: dmontagu count: 17 @@ -183,11 +183,11 @@ uriyyo: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=a27b65a9ec3420586a827a0facccbb8b6df1ffb3&v=4 url: https://github.com/uriyyo -amacfie: - login: amacfie +andrew222651: + login: andrew222651 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/889657?u=d70187989940b085bcbfa3bedad8dbc5f3ab1fe7&v=4 - url: https://github.com/amacfie + url: https://github.com/andrew222651 rkbeatss: login: rkbeatss count: 3 @@ -488,6 +488,11 @@ Lancetnik: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/44573917?u=f9a18be7324333daf9cc314c35c3051f0a20a7a6&v=4 url: https://github.com/Lancetnik +joakimnordling: + login: joakimnordling + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6637576?u=df5d99db9b899b399effd429f4358baaa6f7199c&v=4 + url: https://github.com/joakimnordling yogabonito: login: yogabonito count: 2 @@ -518,6 +523,11 @@ AyushSinghal1794: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/89984761?v=4 url: https://github.com/AyushSinghal1794 +gsheni: + login: gsheni + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/8726321?u=ee3bd9ff6320f4715d1dd9671a3d55cccb65b984&v=4 + url: https://github.com/gsheni DanielKusyDev: login: DanielKusyDev count: 2 diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 5f1a89141..b544633fd 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -10,7 +10,7 @@ Xewus: url: https://github.com/Xewus sodaMelon: login: sodaMelon - count: 113 + count: 124 avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 url: https://github.com/sodaMelon ceb10n: @@ -35,7 +35,7 @@ hard-coders: url: https://github.com/hard-coders alv2017: login: alv2017 - count: 86 + count: 88 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 nazarepiedady: @@ -105,7 +105,7 @@ alperiox: url: https://github.com/alperiox Rishat-F: login: Rishat-F - count: 41 + count: 42 avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 url: https://github.com/Rishat-F Winand: @@ -136,7 +136,7 @@ SwftAlpc: alejsdev: login: alejsdev count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=843355286cea366cbb3a4fc3a14343bd4eceef55&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 url: https://github.com/alejsdev timothy-jeong: login: timothy-jeong @@ -173,11 +173,6 @@ romashevchenko: count: 32 avatarUrl: https://avatars.githubusercontent.com/u/132477732?v=4 url: https://github.com/romashevchenko -wdh99: - login: wdh99 - count: 31 - avatarUrl: https://avatars.githubusercontent.com/u/108172295?u=8a8fb95d5afe3e0fa33257b2aecae88d436249eb&v=4 - url: https://github.com/wdh99 LorhanSohaky: login: LorhanSohaky count: 30 @@ -253,6 +248,11 @@ Aruelius: count: 24 avatarUrl: https://avatars.githubusercontent.com/u/25380989?u=574f8cfcda3ea77a3f81884f6b26a97068e36a9d&v=4 url: https://github.com/Aruelius +wisderfin: + login: wisderfin + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/77553770?u=9a23740d520d65dc0051cdc1ecd87f31cb900313&v=4 + url: https://github.com/wisderfin OzgunCaglarArslan: login: OzgunCaglarArslan count: 24 @@ -268,11 +268,6 @@ axel584: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 url: https://github.com/axel584 -wisderfin: - login: wisderfin - count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/77553770?u=f3b00a26736ba664e9927a1116c6e8088295e073&v=4 - url: https://github.com/wisderfin AGolicyn: login: AGolicyn count: 21 @@ -328,6 +323,11 @@ ivan-abc: count: 18 avatarUrl: https://avatars.githubusercontent.com/u/36765187?u=c6e0ba571c1ccb6db9d94e62e4b8b5eda811a870&v=4 url: https://github.com/ivan-abc +Limsunoh: + login: Limsunoh + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/90311848?u=f456e0c5709fd50c8cd2898b551558eda14e5f21&v=4 + url: https://github.com/Limsunoh bezaca: login: bezaca count: 17 @@ -353,11 +353,6 @@ jeison-araya: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/57369279?u=17001e68af7d8e5b8c343e5e9df4050f419998d5&v=4 url: https://github.com/jeison-araya -Limsunoh: - login: Limsunoh - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/90311848?u=f456e0c5709fd50c8cd2898b551558eda14e5f21&v=4 - url: https://github.com/Limsunoh yanever: login: yanever count: 16 @@ -376,7 +371,7 @@ Joao-Pedro-P-Holanda: JaeHyuckSa: login: JaeHyuckSa count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/104830931?u=b19b3e24d6030f88d22bd3e953f9525d2f062da3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/104830931?u=6e352201714a05154e5d0ccf91b4715a951c622e&v=4 url: https://github.com/JaeHyuckSa SofiiaTrufanova: login: SofiiaTrufanova @@ -393,6 +388,11 @@ kim-sangah: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/173775778?v=4 url: https://github.com/kim-sangah +DianaTrufanova: + login: DianaTrufanova + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/119067607?u=1cd55f841b68b4a187fa6d06a7dafa5f070195aa&v=4 + url: https://github.com/DianaTrufanova PandaHun: login: PandaHun count: 14 @@ -403,11 +403,6 @@ dukkee: count: 14 avatarUrl: https://avatars.githubusercontent.com/u/36825394?u=ccfd86e6a4f2d093dad6f7544cc875af67fa2df8&v=4 url: https://github.com/dukkee -mkdir700: - login: mkdir700 - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=3d6ea8714f5000829b60dcf7b13a75b1e73aaf47&v=4 - url: https://github.com/mkdir700 BORA040126: login: BORA040126 count: 14 @@ -418,11 +413,6 @@ mattkoehne: count: 14 avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4 url: https://github.com/mattkoehne -DianaTrufanova: - login: DianaTrufanova - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/119067607?u=1cd55f841b68b4a187fa6d06a7dafa5f070195aa&v=4 - url: https://github.com/DianaTrufanova jovicon: login: jovicon count: 13 @@ -463,16 +453,16 @@ oandersonmagalhaes: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/83456692?v=4 url: https://github.com/oandersonmagalhaes +mkdir700: + login: mkdir700 + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=3d6ea8714f5000829b60dcf7b13a75b1e73aaf47&v=4 + url: https://github.com/mkdir700 batlopes: login: batlopes count: 12 avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 url: https://github.com/batlopes -Lenclove: - login: Lenclove - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/32355298?u=d0065e01650c63c2b2413f42d983634b2ea85481&v=4 - url: https://github.com/Lenclove joonas-yoon: login: joonas-yoon count: 12 @@ -493,6 +483,11 @@ andersonrocha0: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4 url: https://github.com/andersonrocha0 +gitgernit: + login: gitgernit + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/129539613?u=d04f10143ab32c93f563ea14bf242d1d2bc991b0&v=4 + url: https://github.com/gitgernit kwang1215: login: kwang1215 count: 12 @@ -543,11 +538,6 @@ KNChiu: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/36751646?v=4 url: https://github.com/KNChiu -gitgernit: - login: gitgernit - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/129539613?u=d04f10143ab32c93f563ea14bf242d1d2bc991b0&v=4 - url: https://github.com/gitgernit mariacamilagl: login: mariacamilagl count: 10 @@ -626,18 +616,18 @@ JulianMaurin: JeongHyeongKim: login: JeongHyeongKim count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/26577800?u=fe653349051c0acf62cd984e74c4ff60ca8d2cb6&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/26577800?u=77f060f4686f32c248907b81b16ee2b3177ca44c&v=4 url: https://github.com/JeongHyeongKim arthurio: login: arthurio count: 9 avatarUrl: https://avatars.githubusercontent.com/u/950449?u=76b997138273ce5e1990b971c4f27c9aff979fd5&v=4 url: https://github.com/arthurio -mahone3297: - login: mahone3297 +Lenclove: + login: Lenclove count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/1701379?u=20588ff0e456d13e8017333eb237595d11410234&v=4 - url: https://github.com/mahone3297 + avatarUrl: https://avatars.githubusercontent.com/u/32355298?u=d0065e01650c63c2b2413f42d983634b2ea85481&v=4 + url: https://github.com/Lenclove eVery1337: login: eVery1337 count: 9 @@ -653,6 +643,11 @@ riroan: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/33053284?u=2d18e3771506ee874b66d6aa2b3b1107fd95c38f&v=4 url: https://github.com/riroan +MinLee0210: + login: MinLee0210 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=175010b24bc3a15a5705424badf9b18823bfd67d&v=4 + url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai count: 9 @@ -693,11 +688,6 @@ bnzone: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/39371503?u=c16f00c41d88479fa2d57b0d7d233b758eacce2d&v=4 url: https://github.com/bnzone -ChuyuChoyeon: - login: ChuyuChoyeon - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/129537877?u=f0c76f3327817a8b86b422d62e04a34bf2827f2b&v=4 - url: https://github.com/ChuyuChoyeon shamosishen: login: shamosishen count: 8 @@ -708,16 +698,16 @@ mertssmnoglu: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/61623638?u=59dd885b68ff1832f9ab3b4a4446896358c23442&v=4 url: https://github.com/mertssmnoglu +mahone3297: + login: mahone3297 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/1701379?u=20588ff0e456d13e8017333eb237595d11410234&v=4 + url: https://github.com/mahone3297 KimJoonSeo: login: KimJoonSeo count: 8 avatarUrl: https://avatars.githubusercontent.com/u/17760162?u=a58cdc77ae1c069a64166f7ecc4d42eecfd9a468&v=4 url: https://github.com/KimJoonSeo -MinLee0210: - login: MinLee0210 - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=25f979af418692b95e907df93607a09117e14b53&v=4 - url: https://github.com/MinLee0210 camigomezdev: login: camigomezdev count: 8 @@ -778,6 +768,11 @@ d2a-raudenaerde: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 url: https://github.com/d2a-raudenaerde +sungchan1: + login: sungchan1 + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4 + url: https://github.com/sungchan1 deniscapeto: login: deniscapeto count: 6 @@ -853,11 +848,6 @@ Kirilex: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/100281552?v=4 url: https://github.com/Kirilex -Mordson: - login: Mordson - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/39025897?u=b94ea96ef35bbe43bc85359cfb31d28ac16d470c&v=4 - url: https://github.com/Mordson arunppsg: login: arunppsg count: 6 @@ -868,11 +858,6 @@ dimastbk: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/3132181?u=66587398d43466a1dc75c238df5f048e0afc77ed&v=4 url: https://github.com/dimastbk -lordqyxz: - login: lordqyxz - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/31722468?u=974553c0ba53526d9be7e9876544283291be3b0d&v=4 - url: https://github.com/lordqyxz dudyaosuplayer: login: dudyaosuplayer count: 6 @@ -941,8 +926,13 @@ jvmazagao: cun3yt: login: cun3yt count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/24409240?u=39f651cdcc4991fb9fef5bbd9e9503db2174ac13&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24409240?u=06abfd77786db859b0602d5369d2ae18c932c17c&v=4 url: https://github.com/cun3yt +Mordson: + login: Mordson + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/39025897?u=b94ea96ef35bbe43bc85359cfb31d28ac16d470c&v=4 + url: https://github.com/Mordson aminkhani: login: aminkhani count: 5 @@ -963,6 +953,11 @@ Chushine: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/135534400?v=4 url: https://github.com/Chushine +ChuyuChoyeon: + login: ChuyuChoyeon + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/129537877?u=f0c76f3327817a8b86b422d62e04a34bf2827f2b&v=4 + url: https://github.com/ChuyuChoyeon frwl404: login: frwl404 count: 5 @@ -1081,13 +1076,18 @@ aminalaee: erfan-rfmhr: login: erfan-rfmhr count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/98986056?u=b1559d684b1ced11b2204546fa3cf28addf665a8&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/98986056?u=0acda1ff1df0989f3f3eb79977baa35da4cb6c8c&v=4 url: https://github.com/erfan-rfmhr Scorpionchiques: login: Scorpionchiques count: 4 avatarUrl: https://avatars.githubusercontent.com/u/15703294?v=4 url: https://github.com/Scorpionchiques +lordqyxz: + login: lordqyxz + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/31722468?u=974553c0ba53526d9be7e9876544283291be3b0d&v=4 + url: https://github.com/lordqyxz heysaeid: login: heysaeid count: 4 @@ -1383,11 +1383,11 @@ tienduong-21: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/80129618?v=4 url: https://github.com/tienduong-21 -jameselite: - login: jameselite +soroushgh1: + login: soroushgh1 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=6964d633449bf7d4a83d0fa0198f81f9ee5cfcd0&v=4 - url: https://github.com/jameselite + avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=e4d791c982cf7899c69f6baeebc4d7bbe86635d1&v=4 + url: https://github.com/soroushgh1 zbellos: login: zbellos count: 3 @@ -1466,7 +1466,7 @@ TimorChow: ataberkciftlikli: login: ataberkciftlikli count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64265169?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/64265169?u=ca7c1348242559f70bc1dc027a4be277c464676f&v=4 url: https://github.com/ataberkciftlikli leandrodesouzadev: login: leandrodesouzadev @@ -1501,7 +1501,7 @@ lindsayzhou: jonatasoli: login: jonatasoli count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 url: https://github.com/jonatasoli tyzh-dev: login: tyzh-dev @@ -1726,7 +1726,7 @@ ZhibangYue: saeye: login: saeye count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/62229734?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 url: https://github.com/saeye Heumhub: login: Heumhub @@ -1763,3 +1763,13 @@ ivintoiu: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 url: https://github.com/ivintoiu +EgorOnishchuk: + login: EgorOnishchuk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 + url: https://github.com/EgorOnishchuk +Azazul123: + login: Azazul123 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/102759111?u=b48ce6e30a81a23467cc30e0c011bcc57f0326ab&v=4 + url: https://github.com/Azazul123 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index f79bb300a..d8593f53f 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -253,11 +253,6 @@ Zssaer: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/45691504?u=4c0c195f25cb5ac6af32acfb0ab35427682938d2&v=4 url: https://github.com/Zssaer -wdh99: - login: wdh99 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108172295?u=8a8fb95d5afe3e0fa33257b2aecae88d436249eb&v=4 - url: https://github.com/wdh99 ChuyuChoyeon: login: ChuyuChoyeon count: 3 @@ -281,7 +276,7 @@ hsuanchi: alejsdev: login: alejsdev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=843355286cea366cbb3a4fc3a14343bd4eceef55&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 url: https://github.com/alejsdev riroan: login: riroan @@ -501,7 +496,7 @@ andersonrocha0: saeye: login: saeye count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/62229734?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 url: https://github.com/saeye timothy-jeong: login: timothy-jeong From a748e7336b4a1799acccf36d8fc5d738649101c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 1 May 2025 13:32:46 +0200 Subject: [PATCH 083/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Sponsors=20(#13664)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 131 ++++++++++++++----------------- 1 file changed, 58 insertions(+), 73 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index de6d44f96..e24f64edc 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -2,18 +2,9 @@ sponsors: - - login: renderinc avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 url: https://github.com/renderinc - - login: bump-sh - avatarUrl: https://avatars.githubusercontent.com/u/33217836?v=4 - url: https://github.com/bump-sh - - login: Nixtla - avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 - url: https://github.com/Nixtla - login: andrew-propelauth avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4 url: https://github.com/andrew-propelauth - - login: zanfaruqui - avatarUrl: https://avatars.githubusercontent.com/u/104461687?v=4 - url: https://github.com/zanfaruqui - login: blockbee-io avatarUrl: https://avatars.githubusercontent.com/u/115143449?u=1b8620c2d6567c4df2111a371b85a51f448f9b85&v=4 url: https://github.com/blockbee-io @@ -26,6 +17,9 @@ sponsors: - login: porter-dev avatarUrl: https://avatars.githubusercontent.com/u/62078005?v=4 url: https://github.com/porter-dev + - login: Nixtla + avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 + url: https://github.com/Nixtla - login: scalar avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 url: https://github.com/scalar @@ -68,10 +62,7 @@ sponsors: - login: acsone avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4 url: https://github.com/acsone -- - login: ecosyste-ms - avatarUrl: https://avatars.githubusercontent.com/u/98474690?v=4 - url: https://github.com/ecosyste-ms - - login: Trivie +- - login: Trivie avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 url: https://github.com/Trivie - - login: takashi-yoneya @@ -80,9 +71,6 @@ sponsors: - - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries - - login: CanoaPBC - avatarUrl: https://avatars.githubusercontent.com/u/64223768?v=4 - url: https://github.com/CanoaPBC - login: yasyf avatarUrl: https://avatars.githubusercontent.com/u/709645?u=f36736b3c6a85f578886ecc42a740e7b436e7a01&v=4 url: https://github.com/yasyf @@ -92,30 +80,27 @@ sponsors: - - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io - - login: povilasb - avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4 - url: https://github.com/povilasb - - login: upciti avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 url: https://github.com/upciti + - login: f4rk4sh + avatarUrl: https://avatars.githubusercontent.com/u/90454259?v=4 + url: https://github.com/f4rk4sh - login: freddiev4 avatarUrl: https://avatars.githubusercontent.com/u/8339018?u=1aad5b4f5a04cb750852b843d5e1d8f4ce339c2e&v=4 url: https://github.com/freddiev4 - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - - login: ProteinQure - avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 - url: https://github.com/ProteinQure + - login: vincentkoc + avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 + url: https://github.com/vincentkoc - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky - login: ramonalmeidam avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 url: https://github.com/ramonalmeidam - - login: mjohnsey - avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 - url: https://github.com/mjohnsey - login: ashi-agrawal avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 url: https://github.com/ashi-agrawal @@ -125,14 +110,11 @@ sponsors: - login: RaamEEIL avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 url: https://github.com/RaamEEIL - - login: b-rad-c - avatarUrl: https://avatars.githubusercontent.com/u/25362581?u=5bb10629f4015b62bec1f9a366675d5085551af9&v=4 - url: https://github.com/b-rad-c - login: ehaca avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 url: https://github.com/ehaca - login: raphaellaude - avatarUrl: https://avatars.githubusercontent.com/u/28026311?u=28faad3e62250ef91a0c3c5d0faba39592d9ab39&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/28026311?u=91e1c00d9ac4f8045527e13de8050d504531cbc0&v=4 url: https://github.com/raphaellaude - login: timlrx avatarUrl: https://avatars.githubusercontent.com/u/28362229?u=9a745ca31372ee324af682715ae88ce8522f9094&v=4 @@ -140,9 +122,12 @@ sponsors: - login: Leay15 avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 url: https://github.com/Leay15 - - login: chickenandstats - avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4 - url: https://github.com/chickenandstats + - login: ProteinQure + avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 + url: https://github.com/ProteinQure + - login: roboflow + avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 + url: https://github.com/roboflow - login: kaoru0310 avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 url: https://github.com/kaoru0310 @@ -161,9 +146,6 @@ sponsors: - login: logic-automation avatarUrl: https://avatars.githubusercontent.com/u/144732884?v=4 url: https://github.com/logic-automation - - login: roboflow - avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 - url: https://github.com/roboflow - login: dudikbender avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 url: https://github.com/dudikbender @@ -176,6 +158,9 @@ sponsors: - login: patricioperezv avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4 url: https://github.com/patricioperezv + - login: chickenandstats + avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4 + url: https://github.com/chickenandstats - login: dodo5522 avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4 url: https://github.com/dodo5522 @@ -185,9 +170,6 @@ sponsors: - login: knallgelb avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4 url: https://github.com/knallgelb - - login: Shark009 - avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4 - url: https://github.com/Shark009 - login: dblackrun avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4 url: https://github.com/dblackrun @@ -206,9 +188,12 @@ sponsors: - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 url: https://github.com/gorhack - - login: vincentkoc - avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 - url: https://github.com/vincentkoc + - login: Ryandaydev + avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 + url: https://github.com/Ryandaydev + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog - login: jstanden avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 url: https://github.com/jstanden @@ -242,6 +227,9 @@ sponsors: - login: mintuhouse avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 url: https://github.com/mintuhouse + - login: oliverxchen + avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 + url: https://github.com/oliverxchen - login: TrevorBenson avatarUrl: https://avatars.githubusercontent.com/u/9167887?u=dccbea3327a57750923333d8ebf1a0b3f1948949&v=4 url: https://github.com/TrevorBenson @@ -263,15 +251,9 @@ sponsors: - login: khadrawy avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4 url: https://github.com/khadrawy - - login: Ryandaydev - avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 - url: https://github.com/Ryandaydev - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog - - login: oliverxchen - avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 - url: https://github.com/oliverxchen + - login: mjohnsey + avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 + url: https://github.com/mjohnsey - login: ternaus avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 url: https://github.com/ternaus @@ -279,7 +261,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4 url: https://github.com/eseglem - login: FernandoCelmer - avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=d29fff3fd862fda4ca752079f13f32e84c762ea4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4 url: https://github.com/FernandoCelmer - login: simw avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4 @@ -302,9 +284,6 @@ sponsors: - login: petercool avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=81c525232bb35780945a68e88afd96bb2cdad9c4&v=4 url: https://github.com/petercool - - login: diegopenilla - avatarUrl: https://avatars.githubusercontent.com/u/42318333?v=4 - url: https://github.com/diegopenilla - login: siavashyj avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4 url: https://github.com/siavashyj @@ -314,6 +293,12 @@ sponsors: - login: ArtyomVancyan avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4 url: https://github.com/ArtyomVancyan + - login: caviri + avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 + url: https://github.com/caviri + - login: hgalytoby + avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 + url: https://github.com/hgalytoby - login: joshuatz avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 url: https://github.com/joshuatz @@ -338,12 +323,6 @@ sponsors: - login: engineerjoe440 avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 url: https://github.com/engineerjoe440 - - login: caviri - avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 - url: https://github.com/caviri - - login: hgalytoby - avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 - url: https://github.com/hgalytoby - login: conservative-dude avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4 url: https://github.com/conservative-dude @@ -366,7 +345,7 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 url: https://github.com/miguelgr - login: WillHogan - avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4 url: https://github.com/WillHogan - login: my3 avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 @@ -458,24 +437,30 @@ sponsors: - login: rwxd avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 url: https://github.com/rwxd - - login: kenkanayama - avatarUrl: https://avatars.githubusercontent.com/u/44771224?u=f68870c20c0f069491411aea8693c4714b40ecf0&v=4 - url: https://github.com/kenkanayama + - login: morzan1001 + avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 + url: https://github.com/morzan1001 - login: sadikkuzu avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 url: https://github.com/sadikkuzu - login: Olegt0rr avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 url: https://github.com/Olegt0rr - - login: FabulousCodingFox - avatarUrl: https://avatars.githubusercontent.com/u/78906517?u=924a27cbee3db7e0ece5cc1509921402e1445e74&v=4 - url: https://github.com/FabulousCodingFox - - login: morzan1001 - avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 - url: https://github.com/morzan1001 - - login: BrianCurliss - avatarUrl: https://avatars.githubusercontent.com/u/1222949?v=4 - url: https://github.com/BrianCurliss + - login: Miles-Arts + avatarUrl: https://avatars.githubusercontent.com/u/82297475?u=c41881e4b386d9dbf737218542b120336b5731a1&v=4 + url: https://github.com/Miles-Arts + - login: sandeepsalwan1 + avatarUrl: https://avatars.githubusercontent.com/u/118837112?u=fc9b0330fa4791950661b7decd9bf56f07599b43&v=4 + url: https://github.com/sandeepsalwan1 + - login: fabioantonioastore + avatarUrl: https://avatars.githubusercontent.com/u/132024075?u=b3a267f2e2c7ce2379f82163f88111bd2a2a2f1e&v=4 + url: https://github.com/fabioantonioastore + - login: zhandos256 + avatarUrl: https://avatars.githubusercontent.com/u/60260671?u=aa9ed698bc3cd06fb553d2ef91d3895bbb00cce1&v=4 + url: https://github.com/zhandos256 + - login: one-st-one + avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 + url: https://github.com/one-st-one - login: Toothwitch avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 url: https://github.com/Toothwitch From ed88e250987d075a0b4df7a784ebf607b3ad7e87 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 11:32:57 +0000 Subject: [PATCH 084/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 08f8ecbbc..c6cbd4413 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#13662](https://github.com/fastapi/fastapi/pull/13662) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13656](https://github.com/fastapi/fastapi/pull/13656) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ✅ Use `inline-snapshot` to support different Pydantic versions in the test suite. PR [#12534](https://github.com/fastapi/fastapi/pull/12534) by [@15r10nk](https://github.com/15r10nk). * ⬆ Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot). From 663aae13b219a9cb30bf95ca11def18d39e97ba2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 11:33:13 +0000 Subject: [PATCH 085/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c6cbd4413..bf5c5d2ab 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Sponsors. PR [#13664](https://github.com/fastapi/fastapi/pull/13664) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13662](https://github.com/fastapi/fastapi/pull/13662) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13656](https://github.com/fastapi/fastapi/pull/13656) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ✅ Use `inline-snapshot` to support different Pydantic versions in the test suite. PR [#12534](https://github.com/fastapi/fastapi/pull/12534) by [@15r10nk](https://github.com/15r10nk). From 418c3c8d2b00dbee8eaa63bb9265b5a660a85121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 1 May 2025 14:58:00 +0200 Subject: [PATCH 086/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20rem?= =?UTF-8?q?ove=20Bump.sh=20and=20Coherence=20(#13668)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 -- docs/en/data/sponsors.yml | 6 ------ docs/en/docs/deployment/cloud.md | 1 - docs/en/overrides/main.html | 12 ------------ 4 files changed, 21 deletions(-) diff --git a/README.md b/README.md index a7a069cce..4d6dcc325 100644 --- a/README.md +++ b/README.md @@ -49,10 +49,8 @@ The key features are: - - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 5cbf05f9d..22e262951 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -8,18 +8,12 @@ gold: - url: https://www.porter.run title: Deploy FastAPI on AWS with a few clicks img: https://fastapi.tiangolo.com/img/sponsors/porter.png - - url: https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor - title: Automate FastAPI documentation generation with Bump.sh - img: https://fastapi.tiangolo.com/img/sponsors/bump-sh.svg - url: https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge title: "Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files" img: https://fastapi.tiangolo.com/img/sponsors/scalar.svg - url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge title: Auth, user management and more for your B2B product img: https://fastapi.tiangolo.com/img/sponsors/propelauth.png - - url: https://www.withcoherence.com/?utm_medium=advertising&utm_source=fastapi&utm_campaign=website - title: Coherence - img: https://fastapi.tiangolo.com/img/sponsors/coherence.png - url: https://www.mongodb.com/developer/languages/python/python-quickstart-fastapi/?utm_campaign=fastapi_framework&utm_source=fastapi_sponsorship&utm_medium=web_referral title: Simplify Full Stack Development with FastAPI & MongoDB img: https://fastapi.tiangolo.com/img/sponsors/mongodb.png diff --git a/docs/en/docs/deployment/cloud.md b/docs/en/docs/deployment/cloud.md index 471808851..d713379c3 100644 --- a/docs/en/docs/deployment/cloud.md +++ b/docs/en/docs/deployment/cloud.md @@ -14,5 +14,4 @@ You might want to try their services and follow their guides: * Platform.sh * Porter -* Coherence * Render diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 30973bfcb..eef505184 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -40,12 +40,6 @@ - - + -
From 48c0d3405da78709d4ff00efdee863e7f2664e19 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 12:58:22 +0000 Subject: [PATCH 088/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bf5c5d2ab..90b22fd87 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* 🔧 Update sponsors: remove Bump.sh and Coherence. PR [#13668](https://github.com/fastapi/fastapi/pull/13668) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13664](https://github.com/fastapi/fastapi/pull/13664) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13662](https://github.com/fastapi/fastapi/pull/13662) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13656](https://github.com/fastapi/fastapi/pull/13656) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From cae8f976d85531f4e9ec5c04d7b2d649221b2bb9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 12:59:02 +0000 Subject: [PATCH 089/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 90b22fd87..9f06dd0e8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* 🔧 Update links for LinkedIn and bottom. PR [#13669](https://github.com/fastapi/fastapi/pull/13669) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove Bump.sh and Coherence. PR [#13668](https://github.com/fastapi/fastapi/pull/13668) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13664](https://github.com/fastapi/fastapi/pull/13664) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13662](https://github.com/fastapi/fastapi/pull/13662) by [@tiangolo](https://github.com/tiangolo). From f512b17992c34ecab6267ea49336771e2be34f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 1 May 2025 14:59:46 +0200 Subject: [PATCH 090/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#13667)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/topic_repos.yml | 390 +++++++++++++++++------------------ 1 file changed, 195 insertions(+), 195 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 7452088db..169b62694 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,246 +1,256 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 31581 + stars: 32337 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 29256 + stars: 29833 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21487 + stars: 21544 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 15521 + stars: 15799 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 15353 + stars: 15676 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 11719 + stars: 12183 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 11129 + stars: 11594 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 9387 + stars: 9586 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8787 + stars: 8804 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 6596 + stars: 6688 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 6302 + stars: 6502 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: serge html_url: https://github.com/serge-chat/serge - stars: 5707 + stars: 5720 owner_login: serge-chat owner_html_url: https://github.com/serge-chat +- name: hatchet + html_url: https://github.com/hatchet-dev/hatchet + stars: 5515 + 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: 5045 + stars: 5162 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: polar html_url: https://github.com/polarsource/polar - stars: 4870 + stars: 5119 owner_login: polarsource owner_html_url: https://github.com/polarsource -- name: hatchet - html_url: https://github.com/hatchet-dev/hatchet - stars: 4658 - owner_login: hatchet-dev - owner_html_url: https://github.com/hatchet-dev - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4310 + stars: 4302 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4217 + stars: 4244 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql +- name: fastapi_mcp + html_url: https://github.com/tadata-org/fastapi_mcp + stars: 4178 + owner_login: tadata-org + owner_html_url: https://github.com/tadata-org - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4111 + stars: 4112 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 3936 + stars: 3985 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: poem html_url: https://github.com/poem-web/poem - stars: 3882 + stars: 3918 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3248 + stars: 3287 owner_login: rashadphz owner_html_url: https://github.com/rashadphz - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3130 + stars: 3192 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: 3141 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi - name: opyrator html_url: https://github.com/ml-tooling/opyrator stars: 3116 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling -- name: datamodel-code-generator - html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3054 - owner_login: koxudaxi - owner_html_url: https://github.com/koxudaxi -- name: docarray - html_url: https://github.com/docarray/docarray - stars: 3033 - owner_login: docarray - owner_html_url: https://github.com/docarray - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3019 + stars: 3088 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI - name: logfire html_url: https://github.com/pydantic/logfire - stars: 2909 + stars: 3059 owner_login: pydantic owner_html_url: https://github.com/pydantic -- name: fastapi-realworld-example-app - html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2863 - owner_login: nsidnev - owner_html_url: https://github.com/nsidnev +- name: docarray + html_url: https://github.com/docarray/docarray + stars: 3052 + owner_login: docarray + owner_html_url: https://github.com/docarray - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 2861 + stars: 3025 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor +- name: fastapi-realworld-example-app + html_url: https://github.com/nsidnev/fastapi-realworld-example-app + stars: 2883 + 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: 2736 + stars: 2756 owner_login: tiangolo owner_html_url: https://github.com/tiangolo - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 2556 + stars: 2587 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2485 + stars: 2502 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 2500 + owner_login: remsky + owner_html_url: https://github.com/remsky - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2409 + stars: 2419 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2337 + stars: 2350 owner_login: Buuntu owner_html_url: https://github.com/Buuntu - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2271 + stars: 2277 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2223 + stars: 2273 owner_login: s3rius owner_html_url: https://github.com/s3rius -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 2191 - owner_login: remsky - owner_html_url: https://github.com/remsky - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2172 + stars: 2183 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2090 + stars: 2141 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2055 + stars: 2070 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2040 + stars: 2063 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: solara html_url: https://github.com/widgetti/solara - stars: 2005 + stars: 2028 owner_login: widgetti owner_html_url: https://github.com/widgetti - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 1936 + stars: 1996 owner_login: supabase owner_html_url: https://github.com/supabase - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1852 + stars: 1870 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1828 + stars: 1827 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 1763 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1730 + stars: 1743 owner_login: ycd owner_html_url: https://github.com/ycd -- name: ormar - html_url: https://github.com/collerek/ormar - stars: 1722 - owner_login: collerek - owner_html_url: https://github.com/collerek - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1715 + stars: 1741 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official +- name: ormar + html_url: https://github.com/collerek/ormar + stars: 1730 + owner_login: collerek + owner_html_url: https://github.com/collerek - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1625 + stars: 1631 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: termpair @@ -248,248 +258,238 @@ stars: 1610 owner_login: cs01 owner_html_url: https://github.com/cs01 -- name: coronavirus-tracker-api - html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1588 - owner_login: ExpDev07 - owner_html_url: https://github.com/ExpDev07 - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1568 + stars: 1588 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm +- name: coronavirus-tracker-api + html_url: https://github.com/ExpDev07/coronavirus-tracker-api + stars: 1587 + owner_login: ExpDev07 + owner_html_url: https://github.com/ExpDev07 - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1526 + stars: 1552 owner_login: long2ice owner_html_url: https://github.com/long2ice - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1504 + stars: 1536 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1476 + stars: 1491 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: awesome-fastapi-projects - html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1433 - owner_login: Kludex - owner_html_url: https://github.com/Kludex - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1408 + stars: 1450 owner_login: laurentS owner_html_url: https://github.com/laurentS +- name: awesome-fastapi-projects + html_url: https://github.com/Kludex/awesome-fastapi-projects + stars: 1443 + owner_login: Kludex + owner_html_url: https://github.com/Kludex - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1386 + stars: 1387 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1343 + stars: 1341 owner_login: ebhy owner_html_url: https://github.com/ebhy - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1309 + stars: 1331 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1262 + stars: 1299 owner_login: teamhide owner_html_url: https://github.com/teamhide -- name: fastapi-tutorial - html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1203 - owner_login: liaogx - owner_html_url: https://github.com/liaogx - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1195 + stars: 1235 owner_login: amisadmin owner_html_url: https://github.com/amisadmin -- name: SurfSense - html_url: https://github.com/MODSetter/SurfSense - stars: 1169 - owner_login: MODSetter - owner_html_url: https://github.com/MODSetter +- name: fastapi-tutorial + html_url: https://github.com/liaogx/fastapi-tutorial + stars: 1222 + owner_login: liaogx + owner_html_url: https://github.com/liaogx +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 1190 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1157 + stars: 1180 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1143 + stars: 1166 owner_login: slackapi owner_html_url: https://github.com/slackapi -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1122 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1112 + stars: 1134 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1127 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai - name: odmantic html_url: https://github.com/art049/odmantic - stars: 1109 + stars: 1115 owner_login: art049 owner_html_url: https://github.com/art049 - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1091 + stars: 1112 owner_login: trallnag owner_html_url: https://github.com/trallnag -- name: vue-fastapi-admin - html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1086 - owner_login: mizhexiaoxiao - owner_html_url: https://github.com/mizhexiaoxiao -- name: bedrock-claude-chat - html_url: https://github.com/aws-samples/bedrock-claude-chat - stars: 1075 +- name: bedrock-chat + html_url: https://github.com/aws-samples/bedrock-chat + stars: 1107 owner_login: aws-samples owner_html_url: https://github.com/aws-samples - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1074 + stars: 1094 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 +- name: restish + html_url: https://github.com/rest-sh/restish + stars: 1041 + owner_login: rest-sh + owner_html_url: https://github.com/rest-sh +- name: fastcrud + html_url: https://github.com/igorbenav/fastcrud + stars: 1036 + owner_login: igorbenav + owner_html_url: https://github.com/igorbenav - name: runhouse html_url: https://github.com/run-house/runhouse - stars: 1016 + stars: 1022 owner_login: run-house owner_html_url: https://github.com/run-house -- name: restish - html_url: https://github.com/danielgtaylor/restish - stars: 1012 - owner_login: danielgtaylor - owner_html_url: https://github.com/danielgtaylor +- name: fastapi_best_architecture + html_url: https://github.com/fastapi-practices/fastapi_best_architecture + stars: 997 + owner_login: fastapi-practices + owner_html_url: https://github.com/fastapi-practices - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 988 + stars: 990 owner_login: ajndkr owner_html_url: https://github.com/ajndkr - name: autollm html_url: https://github.com/viddexa/autollm - stars: 987 + stars: 990 owner_login: viddexa owner_html_url: https://github.com/viddexa -- name: fastcrud - html_url: https://github.com/igorbenav/fastcrud - stars: 985 - owner_login: igorbenav - owner_html_url: https://github.com/igorbenav - name: secure html_url: https://github.com/TypeError/secure - stars: 930 + stars: 932 owner_login: TypeError owner_html_url: https://github.com/TypeError - name: langcorn html_url: https://github.com/msoedov/langcorn - stars: 924 + stars: 925 owner_login: msoedov owner_html_url: https://github.com/msoedov -- name: fastapi_best_architecture - html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 921 - owner_login: fastapi-practices - owner_html_url: https://github.com/fastapi-practices -- name: energy-forecasting - html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 903 - owner_login: iusztinpaul - owner_html_url: https://github.com/iusztinpaul -- name: authx - html_url: https://github.com/yezz123/authx - stars: 900 - owner_login: yezz123 - owner_html_url: https://github.com/yezz123 - name: FastAPI-boilerplate html_url: https://github.com/igorbenav/FastAPI-boilerplate - stars: 877 + stars: 925 owner_login: igorbenav owner_html_url: https://github.com/igorbenav +- name: authx + html_url: https://github.com/yezz123/authx + stars: 913 + owner_login: yezz123 + owner_html_url: https://github.com/yezz123 +- name: energy-forecasting + html_url: https://github.com/iusztinpaul/energy-forecasting + stars: 907 + owner_login: iusztinpaul + owner_html_url: https://github.com/iusztinpaul - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 853 + stars: 873 owner_login: developmentseed owner_html_url: https://github.com/developmentseed -- name: ludic - html_url: https://github.com/getludic/ludic - stars: 831 - owner_login: getludic - owner_html_url: https://github.com/getludic +- name: httpdbg + html_url: https://github.com/cle-b/httpdbg + stars: 850 + owner_login: cle-b + owner_html_url: https://github.com/cle-b - name: marker-api html_url: https://github.com/adithya-s-k/marker-api - stars: 829 + stars: 844 owner_login: adithya-s-k owner_html_url: https://github.com/adithya-s-k +- name: ludic + html_url: https://github.com/getludic/ludic + stars: 842 + owner_login: getludic + owner_html_url: https://github.com/getludic +- name: flock + html_url: https://github.com/Onelevenvy/flock + stars: 805 + owner_login: Onelevenvy + owner_html_url: https://github.com/Onelevenvy - name: fastapi-observability html_url: https://github.com/blueswen/fastapi-observability - stars: 771 + stars: 797 owner_login: blueswen owner_html_url: https://github.com/blueswen - name: fastapi-do-zero html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 767 + stars: 786 owner_login: dunossauro owner_html_url: https://github.com/dunossauro - name: fastapi-mail html_url: https://github.com/sabuhish/fastapi-mail - stars: 759 + stars: 781 owner_login: sabuhish owner_html_url: https://github.com/sabuhish -- name: lccn_predictor - html_url: https://github.com/baoliay2008/lccn_predictor - stars: 749 - owner_login: baoliay2008 - owner_html_url: https://github.com/baoliay2008 -- name: flock - html_url: https://github.com/Onelevenvy/flock - stars: 746 - owner_login: Onelevenvy - owner_html_url: https://github.com/Onelevenvy - name: starlette-admin html_url: https://github.com/jowilf/starlette-admin - stars: 737 + stars: 764 owner_login: jowilf owner_html_url: https://github.com/jowilf -- name: annotated-py-projects - html_url: https://github.com/hhstore/annotated-py-projects - stars: 729 - owner_login: hhstore - owner_html_url: https://github.com/hhstore +- name: lccn_predictor + html_url: https://github.com/baoliay2008/lccn_predictor + stars: 759 + owner_login: baoliay2008 + owner_html_url: https://github.com/baoliay2008 - name: KonomiTV html_url: https://github.com/tsukumijima/KonomiTV - stars: 727 + stars: 741 owner_login: tsukumijima owner_html_url: https://github.com/tsukumijima -- name: learn-generative-ai - html_url: https://github.com/panaverse/learn-generative-ai - stars: 725 - owner_login: panaverse - owner_html_url: https://github.com/panaverse - name: FastAPI-Backend-Template html_url: https://github.com/Aeternalis-Ingenium/FastAPI-Backend-Template - stars: 719 + stars: 734 owner_login: Aeternalis-Ingenium owner_html_url: https://github.com/Aeternalis-Ingenium -- name: chatGPT-web - html_url: https://github.com/mic1on/chatGPT-web - stars: 712 - owner_login: mic1on - owner_html_url: https://github.com/mic1on -- name: linbing - html_url: https://github.com/taomujian/linbing - stars: 698 - owner_login: taomujian - owner_html_url: https://github.com/taomujian +- name: learn-generative-ai + html_url: https://github.com/panaverse/learn-generative-ai + stars: 731 + owner_login: panaverse + owner_html_url: https://github.com/panaverse +- name: annotated-py-projects + html_url: https://github.com/hhstore/annotated-py-projects + stars: 730 + owner_login: hhstore + owner_html_url: https://github.com/hhstore From 6eb31132e5c530e91573a8496c7e75856fc1cf2c Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 13:00:17 +0000 Subject: [PATCH 091/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9f06dd0e8..e916ca42d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -30,6 +30,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#13667](https://github.com/fastapi/fastapi/pull/13667) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update links for LinkedIn and bottom. PR [#13669](https://github.com/fastapi/fastapi/pull/13669) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove Bump.sh and Coherence. PR [#13668](https://github.com/fastapi/fastapi/pull/13668) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13664](https://github.com/fastapi/fastapi/pull/13664) by [@tiangolo](https://github.com/tiangolo). From 16234a3f4fcc323d4aad92c3a4fd0201770b077b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 1 May 2025 15:13:51 +0200 Subject: [PATCH 092/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20docs=20for=20"H?= =?UTF-8?q?elp=20FastAPI",=20simplify=20and=20reduce=20"sponsor"=20section?= =?UTF-8?q?=20(#13670)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/help-fastapi.md | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index 81151032f..35d2e7b84 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -249,20 +249,7 @@ On the other side, there are thousands of users in the chat systems, so there's ## Sponsor the author -You can also financially support the author (me) through GitHub sponsors. - -There you could buy me a coffee ☕️ to say thanks. 😄 - -And you can also become a Silver or Gold sponsor for FastAPI. 🏅🎉 - -## Sponsor the tools that power FastAPI - -As you have seen in the documentation, FastAPI stands on the shoulders of giants, Starlette and Pydantic. - -You can also sponsor: - -* Samuel Colvin (Pydantic) -* Encode (Starlette, Uvicorn) +If your **product/company** depends on or is related to **FastAPI** and you want to reach its users, you can sponsor the author (me) through GitHub sponsors. Depending on the tier, you could get some extra benefits, like a badge in the docs. 🎁 --- From 7fdc4952bdd1b32fbb96bffc86e30d001962d442 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 13:14:19 +0000 Subject: [PATCH 093/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e916ca42d..5884c6129 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* 📝 Update docs for "Help FastAPI", simplify and reduce "sponsor" section. PR [#13670](https://github.com/fastapi/fastapi/pull/13670) by [@tiangolo](https://github.com/tiangolo). * 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc). * ✏️ Fix syntax error in `docs/en/docs/tutorial/handling-errors.md`. PR [#13623](https://github.com/fastapi/fastapi/pull/13623) by [@gsheni](https://github.com/gsheni). * 📝 Fix typo in documentation. PR [#13599](https://github.com/fastapi/fastapi/pull/13599) by [@Taoup](https://github.com/Taoup). From bc56c74d6b21300feaae66d27790c8e1c254928a Mon Sep 17 00:00:00 2001 From: Martyn Davies Date: Thu, 1 May 2025 15:15:38 +0200 Subject: [PATCH 094/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20Sponsors:=20Zup?= =?UTF-8?q?lo=20logo=20and=20alt=20text=20(#13645)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- README.md | 2 +- docs/en/data/sponsors.yml | 2 +- docs/en/docs/img/sponsors/zuplo.png | Bin 18891 -> 7551 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4d6dcc325..40d0cdf6c 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ The key features are: - + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 22e262951..f42f67ada 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -18,7 +18,7 @@ gold: title: Simplify Full Stack Development with FastAPI & MongoDB img: https://fastapi.tiangolo.com/img/sponsors/mongodb.png - url: https://zuplo.link/fastapi-gh - title: 'Zuplo: Scale, Protect, Document, and Monetize your FastAPI' + title: 'Zuplo: Deploy, Secure, Document, and Monetize your FastAPI' img: https://fastapi.tiangolo.com/img/sponsors/zuplo.png - url: https://liblab.com?utm_source=fastapi title: liblab - Generate SDKs from FastAPI diff --git a/docs/en/docs/img/sponsors/zuplo.png b/docs/en/docs/img/sponsors/zuplo.png index 7a7c16862983be77faf22ac937c1917fad0b812b..6a4ed233e9edcb50286bdf4d735458a20b3f13cc 100644 GIT binary patch literal 7551 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 VEU6WA8oB@g002ovPDHLkV1j!%^=tqD literal 18891 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 Date: Thu, 1 May 2025 15:15:45 +0200 Subject: [PATCH 095/455] =?UTF-8?q?=E2=AC=86=20Bump=20typer=20from=200.12.?= =?UTF-8?q?5=20to=200.15.3=20(#13666)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [typer](https://github.com/fastapi/typer) from 0.12.5 to 0.15.3. - [Release notes](https://github.com/fastapi/typer/releases) - [Changelog](https://github.com/fastapi/typer/blob/master/docs/release-notes.md) - [Commits](https://github.com/fastapi/typer/compare/0.12.5...0.15.3) --- updated-dependencies: - dependency-name: typer dependency-version: 0.15.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 8812e27f9..bd0082304 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -3,7 +3,7 @@ mkdocs-material==9.6.1 mdx-include >=1.4.1,<2.0.0 mkdocs-redirects>=1.2.1,<1.3.0 -typer == 0.12.5 +typer == 0.15.3 pyyaml >=5.3.1,<7.0.0 # For Material for MkDocs, Chinese search jieba==0.42.1 From b57b8e7ad2cec74939331bb610344666eb1175d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 15:15:54 +0200 Subject: [PATCH 096/455] =?UTF-8?q?=E2=AC=86=20Bump=20sqlmodel=20from=200.?= =?UTF-8?q?0.23=20to=200.0.24=20(#13665)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [sqlmodel](https://github.com/fastapi/sqlmodel) from 0.0.23 to 0.0.24. - [Release notes](https://github.com/fastapi/sqlmodel/releases) - [Changelog](https://github.com/fastapi/sqlmodel/blob/main/docs/release-notes.md) - [Commits](https://github.com/fastapi/sqlmodel/compare/0.0.23...0.0.24) --- updated-dependencies: - dependency-name: sqlmodel dependency-version: 0.0.24 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-tests.txt b/requirements-tests.txt index f722825dd..b9f2b2b66 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -4,7 +4,7 @@ pytest >=7.1.3,<9.0.0 coverage[toml] >= 6.5.0,< 8.0 mypy ==1.8.0 dirty-equals ==0.9.0 -sqlmodel==0.0.23 +sqlmodel==0.0.24 flask >=1.1.2,<4.0.0 anyio[trio] >=3.2.1,<5.0.0 PyJWT==2.8.0 From 581e3a0051d96a346f8f573c4e52e48a115328f7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 13:16:30 +0000 Subject: [PATCH 097/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5884c6129..f93cf505c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* 🔧 Update Sponsors: Zuplo logo and alt text. PR [#13645](https://github.com/fastapi/fastapi/pull/13645) by [@martyndavies](https://github.com/martyndavies). * 👥 Update FastAPI GitHub topic repositories. PR [#13667](https://github.com/fastapi/fastapi/pull/13667) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update links for LinkedIn and bottom. PR [#13669](https://github.com/fastapi/fastapi/pull/13669) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove Bump.sh and Coherence. PR [#13668](https://github.com/fastapi/fastapi/pull/13668) by [@tiangolo](https://github.com/tiangolo). From fb1affca1b86565a7fe1b4661032fd4ec5cc7428 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 13:16:45 +0000 Subject: [PATCH 098/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f93cf505c..88fe8fdec 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* ⬆ Bump sqlmodel from 0.0.23 to 0.0.24. PR [#13665](https://github.com/fastapi/fastapi/pull/13665) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Sponsors: Zuplo logo and alt text. PR [#13645](https://github.com/fastapi/fastapi/pull/13645) by [@martyndavies](https://github.com/martyndavies). * 👥 Update FastAPI GitHub topic repositories. PR [#13667](https://github.com/fastapi/fastapi/pull/13667) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update links for LinkedIn and bottom. PR [#13669](https://github.com/fastapi/fastapi/pull/13669) by [@tiangolo](https://github.com/tiangolo). From 6df106b8772306d60bab4b273b888f2103f8be79 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 13:16:47 +0000 Subject: [PATCH 099/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 88fe8fdec..30127af56 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* ⬆ Bump typer from 0.12.5 to 0.15.3. PR [#13666](https://github.com/fastapi/fastapi/pull/13666) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump sqlmodel from 0.0.23 to 0.0.24. PR [#13665](https://github.com/fastapi/fastapi/pull/13665) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Sponsors: Zuplo logo and alt text. PR [#13645](https://github.com/fastapi/fastapi/pull/13645) by [@martyndavies](https://github.com/martyndavies). * 👥 Update FastAPI GitHub topic repositories. PR [#13667](https://github.com/fastapi/fastapi/pull/13667) by [@tiangolo](https://github.com/tiangolo). From 3620a2b213a16eefe6b6bc9cfc90b33bfedacd92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 1 May 2025 16:42:39 +0200 Subject: [PATCH 100/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#13671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/people.yml | 426 ++++++++++++++++++---------------------- 1 file changed, 191 insertions(+), 235 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 02a91ed19..a94c7c63c 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,11 +1,11 @@ maintainers: - login: tiangolo - answers: 1897 + answers: 1898 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo experts: - login: tiangolo - count: 1897 + count: 1898 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: github-actions @@ -20,14 +20,14 @@ experts: count: 263 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 +- login: YuriiMotov + count: 247 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov - login: dmontagu count: 240 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu -- login: YuriiMotov - count: 238 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov - login: Mause count: 219 avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4 @@ -72,14 +72,14 @@ experts: count: 67 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty +- login: luzzodev + count: 61 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: falkben count: 59 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben -- login: luzzodev - count: 54 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev - login: acidjunk count: 50 avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 @@ -113,7 +113,7 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4 url: https://github.com/frankie567 - login: sinisaos - count: 40 + count: 41 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos - login: includeamin @@ -146,8 +146,12 @@ experts: url: https://github.com/hasansezertasan - login: dbanty count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9d726785d08e50b1e1cd96505800c8ea8405bce2&v=4 url: https://github.com/dbanty +- login: alv2017 + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: wshayes count: 25 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 @@ -156,18 +160,14 @@ experts: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 url: https://github.com/SirTelemak -- login: alv2017 - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: nymous - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 - url: https://github.com/nymous - login: connebs count: 22 avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=e151d5f545a3395136d711c227c22032fda67cfa&v=4 url: https://github.com/connebs +- login: nymous + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 + url: https://github.com/nymous - login: chrisK824 count: 22 avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 @@ -222,7 +222,7 @@ experts: url: https://github.com/nkhitrov - login: jonatasoli count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 url: https://github.com/jonatasoli - login: dstlny count: 16 @@ -245,59 +245,39 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/33907262?u=2721fb37014d50daf473267c808aa678ecaefe09&v=4 url: https://github.com/simondale00 last_month_experts: +- login: YuriiMotov + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov +- login: luzzodev + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: alv2017 - count: 12 + count: 3 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -- login: luzzodev - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev -- login: yauhen-sobaleu - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 - url: https://github.com/yauhen-sobaleu -- login: JavierSanchezCastro - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: marsboy02 +- login: sachinh35 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 - url: https://github.com/marsboy02 -- login: Ale-Cas + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: KianAnbarestani count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: EverStarck + avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 + url: https://github.com/KianAnbarestani +- login: tiangolo count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 - url: https://github.com/EverStarck -- login: jgould22 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: Kludex - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: YuriiMotov - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo three_months_experts: -- login: Kludex - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: YuriiMotov - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov - login: luzzodev - count: 22 + count: 25 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev +- login: YuriiMotov + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov - login: alv2017 count: 22 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 @@ -306,46 +286,50 @@ three_months_experts: count: 13 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 +- login: Kludex + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: yauhen-sobaleu - count: 8 + count: 9 avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu - login: JavierSanchezCastro - count: 8 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro -- login: sehraramiz - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz - login: tiangolo - count: 4 + count: 6 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: yokwejuste - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 - url: https://github.com/yokwejuste +- login: sachinh35 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe -- login: PREPONDERANCE +- login: KianAnbarestani count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE -- login: nbx3 + avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 + url: https://github.com/KianAnbarestani +- login: sinisaos count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: marsboy02 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 - url: https://github.com/marsboy02 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos - login: Ale-Cas count: 2 avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 url: https://github.com/Ale-Cas +- login: adsouza + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 + url: https://github.com/adsouza +- login: marsboy02 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 + url: https://github.com/marsboy02 - login: EverStarck count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 @@ -354,67 +338,47 @@ three_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 url: https://github.com/vtgn -- login: Trinkes - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 - url: https://github.com/Trinkes -- login: XiaoXinYo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/XiaoXinYo -- login: iloveitaly - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly six_months_experts: -- login: YuriiMotov - count: 61 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov - login: luzzodev - count: 54 + count: 57 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev +- login: YuriiMotov + count: 56 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov - login: Kludex - count: 40 + count: 34 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: alv2017 - count: 22 + count: 25 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 - login: jgould22 count: 17 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: JavierSanchezCastro - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: sinisaos - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos - login: sehraramiz count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz -- login: Kfir-G - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 - url: https://github.com/Kfir-G +- login: JavierSanchezCastro + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro - login: yauhen-sobaleu - count: 8 + count: 9 avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu -- login: yvallois - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois - login: estebanx64 count: 7 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 +- login: yvallois + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 + url: https://github.com/yvallois - login: tiangolo count: 6 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 @@ -423,6 +387,10 @@ six_months_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste +- login: sachinh35 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 @@ -431,14 +399,30 @@ six_months_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe -- login: pawelad - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 - url: https://github.com/pawelad -- login: dbfreem - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 - url: https://github.com/dbfreem +- login: chaitanyarahalkar + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/24942959?u=d3fbbc622540cb50b956585d5aec5037e01e4b1f&v=4 + url: https://github.com/chaitanyarahalkar +- login: KianAnbarestani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 + url: https://github.com/KianAnbarestani +- login: sinisaos + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: adsouza + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 + url: https://github.com/adsouza +- login: Synrom + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 + url: https://github.com/Synrom - login: PREPONDERANCE count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 @@ -451,18 +435,10 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 url: https://github.com/marsboy02 -- login: Ale-Cas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas - login: EverStarck count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 url: https://github.com/EverStarck -- login: n8sty - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty - login: vtgn count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 @@ -491,10 +467,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 url: https://github.com/gelezo43 -- login: 1001pepi - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/82064861?u=8c6ffdf2275d6970a07294752c545cd2702c57d3&v=4 - url: https://github.com/1001pepi - login: AliYmn count: 2 avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=98c1fca46c7e4dabe8c39d17b5e55d1511d41cf9&v=4 @@ -503,85 +475,69 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 url: https://github.com/RichieB2B -- login: Synrom - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 - url: https://github.com/Synrom - login: iiotsrc count: 2 avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 url: https://github.com/iiotsrc -- login: Isuxiz +- login: Kfir-G count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 - url: https://github.com/Isuxiz -- login: Reemyos - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/44867003?v=4 - url: https://github.com/Reemyos -- login: deight93 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 - url: https://github.com/deight93 -- login: Jkrox - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/83181939?u=d6a922d97129f7f3916d6a1c166bc011b3a72b7f&v=4 - url: https://github.com/Jkrox + avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 + url: https://github.com/Kfir-G one_year_experts: - login: YuriiMotov - count: 196 + count: 172 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov - login: Kludex - count: 65 + count: 63 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: luzzodev - count: 54 + count: 61 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: sinisaos - count: 40 + count: 41 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos - login: JavierSanchezCastro - count: 37 + count: 33 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: jgould22 - count: 32 + count: 27 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 +- login: alv2017 + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: tiangolo count: 24 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: alv2017 - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: n8sty - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty -- login: estebanx64 - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 - login: ceb10n count: 15 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n -- login: sehraramiz - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz +- login: estebanx64 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 + url: https://github.com/estebanx64 +- login: n8sty + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty - login: Kfir-G count: 13 avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 url: https://github.com/Kfir-G +- login: sehraramiz + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz - login: PhysicallyActive - count: 12 + count: 11 avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 url: https://github.com/PhysicallyActive - login: mattmess1221 @@ -589,7 +545,7 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 url: https://github.com/mattmess1221 - login: yauhen-sobaleu - count: 8 + count: 9 avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu - login: AIdjis @@ -601,13 +557,9 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 url: https://github.com/yvallois - login: hasansezertasan - count: 7 + count: 5 avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 url: https://github.com/hasansezertasan -- login: PREPONDERANCE - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE - login: gustavosett count: 5 avatarUrl: https://avatars.githubusercontent.com/u/99373133?u=1382fe27034a0179f07cf989f63c4f23017f043c&v=4 @@ -616,10 +568,10 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/32629225?u=3b7c30e8a09426a1b9284f6e8a0ae53a525596bf&v=4 url: https://github.com/chyok -- login: acidjunk +- login: PREPONDERANCE count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk + avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 + url: https://github.com/PREPONDERANCE - login: svlandeg count: 4 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 @@ -632,22 +584,18 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 url: https://github.com/yokwejuste -- login: bertomaniac - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 - url: https://github.com/bertomaniac - login: binbjz count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/8213913?u=22b68b7a0d5bf5e09c02084c0f5f53d7503114cd&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/8213913?u=40b777c625cf53dcdc6afc4aa127de67c48bf610&v=4 url: https://github.com/binbjz -- login: CharlesPerrotMinotHCHB +- login: dbfreem count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/112571330?u=a9628848d6096b491135727435a2a253152995a1&v=4 - url: https://github.com/CharlesPerrotMinotHCHB -- login: ryanisn + avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 + url: https://github.com/dbfreem +- login: sachinh35 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/53449841?v=4 - url: https://github.com/ryanisn + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 @@ -656,10 +604,6 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe -- login: pythonweb2 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 - login: DeoLeung count: 3 avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 @@ -668,22 +612,18 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 url: https://github.com/pawelad -- login: dbfreem - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 - url: https://github.com/dbfreem - login: Isuxiz count: 3 avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 url: https://github.com/Isuxiz +- login: bertomaniac + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 + url: https://github.com/bertomaniac - login: deight93 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 url: https://github.com/deight93 -- login: mmzeynalli - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/33568903?u=19efd0c0722730b83a70b7c86c36e5b7d83e07d2&v=4 - url: https://github.com/mmzeynalli - login: Minibrams count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 @@ -692,6 +632,42 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8014288?u=69580504c51a0cdd756fc47b23bb7f404bd694e7&v=4 url: https://github.com/alexandercronin +- login: yanggeorge + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 + url: https://github.com/yanggeorge +- login: chaitanyarahalkar + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/24942959?u=d3fbbc622540cb50b956585d5aec5037e01e4b1f&v=4 + url: https://github.com/chaitanyarahalkar +- login: KianAnbarestani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 + url: https://github.com/KianAnbarestani +- login: rustonaut + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7632017?u=652bb86c1399727082c929fd4666fd7fa65923b1&v=4 + url: https://github.com/rustonaut +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: CharlesPerrotMinotHCHB + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112571330?u=a9628848d6096b491135727435a2a253152995a1&v=4 + url: https://github.com/CharlesPerrotMinotHCHB +- login: adsouza + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 + url: https://github.com/adsouza +- login: Synrom + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 + url: https://github.com/Synrom +- login: gaby + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/835733?u=8c72dec16fa560bdc81113354f2ffd79ad062bde&v=4 + url: https://github.com/gaby - login: nbx3 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 @@ -700,22 +676,10 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 url: https://github.com/marsboy02 -- login: Ale-Cas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: patrick91 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/667029?u=e35958a75ac1f99c81b4bc99e22db8cd665ae7f0&v=4 - url: https://github.com/patrick91 - login: EverStarck count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 url: https://github.com/EverStarck -- login: rustonaut - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7632017?u=652bb86c1399727082c929fd4666fd7fa65923b1&v=4 - url: https://github.com/rustonaut - login: Trolldemorted count: 2 avatarUrl: https://avatars.githubusercontent.com/u/10261186?v=4 @@ -728,10 +692,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 url: https://github.com/slafs -- login: Wyko - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/467094?v=4 - url: https://github.com/Wyko - login: ddahan count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 @@ -740,10 +700,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 url: https://github.com/vtgn -- login: SDAravind - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72403396?v=4 - url: https://github.com/SDAravind - login: redb0 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/30475117?v=4 From ea839df09e5f1271767b05ea659363ba3959ffcb Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 1 May 2025 14:43:04 +0000 Subject: [PATCH 101/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 30127af56..63bfa7029 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#13671](https://github.com/fastapi/fastapi/pull/13671) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump typer from 0.12.5 to 0.15.3. PR [#13666](https://github.com/fastapi/fastapi/pull/13666) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump sqlmodel from 0.0.23 to 0.0.24. PR [#13665](https://github.com/fastapi/fastapi/pull/13665) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Sponsors: Zuplo logo and alt text. PR [#13645](https://github.com/fastapi/fastapi/pull/13645) by [@martyndavies](https://github.com/martyndavies). From 1d63896c3537266dd9c89278e87b0c78d76435ae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 May 2025 10:23:09 +0200 Subject: [PATCH 102/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13688)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.7 → v0.11.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.7...v0.11.8) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b1429a562..2a688e2b4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.7 + rev: v0.11.8 hooks: - id: ruff args: From 9a33ba46ac3a3ef0b845c8515822f4e13c0fb443 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 6 May 2025 08:23:30 +0000 Subject: [PATCH 103/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 63bfa7029..a0a7520d1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13688](https://github.com/fastapi/fastapi/pull/13688) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Experts. PR [#13671](https://github.com/fastapi/fastapi/pull/13671) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump typer from 0.12.5 to 0.15.3. PR [#13666](https://github.com/fastapi/fastapi/pull/13666) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump sqlmodel from 0.0.23 to 0.0.24. PR [#13665](https://github.com/fastapi/fastapi/pull/13665) by [@dependabot[bot]](https://github.com/apps/dependabot). From f61fe35178d0ea00067da0cbdab058d3c8b87a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 9 May 2025 15:48:50 +0200 Subject: [PATCH 104/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20rem?= =?UTF-8?q?ove=20deepset=20/=20Haystack=20(#13700)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - docs/en/data/sponsors.yml | 3 --- 2 files changed, 4 deletions(-) diff --git a/README.md b/README.md index 40d0cdf6c..b834654b1 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index f42f67ada..5e714b2c5 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -30,9 +30,6 @@ gold: title: Cut Code Review Time & Bugs in Half with CodeRabbit img: https://fastapi.tiangolo.com/img/sponsors/coderabbit.png silver: - - url: https://github.com/deepset-ai/haystack/ - title: Build powerful search from composable, open source building blocks - img: https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg - url: https://databento.com/ title: Pay as you go for market data img: https://fastapi.tiangolo.com/img/sponsors/databento.svg From acbf27c97175d6ca7e7fbb71778ff2431041c7de Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 9 May 2025 13:49:14 +0000 Subject: [PATCH 105/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a0a7520d1..bcfe5cefa 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* 🔧 Update sponsors: remove deepset / Haystack. PR [#13700](https://github.com/fastapi/fastapi/pull/13700) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13688](https://github.com/fastapi/fastapi/pull/13688) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Experts. PR [#13671](https://github.com/fastapi/fastapi/pull/13671) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump typer from 0.12.5 to 0.15.3. PR [#13666](https://github.com/fastapi/fastapi/pull/13666) by [@dependabot[bot]](https://github.com/apps/dependabot). From a9a2782f951eaaeb42123d54b14f4db05d1c332b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 9 May 2025 18:36:42 +0200 Subject: [PATCH 106/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20add?= =?UTF-8?q?=20Subtotal=20(#13701)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- README.md | 1 + docs/en/data/sponsors.yml | 3 + docs/en/docs/img/sponsors/subtotal-banner.svg | 133 ++++++++++++++++++ docs/en/docs/img/sponsors/subtotal.svg | 31 ++++ docs/en/overrides/main.html | 6 + 5 files changed, 174 insertions(+) create mode 100644 docs/en/docs/img/sponsors/subtotal-banner.svg create mode 100644 docs/en/docs/img/sponsors/subtotal.svg diff --git a/README.md b/README.md index b834654b1..d668babbb 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 5e714b2c5..a46fd03f5 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -29,6 +29,9 @@ gold: - url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi title: Cut Code Review Time & Bugs in Half with CodeRabbit img: https://fastapi.tiangolo.com/img/sponsors/coderabbit.png + - url: https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source + title: The Gold Standard in Retail Account Linking + img: https://fastapi.tiangolo.com/img/sponsors/subtotal.svg silver: - url: https://databento.com/ title: Pay as you go for market data diff --git a/docs/en/docs/img/sponsors/subtotal-banner.svg b/docs/en/docs/img/sponsors/subtotal-banner.svg new file mode 100644 index 000000000..3d6c98dfc --- /dev/null +++ b/docs/en/docs/img/sponsors/subtotal-banner.svg @@ -0,0 +1,133 @@ + + + + + sponsorship-banner + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/subtotal.svg b/docs/en/docs/img/sponsors/subtotal.svg new file mode 100644 index 000000000..b944c1b2c --- /dev/null +++ b/docs/en/docs/img/sponsors/subtotal.svg @@ -0,0 +1,31 @@ + + + sponsorship-badge + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index b81003808..9d985ea87 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -86,6 +86,12 @@
+
{% endblock %} From f3bfa3b8a510a6e7aa7f212dfddee50f7a948883 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 9 May 2025 16:37:03 +0000 Subject: [PATCH 107/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bcfe5cefa..0a1293e9f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -31,6 +31,7 @@ hide: ### Internal +* 🔧 Update sponsors: add Subtotal. PR [#13701](https://github.com/fastapi/fastapi/pull/13701) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove deepset / Haystack. PR [#13700](https://github.com/fastapi/fastapi/pull/13700) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13688](https://github.com/fastapi/fastapi/pull/13688) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Experts. PR [#13671](https://github.com/fastapi/fastapi/pull/13671) by [@tiangolo](https://github.com/tiangolo). From 214e0740c8cea64858285b02defac2d8ae071f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 11 May 2025 15:37:26 +0200 Subject: [PATCH 108/455] =?UTF-8?q?=F0=9F=8D=B1=20Update=20Drawio=20diagra?= =?UTF-8?q?ms=20SVGs,=20single=20file=20per=20diagram,=20sans-serif=20font?= =?UTF-8?q?=20(#13706)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/de/docs/deployment/concepts.md | 2 +- docs/de/docs/deployment/https.md | 18 +- docs/de/docs/tutorial/bigger-applications.md | 4 +- docs/em/docs/deployment/concepts.md | 2 +- docs/em/docs/deployment/https.md | 18 +- docs/em/docs/tutorial/bigger-applications.md | 4 +- docs/en/docs/deployment/concepts.md | 2 +- docs/en/docs/deployment/https.md | 18 +- .../deployment/concepts/process-ram.drawio | 106 -- .../concepts/process-ram.drawio.svg | 297 ++++++ .../img/deployment/concepts/process-ram.svg | 59 -- .../en/docs/img/deployment/https/https.drawio | 277 ------ .../img/deployment/https/https.drawio.svg | 907 ++++++++++++++++++ docs/en/docs/img/deployment/https/https.svg | 62 -- .../docs/img/deployment/https/https01.drawio | 78 -- .../img/deployment/https/https01.drawio.svg | 131 +++ docs/en/docs/img/deployment/https/https01.svg | 57 -- .../docs/img/deployment/https/https02.drawio | 110 --- .../img/deployment/https/https02.drawio.svg | 245 +++++ docs/en/docs/img/deployment/https/https02.svg | 57 -- .../docs/img/deployment/https/https03.drawio | 131 --- .../img/deployment/https/https03.drawio.svg | 715 ++++++++++++++ docs/en/docs/img/deployment/https/https03.svg | 62 -- .../docs/img/deployment/https/https04.drawio | 152 --- .../img/deployment/https/https04.drawio.svg | 419 ++++++++ docs/en/docs/img/deployment/https/https04.svg | 62 -- .../docs/img/deployment/https/https05.drawio | 166 ---- .../img/deployment/https/https05.drawio.svg | 641 +++++++++++++ docs/en/docs/img/deployment/https/https05.svg | 62 -- .../docs/img/deployment/https/https06.drawio | 183 ---- .../img/deployment/https/https06.drawio.svg | 673 +++++++++++++ docs/en/docs/img/deployment/https/https06.svg | 62 -- .../docs/img/deployment/https/https07.drawio | 203 ---- .../img/deployment/https/https07.drawio.svg | 540 +++++++++++ docs/en/docs/img/deployment/https/https07.svg | 62 -- .../docs/img/deployment/https/https08.drawio | 217 ----- .../img/deployment/https/https08.drawio.svg | 625 ++++++++++++ docs/en/docs/img/deployment/https/https08.svg | 62 -- .../bigger-applications/package.drawio | 43 - .../bigger-applications/package.drawio.svg | 420 ++++++++ .../tutorial/bigger-applications/package.svg | 1 - docs/en/docs/tutorial/bigger-applications.md | 4 +- docs/es/docs/deployment/concepts.md | 2 +- docs/es/docs/deployment/https.md | 18 +- docs/es/docs/tutorial/bigger-applications.md | 4 +- docs/ja/docs/deployment/concepts.md | 2 +- docs/ja/docs/deployment/https.md | 18 +- docs/pt/docs/deployment/concepts.md | 2 +- docs/pt/docs/deployment/https.md | 18 +- docs/pt/docs/tutorial/bigger-applications.md | 4 +- docs/ru/docs/deployment/concepts.md | 2 +- docs/ru/docs/deployment/https.md | 18 +- docs/ru/docs/tutorial/bigger-applications.md | 4 +- docs/zh/docs/deployment/concepts.md | 2 +- docs/zh/docs/deployment/https.md | 18 +- docs/zh/docs/tutorial/bigger-applications.md | 4 +- 56 files changed, 5707 insertions(+), 2368 deletions(-) delete mode 100644 docs/en/docs/img/deployment/concepts/process-ram.drawio create mode 100644 docs/en/docs/img/deployment/concepts/process-ram.drawio.svg delete mode 100644 docs/en/docs/img/deployment/concepts/process-ram.svg delete mode 100644 docs/en/docs/img/deployment/https/https.drawio create mode 100644 docs/en/docs/img/deployment/https/https.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https.svg delete mode 100644 docs/en/docs/img/deployment/https/https01.drawio create mode 100644 docs/en/docs/img/deployment/https/https01.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https01.svg delete mode 100644 docs/en/docs/img/deployment/https/https02.drawio create mode 100644 docs/en/docs/img/deployment/https/https02.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https02.svg delete mode 100644 docs/en/docs/img/deployment/https/https03.drawio create mode 100644 docs/en/docs/img/deployment/https/https03.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https03.svg delete mode 100644 docs/en/docs/img/deployment/https/https04.drawio create mode 100644 docs/en/docs/img/deployment/https/https04.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https04.svg delete mode 100644 docs/en/docs/img/deployment/https/https05.drawio create mode 100644 docs/en/docs/img/deployment/https/https05.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https05.svg delete mode 100644 docs/en/docs/img/deployment/https/https06.drawio create mode 100644 docs/en/docs/img/deployment/https/https06.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https06.svg delete mode 100644 docs/en/docs/img/deployment/https/https07.drawio create mode 100644 docs/en/docs/img/deployment/https/https07.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https07.svg delete mode 100644 docs/en/docs/img/deployment/https/https08.drawio create mode 100644 docs/en/docs/img/deployment/https/https08.drawio.svg delete mode 100644 docs/en/docs/img/deployment/https/https08.svg delete mode 100644 docs/en/docs/img/tutorial/bigger-applications/package.drawio create mode 100644 docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg delete mode 100644 docs/en/docs/img/tutorial/bigger-applications/package.svg diff --git a/docs/de/docs/deployment/concepts.md b/docs/de/docs/deployment/concepts.md index 97ad854e2..907598e54 100644 --- a/docs/de/docs/deployment/concepts.md +++ b/docs/de/docs/deployment/concepts.md @@ -216,7 +216,7 @@ Dieser Manager-Prozess wäre wahrscheinlich derjenige, welcher der IP am **Port* Diese Workerprozesse würden Ihre Anwendung ausführen, sie würden die Hauptberechnungen durchführen, um einen **Request** entgegenzunehmen und eine **Response** zurückzugeben, und sie würden alles, was Sie in Variablen einfügen, in den RAM laden. - + Und natürlich würden auf derselben Maschine neben Ihrer Anwendung wahrscheinlich auch **andere Prozesse** laufen. diff --git a/docs/de/docs/deployment/https.md b/docs/de/docs/deployment/https.md index 630582995..a216f44af 100644 --- a/docs/de/docs/deployment/https.md +++ b/docs/de/docs/deployment/https.md @@ -85,7 +85,7 @@ Zuerst würde der Browser mithilfe der **DNS-Server** herausfinden, welches die Die DNS-Server geben dem Browser eine bestimmte **IP-Adresse** zurück. Das wäre die von Ihrem Server verwendete öffentliche IP-Adresse, die Sie in den DNS-Servern konfiguriert haben. - + ### TLS-Handshake-Start @@ -93,7 +93,7 @@ Der Browser kommuniziert dann mit dieser IP-Adresse über **Port 443** (den HTTP Der erste Teil der Kommunikation besteht lediglich darin, die Verbindung zwischen dem Client und dem Server herzustellen und die zu verwendenden kryptografischen Schlüssel usw. zu vereinbaren. - + Diese Interaktion zwischen dem Client und dem Server zum Aufbau der TLS-Verbindung wird als **TLS-Handshake** bezeichnet. @@ -111,7 +111,7 @@ Mithilfe der oben beschriebenen **SNI-Erweiterung** würde der TLS-Terminierungs In diesem Fall würde er das Zertifikat für `someapp.example.com` verwenden. - + Der Client **vertraut** bereits der Entität, die das TLS-Zertifikat generiert hat (in diesem Fall Let's Encrypt, aber wir werden später mehr darüber erfahren), sodass er **verifizieren** kann, dass das Zertifikat gültig ist. @@ -133,19 +133,19 @@ Da Client und Server (sprich, der Browser und der TLS-Terminierungsproxy) nun ü Der Client sendet also einen **HTTPS-Request**. Das ist einfach ein HTTP-Request über eine verschlüsselte TLS-Verbindung. - + ### Den Request entschlüsseln Der TLS-Terminierungsproxy würde die vereinbarte Verschlüsselung zum **Entschlüsseln des Requests** verwenden und den **einfachen (entschlüsselten) HTTP-Request** an den Prozess weiterleiten, der die Anwendung ausführt (z. B. einen Prozess, bei dem Uvicorn die FastAPI-Anwendung ausführt). - + ### HTTP-Response Die Anwendung würde den Request verarbeiten und eine **einfache (unverschlüsselte) HTTP-Response** an den TLS-Terminierungsproxy senden. - + ### HTTPS-Response @@ -153,7 +153,7 @@ Der TLS-Terminierungsproxy würde dann die Response mithilfe der zuvor vereinbar Als Nächstes überprüft der Browser, ob die Response gültig und mit dem richtigen kryptografischen Schlüssel usw. verschlüsselt ist. Anschließend **entschlüsselt er die Response** und verarbeitet sie. - + Der Client (Browser) weiß, dass die Response vom richtigen Server kommt, da dieser die Kryptografie verwendet, die zuvor mit dem **HTTPS-Zertifikat** vereinbart wurde. @@ -163,7 +163,7 @@ Auf demselben Server (oder denselben Servern) könnten sich **mehrere Anwendunge Nur ein Prozess kann diese spezifische IP und den Port verarbeiten (in unserem Beispiel der TLS-Terminierungsproxy), aber die anderen Anwendungen/Prozesse können auch auf dem/den Server(n) ausgeführt werden, solange sie nicht versuchen, dieselbe **Kombination aus öffentlicher IP und Port** zu verwenden. - + Auf diese Weise könnte der TLS-Terminierungsproxy HTTPS und Zertifikate für **mehrere Domains**, für mehrere Anwendungen, verarbeiten und die Requests dann jeweils an die richtige Anwendung weiterleiten. @@ -173,7 +173,7 @@ Irgendwann in der Zukunft würde jedes Zertifikat **ablaufen** (etwa 3 Monate na Und dann gäbe es ein anderes Programm (in manchen Fällen ist es ein anderes Programm, in manchen Fällen ist es derselbe TLS-Terminierungsproxy), das mit Let's Encrypt kommuniziert und das/die Zertifikat(e) erneuert. - + Die **TLS-Zertifikate** sind **einem Domainnamen zugeordnet**, nicht einer IP-Adresse. diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md index 59e91bdcc..514e3fd3a 100644 --- a/docs/de/docs/tutorial/bigger-applications.md +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * Es gibt auch ein Unterverzeichnis `app/internal/` mit einer weiteren Datei `__init__.py`, es handelt sich also um ein weiteres „Python-Subpackage“: `app.internal`. * Und die Datei `app/internal/admin.py` ist ein weiteres Submodul: `app.internal.admin`. - + Die gleiche Dateistruktur mit Kommentaren: @@ -270,7 +270,7 @@ Aber diese Datei existiert nicht, unsere Abhängigkeiten befinden sich in einer Erinnern Sie sich, wie unsere Anwendungs-/Dateistruktur aussieht: - + --- diff --git a/docs/em/docs/deployment/concepts.md b/docs/em/docs/deployment/concepts.md index 019703296..bbb017277 100644 --- a/docs/em/docs/deployment/concepts.md +++ b/docs/em/docs/deployment/concepts.md @@ -216,7 +216,7 @@ 👈 👨‍🏭 🛠️ 🔜 🕐 🏃‍♂ 👆 🈸, 👫 🔜 🎭 👑 📊 📨 **📨** & 📨 **📨**, & 👫 🔜 📐 🕳 👆 🚮 🔢 💾. - + & ↗️, 🎏 🎰 🔜 🎲 ✔️ **🎏 🛠️** 🏃 👍, ↖️ ⚪️➡️ 👆 🈸. diff --git a/docs/em/docs/deployment/https.md b/docs/em/docs/deployment/https.md index 31cf99001..6d2641a92 100644 --- a/docs/em/docs/deployment/https.md +++ b/docs/em/docs/deployment/https.md @@ -85,7 +85,7 @@ 🏓 💽 🔜 💬 🖥 ⚙️ 🎯 **📢 📢**. 👈 🔜 📢 📢 📢 ⚙️ 👆 💽, 👈 👆 🔗 🏓 💽. - + ### 🤝 🤝 ▶️ @@ -93,7 +93,7 @@ 🥇 🍕 📻 🛠️ 🔗 🖖 👩‍💻 & 💽 & 💭 🔐 🔑 👫 🔜 ⚙️, ♒️. - + 👉 🔗 🖖 👩‍💻 & 💽 🛠️ 🤝 🔗 🤙 **🤝 🤝**. @@ -111,7 +111,7 @@ 👉 💼, ⚫️ 🔜 ⚙️ 📄 `someapp.example.com`. - + 👩‍💻 ⏪ **💙** 👨‍💼 👈 🏗 👈 🤝 📄 (👉 💼 ➡️ 🗜, ✋️ 👥 🔜 👀 🔃 👈 ⏪), ⚫️ 💪 **✔** 👈 📄 ☑. @@ -133,19 +133,19 @@ , 👩‍💻 📨 **🇺🇸🔍 📨**. 👉 🇺🇸🔍 📨 🔘 🗜 🤝 🔗. - + ### 🗜 📨 🤝 ❎ 🗳 🔜 ⚙️ 🔐 ✔ **🗜 📨**, & 🔜 📶 **✅ (🗜) 🇺🇸🔍 📨** 🛠️ 🏃 🈸 (🖼 🛠️ ⏮️ Uvicorn 🏃‍♂ FastAPI 🈸). - + ### 🇺🇸🔍 📨 🈸 🔜 🛠️ 📨 & 📨 **✅ (💽) 🇺🇸🔍 📨** 🤝 ❎ 🗳. - + ### 🇺🇸🔍 📨 @@ -153,7 +153,7 @@ ⏭, 🖥 🔜 ✔ 👈 📨 ☑ & 🗜 ⏮️ ▶️️ 🔐 🔑, ♒️. ⚫️ 🔜 ⤴️ **🗜 📨** & 🛠️ ⚫️. - + 👩‍💻 (🖥) 🔜 💭 👈 📨 👟 ⚪️➡️ ☑ 💽 ↩️ ⚫️ ⚙️ ⚛ 👫 ✔ ⚙️ **🇺🇸🔍 📄** ⏭. @@ -163,7 +163,7 @@ 🕴 1️⃣ 🛠️ 💪 🚚 🎯 📢 & ⛴ (🤝 ❎ 🗳 👆 🖼) ✋️ 🎏 🈸/🛠️ 💪 🏃 🔛 💽(Ⓜ) 💁‍♂️, 📏 👫 🚫 🔄 ⚙️ 🎏 **🌀 📢 📢 & ⛴**. - + 👈 🌌, 🤝 ❎ 🗳 💪 🍵 🇺🇸🔍 & 📄 **💗 🆔**, 💗 🈸, & ⤴️ 📶 📨 ▶️️ 🈸 🔠 💼. @@ -173,7 +173,7 @@ & ⤴️, 📤 🔜 ➕1️⃣ 📋 (💼 ⚫️ ➕1️⃣ 📋, 💼 ⚫️ 💪 🎏 🤝 ❎ 🗳) 👈 🔜 💬 ➡️ 🗜, & ♻ 📄(Ⓜ). - + **🤝 📄** **🔗 ⏮️ 🆔 📛**, 🚫 ⏮️ 📢 📢. diff --git a/docs/em/docs/tutorial/bigger-applications.md b/docs/em/docs/tutorial/bigger-applications.md index 68f506f27..78a321ae6 100644 --- a/docs/em/docs/tutorial/bigger-applications.md +++ b/docs/em/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * 📤 📁 `app/internal/` ⏮️ ➕1️⃣ 📁 `__init__.py`, ⚫️ ➕1️⃣ "🐍 📦": `app.internal`. * & 📁 `app/internal/admin.py` ➕1️⃣ 🔁: `app.internal.admin`. - + 🎏 📁 📊 ⏮️ 🏤: @@ -244,7 +244,7 @@ from .dependencies import get_token_header 💭 ❔ 👆 📱/📁 📊 👀 💖: - + --- diff --git a/docs/en/docs/deployment/concepts.md b/docs/en/docs/deployment/concepts.md index ed13bc28d..ed635a920 100644 --- a/docs/en/docs/deployment/concepts.md +++ b/docs/en/docs/deployment/concepts.md @@ -216,7 +216,7 @@ This Manager Process would probably be the one listening on the **port** in the Those worker processes would be the ones running your application, they would perform the main computations to receive a **request** and return a **response**, and they would load anything you put in variables in RAM. - + And of course, the same machine would probably have **other processes** running as well, apart from your application. diff --git a/docs/en/docs/deployment/https.md b/docs/en/docs/deployment/https.md index 46eda791e..8b4a08dbe 100644 --- a/docs/en/docs/deployment/https.md +++ b/docs/en/docs/deployment/https.md @@ -85,7 +85,7 @@ First, the browser would check with the **DNS servers** what is the **IP for the The DNS servers would tell the browser to use some specific **IP address**. That would be the public IP address used by your server, that you configured in the DNS servers. - + ### TLS Handshake Start @@ -93,7 +93,7 @@ The browser would then communicate with that IP address on **port 443** (the HTT The first part of the communication is just to establish the connection between the client and the server and to decide the cryptographic keys they will use, etc. - + This interaction between the client and the server to establish the TLS connection is called the **TLS handshake**. @@ -111,7 +111,7 @@ Using the **SNI extension** discussed above, the TLS Termination Proxy would che In this case, it would use the certificate for `someapp.example.com`. - + The client already **trusts** the entity that generated that TLS certificate (in this case Let's Encrypt, but we'll see about that later), so it can **verify** that the certificate is valid. @@ -133,19 +133,19 @@ Now that the client and server (specifically the browser and the TLS Termination So, the client sends an **HTTPS request**. This is just an HTTP request through an encrypted TLS connection. - + ### Decrypt the Request The TLS Termination Proxy would use the encryption agreed to **decrypt the request**, and would transmit the **plain (decrypted) HTTP request** to the process running the application (for example a process with Uvicorn running the FastAPI application). - + ### HTTP Response The application would process the request and send a **plain (unencrypted) HTTP response** to the TLS Termination Proxy. - + ### HTTPS Response @@ -153,7 +153,7 @@ The TLS Termination Proxy would then **encrypt the response** using the cryptogr Next, the browser would verify that the response is valid and encrypted with the right cryptographic key, etc. It would then **decrypt the response** and process it. - + The client (browser) will know that the response comes from the correct server because it is using the cryptography they agreed using the **HTTPS certificate** before. @@ -163,7 +163,7 @@ In the same server (or servers), there could be **multiple applications**, for e Only one process can be handling the specific IP and port (the TLS Termination Proxy in our example) but the other applications/processes can be running on the server(s) too, as long as they don't try to use the same **combination of public IP and port**. - + That way, the TLS Termination Proxy could handle HTTPS and certificates for **multiple domains**, for multiple applications, and then transmit the requests to the right application in each case. @@ -173,7 +173,7 @@ At some point in the future, each certificate would **expire** (about 3 months a And then, there would be another program (in some cases it's another program, in some cases it could be the same TLS Termination Proxy) that would talk to Let's Encrypt, and renew the certificate(s). - + The **TLS certificates** are **associated with a domain name**, not with an IP address. diff --git a/docs/en/docs/img/deployment/concepts/process-ram.drawio b/docs/en/docs/img/deployment/concepts/process-ram.drawio deleted file mode 100644 index b29c8a342..000000000 --- a/docs/en/docs/img/deployment/concepts/process-ram.drawio +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg b/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg new file mode 100644 index 000000000..a6a5c81d0 --- /dev/null +++ b/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + + + +
+
+
+ + + Server + + +
+
+
+
+ + Server + +
+
+
+ + + + + + + + + + +
+
+
+ + + RAM + +
+
+
+
+
+
+ + RAM + +
+
+
+ + + + + + + + + + +
+
+
+ + + CPU + +
+
+
+
+
+
+ + CPU + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + Process + + + + Manager + + +
+
+
+
+ + Process Manager + +
+
+
+ + + + + + + + + + +
+
+
+ + + Worker Process + + +
+
+
+
+ + Worker Process + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Worker Process + + +
+
+
+
+ + Worker Process + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Another Process + + +
+
+
+
+ + Another Process + +
+
+
+ + + + + + + + + + + + + + + + + + + +
+
+
+ + 1 GB + +
+
+
+
+ + 1 GB + +
+
+
+ + + + + + + +
+
+
+ + 1 GB + +
+
+
+
+ + 1 GB + +
+
+
+ + + + + + +
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/concepts/process-ram.svg b/docs/en/docs/img/deployment/concepts/process-ram.svg deleted file mode 100644 index c1bf0d589..000000000 --- a/docs/en/docs/img/deployment/concepts/process-ram.svg +++ /dev/null @@ -1,59 +0,0 @@ -
Server
Server
RAM
RAM -
CPU
CPU -
Process Manager
Process Manager
Worker Process
Worker Process
Worker Process
Worker Process
Another Process
Another Process
1 GB
1 GB
1 GB
1 GB
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https.drawio b/docs/en/docs/img/deployment/https/https.drawio deleted file mode 100644 index c4c8a3628..000000000 --- a/docs/en/docs/img/deployment/https/https.drawio +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https.drawio.svg b/docs/en/docs/img/deployment/https/https.drawio.svg new file mode 100644 index 000000000..c2a65b69f --- /dev/null +++ b/docs/en/docs/img/deployment/https/https.drawio.svg @@ -0,0 +1,907 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + Cert Renovation Program + +
+
+
+
+ + Cert Renovation Program + +
+
+
+ + + + + + + + + + + +
+
+
+ + Let's Encrypt + +
+
+
+
+ + Let's Encrypt + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Another app + + + : another.example.com + + +
+
+
+
+ + Another app: another.example.com + +
+
+
+ + + + + + + +
+
+
+ + + One more app + + + : onemore.example.com + + +
+
+
+
+ + One more app: onemore.example.com + +
+
+
+ + + + + + + +
+
+
+ + + A Database + + +
+
+
+
+ + A Database + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Renew HTTPS cert for: someapp.example.com + + +
+
+
+
+ + Renew HTTPS cert for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + New HTTPS cert for: someapp.example.com + + +
+
+
+
+ + New HTTPS cert for: someapp.example.com + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https.svg b/docs/en/docs/img/deployment/https/https.svg deleted file mode 100644 index 69497518a..000000000 --- a/docs/en/docs/img/deployment/https/https.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
Cert Renovation Program
Cert Renovation Program
Let's Encrypt
Let's Encrypt
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Another app: another.example.com
Another app: another.example.com
One more app: onemore.example.com
One more app: onemore.example.com
A Database
A Database
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
Renew HTTPS cert for: someapp.example.com
Renew HTTPS cert for: someapp.example.com
New HTTPS cert for: someapp.example.com
New HTTPS cert for: someapp.example.com
TLS Handshake
TLS Handshake
Encrypted response from: someapp.example.com
Encrypted response from: someapp.example.com
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https01.drawio b/docs/en/docs/img/deployment/https/https01.drawio deleted file mode 100644 index 181582f9b..000000000 --- a/docs/en/docs/img/deployment/https/https01.drawio +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https01.drawio.svg b/docs/en/docs/img/deployment/https/https01.drawio.svg new file mode 100644 index 000000000..ea128daf8 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https01.drawio.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https01.svg b/docs/en/docs/img/deployment/https/https01.svg deleted file mode 100644 index 2edbd0623..000000000 --- a/docs/en/docs/img/deployment/https/https01.svg +++ /dev/null @@ -1,57 +0,0 @@ -
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https02.drawio b/docs/en/docs/img/deployment/https/https02.drawio deleted file mode 100644 index 650c06d1e..000000000 --- a/docs/en/docs/img/deployment/https/https02.drawio +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https02.drawio.svg b/docs/en/docs/img/deployment/https/https02.drawio.svg new file mode 100644 index 000000000..c29d59356 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https02.drawio.svg @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https02.svg b/docs/en/docs/img/deployment/https/https02.svg deleted file mode 100644 index e16b7e94a..000000000 --- a/docs/en/docs/img/deployment/https/https02.svg +++ /dev/null @@ -1,57 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Port 443 (HTTPS)
Port 443 (HTTPS)
IP:
123.124.125.126
IP:...
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https03.drawio b/docs/en/docs/img/deployment/https/https03.drawio deleted file mode 100644 index c178fd363..000000000 --- a/docs/en/docs/img/deployment/https/https03.drawio +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https03.drawio.svg b/docs/en/docs/img/deployment/https/https03.drawio.svg new file mode 100644 index 000000000..6971e4c9c --- /dev/null +++ b/docs/en/docs/img/deployment/https/https03.drawio.svg @@ -0,0 +1,715 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https03.svg b/docs/en/docs/img/deployment/https/https03.svg deleted file mode 100644 index 2badd1c7d..000000000 --- a/docs/en/docs/img/deployment/https/https03.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
Port 443 (HTTPS)
Port 443 (HTTPS)
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https04.drawio b/docs/en/docs/img/deployment/https/https04.drawio deleted file mode 100644 index 78a6e919a..000000000 --- a/docs/en/docs/img/deployment/https/https04.drawio +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https04.drawio.svg b/docs/en/docs/img/deployment/https/https04.drawio.svg new file mode 100644 index 000000000..7e32bcdfe --- /dev/null +++ b/docs/en/docs/img/deployment/https/https04.drawio.svg @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https04.svg b/docs/en/docs/img/deployment/https/https04.svg deleted file mode 100644 index 4513ac76b..000000000 --- a/docs/en/docs/img/deployment/https/https04.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https05.drawio b/docs/en/docs/img/deployment/https/https05.drawio deleted file mode 100644 index 236ecd841..000000000 --- a/docs/en/docs/img/deployment/https/https05.drawio +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https05.drawio.svg b/docs/en/docs/img/deployment/https/https05.drawio.svg new file mode 100644 index 000000000..fed2fad16 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https05.drawio.svg @@ -0,0 +1,641 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https05.svg b/docs/en/docs/img/deployment/https/https05.svg deleted file mode 100644 index ddcd2760a..000000000 --- a/docs/en/docs/img/deployment/https/https05.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https06.drawio b/docs/en/docs/img/deployment/https/https06.drawio deleted file mode 100644 index 9dec13184..000000000 --- a/docs/en/docs/img/deployment/https/https06.drawio +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https06.drawio.svg b/docs/en/docs/img/deployment/https/https06.drawio.svg new file mode 100644 index 000000000..e0bd9bc6e --- /dev/null +++ b/docs/en/docs/img/deployment/https/https06.drawio.svg @@ -0,0 +1,673 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https06.svg b/docs/en/docs/img/deployment/https/https06.svg deleted file mode 100644 index 3695de40c..000000000 --- a/docs/en/docs/img/deployment/https/https06.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https07.drawio b/docs/en/docs/img/deployment/https/https07.drawio deleted file mode 100644 index aa8f4d6be..000000000 --- a/docs/en/docs/img/deployment/https/https07.drawio +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https07.drawio.svg b/docs/en/docs/img/deployment/https/https07.drawio.svg new file mode 100644 index 000000000..b74b33807 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https07.drawio.svg @@ -0,0 +1,540 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https07.svg b/docs/en/docs/img/deployment/https/https07.svg deleted file mode 100644 index 551354cef..000000000 --- a/docs/en/docs/img/deployment/https/https07.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Encrypted response from: someapp.example.com
Encrypted response from: someapp.example.com
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https08.drawio b/docs/en/docs/img/deployment/https/https08.drawio deleted file mode 100644 index 794b192df..000000000 --- a/docs/en/docs/img/deployment/https/https08.drawio +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https08.drawio.svg b/docs/en/docs/img/deployment/https/https08.drawio.svg new file mode 100644 index 000000000..8fc0b31ec --- /dev/null +++ b/docs/en/docs/img/deployment/https/https08.drawio.svg @@ -0,0 +1,625 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Another app + + + : another.example.com + + +
+
+
+
+ + Another app: another.example.com + +
+
+
+ + + + + + + +
+
+
+ + + One more app + + + : onemore.example.com + + +
+
+
+
+ + One more app: onemore.example.com + +
+
+
+ + + + + + + +
+
+
+ + + A Database + + +
+
+
+
+ + A Database + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https08.svg b/docs/en/docs/img/deployment/https/https08.svg deleted file mode 100644 index 2d4680dcc..000000000 --- a/docs/en/docs/img/deployment/https/https08.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Another app: another.example.com
Another app: another.example.com
One more app: onemore.example.com
One more app: onemore.example.com
A Database
A Database
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Encrypted response from: someapp.example.com
Encrypted response from: someapp.example.com
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.drawio b/docs/en/docs/img/tutorial/bigger-applications/package.drawio deleted file mode 100644 index cab3de2ca..000000000 --- a/docs/en/docs/img/tutorial/bigger-applications/package.drawio +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg b/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg new file mode 100644 index 000000000..7e28f4a68 --- /dev/null +++ b/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg @@ -0,0 +1,420 @@ + + + + + + + + + + + + + + + + +
+
+
+ + Package app +
+ app/__init__.py +
+
+
+
+
+ + Package app... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.main + +
+ + app/main.py + +
+
+
+
+
+ + Module app.main... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.dependencies + +
+ + app/dependencies.py + +
+
+
+
+
+ + Module app.dependencies... + +
+
+
+ + + + + + + + + + +
+
+
+ + + Subpackage app.internal +
+
+ + app/internal/__init__.py + +
+ +
+
+
+
+
+
+ + Subpackage app.internal... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.internal.admin + +
+ + app/internal/admin.py + +
+
+
+
+
+ + Module app.internal.admin... + +
+
+
+ + + + + + + + + + +
+
+
+ + + Subpackage app.routers +
+ app/routers/__init__.py +
+
+
+
+
+
+
+ + Subpackage app.routers... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.routers.items + +
+ + app/routers/items.py + +
+
+
+
+
+ + Module app.routers.items... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.routers.users + +
+ + app/routers/users.py + +
+
+
+
+
+ + Module app.routers.users... + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.svg b/docs/en/docs/img/tutorial/bigger-applications/package.svg deleted file mode 100644 index 44da1dc30..000000000 --- a/docs/en/docs/img/tutorial/bigger-applications/package.svg +++ /dev/null @@ -1 +0,0 @@ -
Package app
app/__init__.py
Package app...
Module app.main
app/main.py
Module app.main...
Module app.dependencies
app/dependencies.py
Module app.dependencies...
Subpackage app.internal
app/internal/__init__.py
Subpackage app.internal...
Module app.internal.admin
app/internal/admin.py
Module app.internal.admin...
Subpackage app.routers
app/routers/__init__.py
Subpackage app.routers...
Module app.routers.items
app/routers/items.py
Module app.routers.items...
Module app.routers.users
app/routers/users.py
Module app.routers.users...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/tutorial/bigger-applications.md b/docs/en/docs/tutorial/bigger-applications.md index 605ced0d3..f5f29a173 100644 --- a/docs/en/docs/tutorial/bigger-applications.md +++ b/docs/en/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * There's also a subdirectory `app/internal/` with another file `__init__.py`, so it's another "Python subpackage": `app.internal`. * And the file `app/internal/admin.py` is another submodule: `app.internal.admin`. - + The same file structure with comments: @@ -270,7 +270,7 @@ But that file doesn't exist, our dependencies are in a file at `app/dependencies Remember how our app/file structure looks like: - + --- diff --git a/docs/es/docs/deployment/concepts.md b/docs/es/docs/deployment/concepts.md index f5725c5dc..bcc7948bc 100644 --- a/docs/es/docs/deployment/concepts.md +++ b/docs/es/docs/deployment/concepts.md @@ -216,7 +216,7 @@ Este Proceso Administrador probablemente sería el que escuche en el **puerto** Esos worker processes serían los que ejecutan tu aplicación, realizarían los cálculos principales para recibir un **request** y devolver un **response**, y cargarían cualquier cosa que pongas en variables en RAM. - + Y por supuesto, la misma máquina probablemente tendría **otros procesos** ejecutándose también, aparte de tu aplicación. diff --git a/docs/es/docs/deployment/https.md b/docs/es/docs/deployment/https.md index f2871ac03..3ccb5dc47 100644 --- a/docs/es/docs/deployment/https.md +++ b/docs/es/docs/deployment/https.md @@ -85,7 +85,7 @@ Primero, el navegador consultaría con los **servidores DNS** cuál es la **IP d Los servidores DNS le dirían al navegador que use una **dirección IP** específica. Esa sería la dirección IP pública utilizada por tu servidor, que configuraste en los servidores DNS. - + ### Inicio del Handshake TLS @@ -93,7 +93,7 @@ El navegador luego se comunicaría con esa dirección IP en el **puerto 443** (e La primera parte de la comunicación es solo para establecer la conexión entre el cliente y el servidor y decidir las claves criptográficas que usarán, etc. - + Esta interacción entre el cliente y el servidor para establecer la conexión TLS se llama **handshake TLS**. @@ -111,7 +111,7 @@ Usando la **extensión SNI** discutida anteriormente, el TLS Termination Proxy v En este caso, usaría el certificado para `someapp.example.com`. - + El cliente ya **confía** en la entidad que generó ese certificado TLS (en este caso Let's Encrypt, pero lo veremos más adelante), por lo que puede **verificar** que el certificado sea válido. @@ -133,19 +133,19 @@ Ahora que el cliente y el servidor (específicamente el navegador y el TLS Termi Así que, el cliente envía un **request HTTPS**. Esto es simplemente un request HTTP a través de una conexión TLS encriptada. - + ### Desencriptar el Request El TLS Termination Proxy usaría la encriptación acordada para **desencriptar el request**, y transmitiría el **request HTTP simple (desencriptado)** al proceso que ejecuta la aplicación (por ejemplo, un proceso con Uvicorn ejecutando la aplicación FastAPI). - + ### Response HTTP La aplicación procesaría el request y enviaría un **response HTTP simple (sin encriptar)** al TLS Termination Proxy. - + ### Response HTTPS @@ -153,7 +153,7 @@ El TLS Termination Proxy entonces **encriptaría el response** usando la criptog Luego, el navegador verificaría que el response sea válido y encriptado con la clave criptográfica correcta, etc. Entonces **desencriptaría el response** y lo procesaría. - + El cliente (navegador) sabrá que el response proviene del servidor correcto porque está utilizando la criptografía que acordaron usando el **certificado HTTPS** anteriormente. @@ -163,7 +163,7 @@ En el mismo servidor (o servidores), podrían haber **múltiples aplicaciones**, Solo un proceso puede estar gestionando la IP y puerto específica (el TLS Termination Proxy en nuestro ejemplo) pero las otras aplicaciones/procesos pueden estar ejecutándose en el/los servidor(es) también, siempre y cuando no intenten usar la misma **combinación de IP pública y puerto**. - + De esa manera, el TLS Termination Proxy podría gestionar HTTPS y certificados para **múltiples dominios**, para múltiples aplicaciones, y luego transmitir los requests a la aplicación correcta en cada caso. @@ -173,7 +173,7 @@ En algún momento en el futuro, cada certificado **expiraría** (alrededor de 3 Y entonces, habría otro programa (en algunos casos es otro programa, en algunos casos podría ser el mismo TLS Termination Proxy) que hablaría con Let's Encrypt y renovaría el/los certificado(s). - + Los **certificados TLS** están **asociados con un nombre de dominio**, no con una dirección IP. diff --git a/docs/es/docs/tutorial/bigger-applications.md b/docs/es/docs/tutorial/bigger-applications.md index 78165ef05..c3d8f0686 100644 --- a/docs/es/docs/tutorial/bigger-applications.md +++ b/docs/es/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * También hay un subdirectorio `app/internal/` con otro archivo `__init__.py`, por lo que es otro "subpaquete de Python": `app.internal`. * Y el archivo `app/internal/admin.py` es otro submódulo: `app.internal.admin`. - + La misma estructura de archivos con comentarios: @@ -270,7 +270,7 @@ Pero ese archivo no existe, nuestras dependencias están en un archivo en `app/d Recuerda cómo se ve nuestra estructura de aplicación/archivo: - + --- diff --git a/docs/ja/docs/deployment/concepts.md b/docs/ja/docs/deployment/concepts.md index c6b21fd1b..a0d4fb35b 100644 --- a/docs/ja/docs/deployment/concepts.md +++ b/docs/ja/docs/deployment/concepts.md @@ -219,7 +219,7 @@ FastAPI アプリケーションでは、Uvicorn のようなサーバープロ これらのワーカー・プロセスは、アプリケーションを実行するものであり、**リクエスト**を受けて**レスポンス**を返すための主要な計算を行い、あなたが変数に入れたものは何でもRAMにロードします。 - + そしてもちろん、同じマシンでは、あなたのアプリケーションとは別に、**他のプロセス**も実行されているでしょう。 diff --git a/docs/ja/docs/deployment/https.md b/docs/ja/docs/deployment/https.md index ac40b0982..7b0f567aa 100644 --- a/docs/ja/docs/deployment/https.md +++ b/docs/ja/docs/deployment/https.md @@ -92,7 +92,7 @@ DNSサーバーでは、**取得したドメイン**をあなたのサーバー DNSサーバーは、ブラウザに特定の**IPアドレス**を使用するように指示します。このIPアドレスは、DNSサーバーで設定した、あなたのサーバーが使用するパブリックIPアドレスになります。 - + ### TLS Handshake の開始 @@ -100,7 +100,7 @@ DNSサーバーは、ブラウザに特定の**IPアドレス**を使用する 通信の最初の部分は、クライアントとサーバー間の接続を確立し、使用する暗号鍵などを決めるだけです。 - + TLS接続を確立するためのクライアントとサーバー間のこのやりとりは、**TLSハンドシェイク**と呼ばれます。 @@ -120,7 +120,7 @@ TLS Termination Proxyは、1つ以上の**TLS証明書**(HTTPS証明書)に 今回は、`someapp.example.com`の証明書を使うことになります。 - + クライアントは、そのTLS証明書を生成したエンティティ(この場合はLet's Encryptですが、これについては後述します)をすでに**信頼**しているため、その証明書が有効であることを**検証**することができます。 @@ -142,19 +142,19 @@ TLS Termination Proxyは、1つ以上の**TLS証明書**(HTTPS証明書)に そこで、クライアントは**HTTPSリクエスト**を送信します。これは、暗号化されたTLSコネクションを介した単なるHTTPリクエストです。 - + ### リクエストの復号化 TLS Termination Proxy は、合意が取れている暗号化を使用して、**リクエストを復号化**し、**プレーン (復号化された) HTTP リクエスト** をアプリケーションを実行しているプロセス (例えば、FastAPI アプリケーションを実行している Uvicorn を持つプロセス) に送信します。 - + ### HTTP レスポンス アプリケーションはリクエストを処理し、**プレーン(暗号化されていない)HTTPレスポンス** をTLS Termination Proxyに送信します。 - + ### HTTPS レスポンス @@ -162,7 +162,7 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap その後ブラウザでは、レスポンスが有効で正しい暗号キーで暗号化されていることなどを検証します。そして、ブラウザはレスポンスを**復号化**して処理します。 - + クライアント(ブラウザ)は、レスポンスが正しいサーバーから来たことを知ることができます。 なぜなら、そのサーバーは、以前に**HTTPS証明書**を使って合意した暗号を使っているからです。 @@ -172,7 +172,7 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap 特定のIPとポート(この例ではTLS Termination Proxy)を扱うことができるのは1つのプロセスだけですが、他のアプリケーション/プロセスも、同じ**パブリックIPとポート**の組み合わせを使用しようとしない限り、サーバー上で実行することができます。 - + そうすれば、TLS Termination Proxy は、**複数のドメイン**や複数のアプリケーションのHTTPSと証明書を処理し、それぞれのケースで適切なアプリケーションにリクエストを送信することができます。 @@ -182,7 +182,7 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap その後、Let's Encryptと通信する別のプログラム(別のプログラムである場合もあれば、同じTLS Termination Proxyである場合もある)によって、証明書を更新します。 - + **TLS証明書**は、IPアドレスではなく、**ドメイン名に関連付けられて**います。 diff --git a/docs/pt/docs/deployment/concepts.md b/docs/pt/docs/deployment/concepts.md index 8cf70d0b4..014ca3797 100644 --- a/docs/pt/docs/deployment/concepts.md +++ b/docs/pt/docs/deployment/concepts.md @@ -216,7 +216,7 @@ Este Processo de Gerenciador provavelmente seria o que escutaria na **porta** no Esses processos de trabalho seriam aqueles que executariam seu aplicativo, eles executariam os cálculos principais para receber uma **solicitação** e retornar uma **resposta**, e carregariam qualquer coisa que você colocasse em variáveis ​​na RAM. - + E, claro, a mesma máquina provavelmente teria **outros processos** em execução, além do seu aplicativo. diff --git a/docs/pt/docs/deployment/https.md b/docs/pt/docs/deployment/https.md index 9ad419934..904d04eaa 100644 --- a/docs/pt/docs/deployment/https.md +++ b/docs/pt/docs/deployment/https.md @@ -85,7 +85,7 @@ Primeiro, o navegador iria verificar com os **servidores DNS** qual o **IP do do Os servidores DNS iriam informar o navegador para utilizar algum **endereço IP** específico. Esse seria o endereço IP público em uso no seu servidor, que você configurou nos servidores DNS. - + ### Início do Handshake TLS @@ -93,7 +93,7 @@ O navegador então irá comunicar-se com esse endereço IP na **porta 443** (a p A primeira parte dessa comunicação é apenas para estabelecer a conexão entre o cliente e o servidor e para decidir as chaves criptográficas a serem utilizadas, etc. - + Esse interação entre o cliente e o servidor para estabelecer uma conexão TLS é chamada de **Handshake TLS**. @@ -111,7 +111,7 @@ Utilizando a **extensão SNI** discutida acima, o Proxy de Terminação TLS iria Nesse caso, ele usaria o certificado para `someapp.example.com`. - + O cliente já **confia** na entidade que gerou o certificado TLS (nesse caso, o Let's Encrypt, mas veremos sobre isso mais tarde), então ele pode **verificar** que o certificado é válido. @@ -133,19 +133,19 @@ Agora que o cliente e servidor (especialmente o navegador e o Proxy de Terminaç Então, o cliente envia uma **solicitação HTTPS**. Que é apenas uma solicitação HTTP sobre uma conexão TLS encriptada. - + ### Desencriptando a Solicitação O Proxy de Terminação TLS então usaria a encriptação combinada para **desencriptar a solicitação**, e transmitiria a **solicitação básica (desencriptada)** para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI). - + ### Resposta HTTP A aplicação processaria a solicitação e retornaria uma **resposta HTTP básica (não encriptada)** para o Proxy de Terminação TLS. - + ### Resposta HTTPS @@ -153,7 +153,7 @@ O Proxy de Terminação TLS iria **encriptar a resposta** utilizando a criptogra No próximo passo, o navegador verifica que a resposta é válida e encriptada com a chave criptográfica correta, etc. E depois **desencripta a resposta** e a processa. - + O cliente (navegador) saberá que a resposta vem do servidor correto por que ela usa a criptografia que foi combinada entre eles usando o **certificado HTTPS** anterior. @@ -163,7 +163,7 @@ Podem existir **múltiplas aplicações** em execução no mesmo servidor (ou se Apenas um processo pode estar vinculado a um IP e porta (o Proxy de Terminação TLS, por exemplo), mas outras aplicações/processos também podem estar em execução no(s) servidor(es), desde que não tentem usar a mesma **combinação de IP público e porta**. - + Dessa forma, o Proxy de Terminação TLS pode gerenciar o HTTPS e os certificados de **múltiplos domínios**, para múltiplas aplicações, e então transmitir as requisições para a aplicação correta em cada caso. @@ -173,7 +173,7 @@ Em algum momento futuro, cada certificado irá **expirar** (aproximadamente 3 me E então, haverá outro programa (em alguns casos pode ser o próprio Proxy de Terminação TLS) que irá interagir com o Let's Encrypt e renovar o(s) certificado(s). - + Os **certificados TLS** são **associados com um nome de domínio**, e não a um endereço IP. diff --git a/docs/pt/docs/tutorial/bigger-applications.md b/docs/pt/docs/tutorial/bigger-applications.md index a094005fd..b621f3c72 100644 --- a/docs/pt/docs/tutorial/bigger-applications.md +++ b/docs/pt/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * Há também um subdiretório `app/internal/` com outro arquivo `__init__.py`, então ele é outro "subpacote Python":`app.internal`. * E o arquivo `app/internal/admin.py` é outro submódulo: `app.internal.admin`. - + A mesma estrutura de arquivos com comentários: @@ -270,7 +270,7 @@ Mas esse arquivo não existe, nossas dependências estão em um arquivo em `app/ Lembre-se de como nossa estrutura app/file se parece: - + --- diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md index 7cdc29526..acfa1f4fe 100644 --- a/docs/ru/docs/deployment/concepts.md +++ b/docs/ru/docs/deployment/concepts.md @@ -216,7 +216,7 @@ Каждый из этих процессов будет запускать ваше приложение для обработки полученного **запроса** и возвращения вычисленного **ответа** и они будут использовать оперативную память. - + Безусловно, на этом же сервере будут работать и **другие процессы**, которые не относятся к вашему приложению. diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md index 85c4cce60..d8877a9a1 100644 --- a/docs/ru/docs/deployment/https.md +++ b/docs/ru/docs/deployment/https.md @@ -92,7 +92,7 @@ DNS-сервера присылают браузеру определённый **IP-адрес**, тот самый публичный IP-адрес вашего сервера, который вы указали в ресурсной "записи А" при настройке. - + ### Рукопожатие TLS @@ -100,7 +100,7 @@ DNS-сервера присылают браузеру определённый Первым шагом будет установление соединения между клиентом (браузером) и сервером и выбор криптографического ключа (для шифрования). - + Эта часть клиент-серверного взаимодействия устанавливает TLS-соединение и называется **TLS-рукопожатием**. @@ -118,7 +118,7 @@ DNS-сервера присылают браузеру определённый То есть будет выбран сертификат для домена `someapp.example.com`. - + Клиент уже **доверяет** тому, кто выдал этот TLS-сертификат (в нашем случае - Let's Encrypt, но мы ещё обсудим это), потому может **проверить**, действителен ли полученный от сервера сертификат. @@ -140,19 +140,19 @@ DNS-сервера присылают браузеру определённый Так клиент отправляет **HTTPS-запрос**. То есть обычный HTTP-запрос, но через зашифрованное TLS-содинение. - + ### Расшифровка запроса Прокси-сервер, используя согласованный с клиентом ключ, расшифрует полученный **зашифрованный запрос** и передаст **обычный (незашифрованный) HTTP-запрос** процессу, запускающему приложение (например, процессу Uvicorn запускающему приложение FastAPI). - + ### HTTP-ответ Приложение обработает запрос и вернёт **обычный (незашифрованный) HTTP-ответ** прокси-серверу. - + ### HTTPS-ответ @@ -160,7 +160,7 @@ DNS-сервера присылают браузеру определённый Наконец, браузер проверит ответ, в том числе, что тот зашифрован с нужным ключом, **расшифрует его** и обработает. - + Клиент (браузер) знает, что ответ пришёл от правильного сервера, так как использует методы шифрования, согласованные ими раннее через **HTTPS-сертификат**. @@ -171,7 +171,7 @@ DNS-сервера присылают браузеру определённый Напомню, что только один процесс (например, прокси-сервер) может прослушивать определённый порт определённого IP-адреса. Но другие процессы и приложения тоже могут работать на этом же сервере (серверах), если они не пытаются использовать уже занятую **комбинацию IP-адреса и порта** (сокет). - + Таким образом, сервер завершения TLS может обрабатывать HTTPS-запросы и использовать сертификаты для **множества доменов** или приложений и передавать запросы правильным адресатам (другим приложениям). @@ -181,7 +181,7 @@ DNS-сервера присылают браузеру определённый Когда это произойдёт, можно запустить другую программу, которая подключится к Let's Encrypt и обновит сертификат(ы). Существуют прокси-серверы, которые могут сделать это действие самостоятельно. - + **TLS-сертификаты** не привязаны к IP-адресу, но **связаны с именем домена**. diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md index 7c3dc288f..8b9080d39 100644 --- a/docs/ru/docs/tutorial/bigger-applications.md +++ b/docs/ru/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * Подкаталог `app/internal/`, содержащий файл `__init__.py`, является ещё одним суб-пакетом: `app.internal`. * А файл `app/internal/admin.py` является ещё одним суб-модулем: `app.internal.admin`. - + Та же самая файловая структура приложения, но с комментариями: @@ -269,7 +269,7 @@ from .dependencies import get_token_header Вспомните, как выглядит файловая структура нашего приложения: - + --- diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md index 7a0b6c3d2..f7208da7c 100644 --- a/docs/zh/docs/deployment/concepts.md +++ b/docs/zh/docs/deployment/concepts.md @@ -220,7 +220,7 @@ 这些工作进程将是运行您的应用程序的进程,它们将执行主要计算以接收 **请求** 并返回 **响应**,并且它们将加载您放入 RAM 中的变量中的任何内容。 - + 当然,除了您的应用程序之外,同一台机器可能还运行**其他进程**。 diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md index 9c963d587..d994c4add 100644 --- a/docs/zh/docs/deployment/https.md +++ b/docs/zh/docs/deployment/https.md @@ -86,7 +86,7 @@ DNS 服务器会告诉浏览器使用某个特定的 **IP 地址**。 这将是你在 DNS 服务器中为你的服务器配置的公共 IP 地址。 - + ### TLS 握手开始 @@ -94,7 +94,7 @@ DNS 服务器会告诉浏览器使用某个特定的 **IP 地址**。 这将是 通信的第一部分只是建立客户端和服务器之间的连接并决定它们将使用的加密密钥等。 - + 客户端和服务器之间建立 TLS 连接的过程称为 **TLS 握手**。 @@ -112,7 +112,7 @@ TLS 终止代理可以访问一个或多个 **TLS 证书**(HTTPS 证书)。 在这种情况下,它将使用`someapp.example.com`的证书。 - + 客户端已经**信任**生成该 TLS 证书的实体(在本例中为 Let's Encrypt,但我们稍后会看到),因此它可以**验证**该证书是否有效。 @@ -134,19 +134,19 @@ TLS 终止代理可以访问一个或多个 **TLS 证书**(HTTPS 证书)。 接下来,客户端发送一个 **HTTPS 请求**。 这其实只是一个通过 TLS 加密连接的 HTTP 请求。 - + ### 解密请求 TLS 终止代理将使用协商好的加密算法**解密请求**,并将**(解密的)HTTP 请求**传输到运行应用程序的进程(例如运行 FastAPI 应用的 Uvicorn 进程)。 - + ### HTTP 响应 应用程序将处理请求并向 TLS 终止代理发送**(未加密)HTTP 响应**。 - + ### HTTPS 响应 @@ -154,7 +154,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 接下来,浏览器将验证响应是否有效和是否使用了正确的加密密钥等。然后它会**解密响应**并处理它。 - + 客户端(浏览器)将知道响应来自正确的服务器,因为它使用了他们之前使用 **HTTPS 证书** 协商出的加密算法。 @@ -164,7 +164,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 只有一个进程可以处理特定的 IP 和端口(在我们的示例中为 TLS 终止代理),但其他应用程序/进程也可以在服务器上运行,只要它们不尝试使用相同的 **公共 IP 和端口的组合**。 - + 这样,TLS 终止代理就可以为多个应用程序处理**多个域名**的 HTTPS 和证书,然后在每种情况下将请求传输到正确的应用程序。 @@ -174,7 +174,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 然后,会有另一个程序(在某些情况下是另一个程序,在某些情况下可能是同一个 TLS 终止代理)与 Let's Encrypt 通信并更新证书。 - + **TLS 证书** **与域名相关联**,而不是与 IP 地址相关联。 diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md index 318e10fd7..554bc654f 100644 --- a/docs/zh/docs/tutorial/bigger-applications.md +++ b/docs/zh/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * 还有一个子目录 `app/internal/` 包含另一个 `__init__.py` 文件,因此它是又一个「Python 子包」:`app.internal`。 * `app/internal/admin.py` 是另一个子模块:`app.internal.admin`。 - + 带有注释的同一文件结构: @@ -244,7 +244,7 @@ from .dependencies import get_token_header 请记住我们的程序/文件结构是怎样的: - + --- From ea7b1054762c72a79bc111e747e20d4c67721afc Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 11 May 2025 13:37:47 +0000 Subject: [PATCH 109/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0a1293e9f..f931fafff 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Docs +* 🍱 Update Drawio diagrams SVGs, single file per diagram, sans-serif font. PR [#13706](https://github.com/fastapi/fastapi/pull/13706) by [@tiangolo](https://github.com/tiangolo). * 📝 Update docs for "Help FastAPI", simplify and reduce "sponsor" section. PR [#13670](https://github.com/fastapi/fastapi/pull/13670) by [@tiangolo](https://github.com/tiangolo). * 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc). * ✏️ Fix syntax error in `docs/en/docs/tutorial/handling-errors.md`. PR [#13623](https://github.com/fastapi/fastapi/pull/13623) by [@gsheni](https://github.com/gsheni). From be0cf41d38e1f9b56f45ce8586d1336c2983ae84 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 18:02:28 +0200 Subject: [PATCH 110/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13711)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.8 → v0.11.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.8...v0.11.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2a688e2b4..2c7cee518 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.8 + rev: v0.11.10 hooks: - id: ruff args: From 4d1c69751eebeba3db591ccdd52b690d1ebd0878 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 20 May 2025 16:02:48 +0000 Subject: [PATCH 111/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f931fafff..ace8cb045 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -32,6 +32,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13711](https://github.com/fastapi/fastapi/pull/13711) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🔧 Update sponsors: add Subtotal. PR [#13701](https://github.com/fastapi/fastapi/pull/13701) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove deepset / Haystack. PR [#13700](https://github.com/fastapi/fastapi/pull/13700) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13688](https://github.com/fastapi/fastapi/pull/13688) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 7382ceda579e73776df0ea71cb76adefdcb21d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 21 May 2025 17:17:03 +0200 Subject: [PATCH 112/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20rem?= =?UTF-8?q?ove=20MongoDB=20(#13725)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - docs/en/data/sponsors.yml | 3 --- docs/en/overrides/main.html | 6 ------ 3 files changed, 10 deletions(-) diff --git a/README.md b/README.md index d668babbb..96809127d 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index a46fd03f5..9c57dad0e 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -14,9 +14,6 @@ gold: - url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge title: Auth, user management and more for your B2B product img: https://fastapi.tiangolo.com/img/sponsors/propelauth.png - - url: https://www.mongodb.com/developer/languages/python/python-quickstart-fastapi/?utm_campaign=fastapi_framework&utm_source=fastapi_sponsorship&utm_medium=web_referral - title: Simplify Full Stack Development with FastAPI & MongoDB - img: https://fastapi.tiangolo.com/img/sponsors/mongodb.png - url: https://zuplo.link/fastapi-gh title: 'Zuplo: Deploy, Secure, Document, and Monetize your FastAPI' img: https://fastapi.tiangolo.com/img/sponsors/zuplo.png diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 9d985ea87..89c8171d0 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -56,12 +56,6 @@ -
From 0e1ec488856b18da719f97a0da94004094f69465 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 21 May 2025 15:17:32 +0000 Subject: [PATCH 113/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ace8cb045..654c5c013 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -32,6 +32,7 @@ hide: ### Internal +* 🔧 Update sponsors: remove MongoDB. PR [#13725](https://github.com/fastapi/fastapi/pull/13725) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13711](https://github.com/fastapi/fastapi/pull/13711) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🔧 Update sponsors: add Subtotal. PR [#13701](https://github.com/fastapi/fastapi/pull/13701) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove deepset / Haystack. PR [#13700](https://github.com/fastapi/fastapi/pull/13700) by [@tiangolo](https://github.com/tiangolo). From a01a665b5723aef8613d269ccb7d8d77b6ecd678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 22 May 2025 11:18:52 +0200 Subject: [PATCH 114/455] =?UTF-8?q?=F0=9F=94=A7=20Remove=20Google=20Analyt?= =?UTF-8?q?ics=20(#13727)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/mkdocs.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 48b7fd8a0..8a5ea13e0 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -289,20 +289,6 @@ markdown_extensions: mdx_include: null markdown_include_variants: null extra: - analytics: - provider: google - property: G-YNEVN69SC3 - feedback: - title: Was this page helpful? - ratings: - - icon: material/emoticon-happy-outline - name: This page was helpful - data: 1 - note: Thanks for your feedback! - - icon: material/emoticon-sad-outline - name: This page could be improved - data: 0 - note: Thanks for your feedback! social: - icon: fontawesome/brands/github-alt link: https://github.com/fastapi/fastapi From bcb7935ab78e1e31c7f201e264b5b17a5772a3f0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 22 May 2025 09:19:16 +0000 Subject: [PATCH 115/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 654c5c013..69124c29e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -32,6 +32,7 @@ hide: ### Internal +* 🔧 Remove Google Analytics. PR [#13727](https://github.com/fastapi/fastapi/pull/13727) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove MongoDB. PR [#13725](https://github.com/fastapi/fastapi/pull/13725) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13711](https://github.com/fastapi/fastapi/pull/13711) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🔧 Update sponsors: add Subtotal. PR [#13701](https://github.com/fastapi/fastapi/pull/13701) by [@tiangolo](https://github.com/tiangolo). From 29ed7d052b58f32444ff14ae299de365262fcc56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 22 May 2025 11:45:32 +0200 Subject: [PATCH 116/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20Add?= =?UTF-8?q?=20InterviewPal=20(#13728)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/en/data/sponsors.yml | 3 +++ docs/en/data/sponsors_badge.yml | 4 ++++ docs/en/docs/img/sponsors/interviewpal.png | Bin 0 -> 25890 bytes 4 files changed, 8 insertions(+) create mode 100644 docs/en/docs/img/sponsors/interviewpal.png diff --git a/README.md b/README.md index 96809127d..78ae6b10e 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 9c57dad0e..14a1f3cf3 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -45,6 +45,9 @@ silver: - url: https://www.permit.io/blog/implement-authorization-in-fastapi?utm_source=github&utm_medium=referral&utm_campaign=fastapi title: Fine-Grained Authorization for FastAPI img: https://fastapi.tiangolo.com/img/sponsors/permit.png + - url: https://www.interviewpal.com/?utm_source=fastapi&utm_medium=open-source&utm_campaign=dev-hiring + title: InterviewPal - AI Interview Coach for Engineers and Devs + img: https://fastapi.tiangolo.com/img/sponsors/interviewpal.png bronze: - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source title: Biosecurity risk assessments made easy. diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index d507a500f..fd34019b3 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -38,3 +38,7 @@ logins: - render-sponsorships - renderinc - stainless-api + - snapit-cypher + - coderabbitai + - permitio + - LambdaTest-Inc diff --git a/docs/en/docs/img/sponsors/interviewpal.png b/docs/en/docs/img/sponsors/interviewpal.png new file mode 100644 index 0000000000000000000000000000000000000000..e40ed01fd4f9c0b41183fb2f9cb5291985348e9e GIT binary patch literal 25890 zcmeFYRa7L+)-77NOXKeD(73z1JB_=$Hx7lnyKCdFjk`>$clf&qRL;#>#yAe8uIJ4wV-SG>k#Ut zs_CL^=uYI|WN&6^V@l-W>0nA^>S1XH0C=pb#mvI=GC_-eW*3lRv6*lr%`Yo*9MGTOqqcc&M^(dGSYmLfwzO|z-H~CY<0#U%V#@)F5Sq2Qf zJd6Q?g_*QxRnTxXKt`()uo;EiU+H}EpA*U>No~<7n=%J}2LNCpEx&rCDJRQqY;Vh8 zXku?<%HUz^@YPiSfLFl7!O+;+)P=~%)ZEgJkL0SOhlI$|gpWjnO^!**3`w2$ivpg&Y9bTkL15_xxe23^ED$0(SNzPSo4u+ z$|(|w*gKgLu`;kSFwu*7Sh}&0@WT@EI+>VpD~pQ%55(6eJ`xKT7YA-eMt6622KVm_ z_D<%E%v@Ytj7%(yEG+b29`w$hb}oh<^mfjq|3LgVhN!8tv6H2Pi>19C(Lb1mM)s~Q zd?X}acB20Q|A+nmgKp>iKO}t7!T67bk(q&s@&9&ru{8UCasS8iFZX{Mb1PbUnA&KH zTH2c0Ie&G5kA#Jl>A%4KW!3t>tjtXRZT$y{TgukZ+*HHT#Kq!Y&HiPOHMKMU$MXMZ zqTpm{`o+ONSNmllVf=?l#{Z%6D>97#Cp7=?^Z)(!pOgGs9RG)||IqbsG4O9W|3_W_ zq3hpb;NNookGlTakkY<({Rd;mY{&p0jo+&p221Xf~Q~uo>CgYGj-lj3W(O^o@u(pjSrHgUquhn5=Q; zcTj4t_kjFQ2?Q(-8{_rNVERf;J<@3L41VWVzO%<+%Z_Xwxe z$$Huy5G$R`2B7g;VV*no5UDzMV7K|FVURP}boA zrmbZLJ4r8zrZXE~c$r7CVIfE*;1 zU|!P6wrI%yDH;JrRQ10DN747VB)wBKjASg0BbH=5|$b>)odg z8rw`xal$Ny3+xJ*9z32p^i=q$$|fQY-!#p;Z9kyTBXO;xD&U9_F=H$KSiDdJ+swQKs2{jHGU}2=Ut!a#5-Du|=t|W(nk~wMyFex=O3S*iKI1BkUzD0_HFzb-UZ_cL`b$cw_ zrR1!cq;jxb-<8+ojE7g2)T~?bcV$Hu7Xbq-byOQki7VMr`((9~Fm=toI3u#)B{RYx z5Ox5{?p&~23|pQOD@V=^{*B`17JhuZe29T`GXvPPIU}B87$=K8jM9k11a#MN1J>oG z_L_0Fxk)r`Lxj4+CDDD$zM{Wb)HS)yNZ);9w23}`f34tDv?fSZK$?uemDXp;vBLG~KKF}c9AEcDbZ{w~*eVCgcEK7$ z{+vhoU^_xMp3%%r*cUX(KH!=f&m+W*IJnbkpIMMbvl&%gK4s*zX-GLmsR-@Mu7pLj zQO6VpMYtl9juc!J%w`s3q3-G%1D`8Mf-?lfBo2#okq!blJa=qLF9FlJY2$MWk?&;8%FcUbqf1lkRC9hg>PTzOea1@2#0x zXv?Nb={lpFc-P;Pizm9)sMU{m>(nQ*khquc5qUJToF2rm%B{so}6z5nXc9x203~P9#V`RC+7b{#z$D$NNq%Izubz`Ws7NKxod*_yaS^@=16{k1QZg5ag5GLFsb7gfhnUwtw9Aswm{BN$0nPE~19!zOnWTG2*z z>FF@g$TrVew}KWJpvl5U;$xJNUm`1_5e!S+7gI&fvM6h3TQf;2Dw^1|D=gWXI>_Yj z#1Ib20{rkP*cirY@%F~V-7dmaWLf%I0F^+MLrW)iK*o|^L6?vs z7kS1f&817Yq&w8U4c_ZYnC49B|1A9}U%*!^b4 zO7AD9W4Rmd9T6^eJPWOm5_5w0p{aq8q=O!Jpxl}(AfB%hs5;tEPHAgWocD=Q9l4>lJgkN5QrH`-@R@xe}ZP1IbQ;KcmTCNu#lB8lMZm)3!D~m5a6m*P| zhyvY@sKi2*l1-G+O=qclPD!B=FN%`#q?i;{L^K>4N-3%)KAx6Gb!F?rmMfX{@fa18 zO}8@hq)k^wpe9$(D|720?n#3;((GA!x)=#G%i%fV7(91M*Ffw_3~%j2bD=XaY7%}J zfaZ^A#xdTRL1@Ar3YHX9j%R(ELCz>M3(lDuPz7&dqoH;w%ws_s(7Tr?g0oHbbiDl& z7&l`?XX#03gkpF&R-T3wKXjdFdU*z;Yr&;maA+jKXwi;o)SgFgvI_Jeb{J(ey)+?M zH%*stDN&o+rj0MZlQ1<*P_(SC)%%$K-ipq1?9FCabHfHX!fxHLr-pVqkllGT& zBr{#RlQC)Ny(Rbb+1{{Tx%YjZRgf@(M9BaB8-T?iKt2E~$X11*XJIES#5?ie``fd~e419>XoLD&l70J_xrJ`oiLS9DB z$XA{e$Ap_hT_q<%i4>kZoEb4gQKCKpkkb`$8qsak7iM-}1?_^&1&`2H1DTI@Ox_u~ zkpNGNnV5GHNI57K>8rAAFae%vLz3@R-?XHs(CR8fs5rHxVU6J$u9EQ%83Kd)q+;rr zO&N;OkM|FQ=IG~>l6uidL@Q($djWef7OVJ_)B_mY&0t4Xcu>-;hB{H>>Jf$@?Yv^kRz16W~1HBJf2m}R8 z5CwHSBecv=PzStXt;om>3t* zldjrFx=HRFr1GHK)omjwITMmtfx3PN*MepD-J%gKK5A_D#XVKBdjC$b_WNRBjCaCu z*^MHlYji1vZ{EP_0Cl3$D=WSsbqpk@=gd%0-BLD^>s)w>SfWHC^e83S+v1dqO1;~| z%Wq4U#kCEK{+mV7Q41%^N-`%CAHsfA{}ih*-VHUKQAqg0Q*(GPX28{}Hmfg#XJYUX z#3v*MPBgw2mn3i5VNt_nv{-C#yxbA=Oc;9-SrMpqu558~?F7h2$3+^(eJttrY zqxb`tu|ROPWGS*O-XOHzI%)DQ9`0St7@1L8FzZr02Am=n;BaOBHy*p`Iz4GXN*+&G zb7b_B75Kg6uvn~7cnMBI!W(FB0h6^ZmN1fFEu&k zz&)yZKp$d0zM<35wd6`03dJy&p=bmuy1FhM?YQ{fYUD)vO%aNSvg{9*mCoj>v;LbM zt@NxKtxUY|1>ssm?6L(LM?De7IARQFvv2Sd{b^%eWDLhYo~gC-K?mPWrE3NFYHZGx zwVBap*`a9hR~toFNID`eUn?A)BTZ#XL#o6=4_SsMz-Zxqsm)LmN2!Pk68j2-o{a9V zSU$F|UylDQ0WUZaO3P~NcIxr|B7|aiU?qgbq zQ(_JYMZDxeTr`wG-iRq2)cgG*_9)WM5!Q4sFg1m^ z@%^ffNv{UM+2H~o+?Osy4~B}gBUA#^%5aQX+;NPS@in_OK>#N!>trfoEF6AH16ij% zTO}RF5aHYEAHYvN@8Rp~dCKS?KAN8+V?<~ggA(%sN+~tkd)nKwZ{m$VxdDJKJx>=` zGiIIYvvhf*<@EYyI8wOj{PFgO(yW0XIH1p(Ev`1f&n^G$aGzaTo>_|*x7)6i^0HxO zFK;KsLwIk**fXsd_Lm9h74>=!2s4a)$@9Q8N5*lCg)=Y8P11STClPud>LJA9&?nJ( zC}%`bD7ObkV2MlxqPY|^5!rEsAWrrW)Z2h6IqD8O4noqnDP9`3IG;-Y`2xI^{-2C3 zj=#A8 z?pG-oM7R9c&Ok$6miVA7 z4Tvd*X)ucYn?Wf}qCks6c^C`y|#68aO>06^VO&zS^^oB6C>JS}5Cvp5XUUJAQ9 zNzjZt`@K|*D}Na2*%aqXvk0f|!)f<0;iLwqHTFkQ9&Gj|wwv3-ZItn0{ktSx)>g ztbuD#?oUS~T&()QMk26Er|_ZeikljhYbKwaP@23&^gYz6(I0&5^rQuBNBcX)zAc?` z+@(}%M_#L@{_7c9uO6<4j`(wE2 zwkCxs$c`UfdVvtWU%){Fa-WA7_bCMgD$>{dUnNp+v!cP$=$D_D1iB11-)S=)$Jr`1 ztJxff2{-XOzz2m>uDssO+CFa4b!V1C&E|)@NfTS|BpCNLhhsqi4BXzxg#OcF;6Hnw zbEn6qb9u03j%yTj!!Dt_9&tD!LC-O zd>Dcz&%AC{rgjAVmaB&Fmuq&0)c8hBcx9)TuJ_?eZw~A)Qb;LFRgU1fmN0y%fo(vDhS0<^`{!M8+%fNT~p9-#Do^4~v5O@i*%ml0>I7;KK3rVY$VXsydl2 z*8*Kru8YCZ%Z;^ZuF2Bkr)ZdyEqlk!uD4?SkZ^%P9&N0FC$bRt0Wmnt*_J>5!1E&e zD#M8=i(7f!ca+N3@JBiZwhF7o$h|iUi@&tPf&cu6=1q^mv8PBdK3k8+Uv~Ma#XbjX zjQL$@Vg~NST#L8ZXt&rduKNH+PAUEe%GA4p>L5U1;xcKink^PQMyb0#vP$bkC`{E zV~gUv^Vt_%ekaqvhT75jqJ|P~!Y8d?uWtle!)a4oMm}FI2|Ratsknh!`_9<9E`NpJ z-kyJe{LQeLchXW(`ACq@P~cG-R~ZRi82KLaxpZe`GX=jJ zQpmV_1v?$oMknouE(i4&V{0;Tz{O11H+Yq4g7uZxcZqSU8;kJ$H|mPBg>bViRxi|+ zCqrZi-KI;w*T?vyeuDq=hs;w8;Z-7`?n<<>m<4`{Eiohh$-6NlN5&0mKgo=)A}##K5Lz>pU*h_vgrnc)1A%=Y)xH&2;;onV87>+f)V~e}!!~8F{^l zL*=IdfT^{{pMdN8NYc4$Up`b;N4ed$)ox27zt{bAtt#!MJ`VjJM1aF%p~L}U_Xn@^ z0XO3c3svs(cJjH+^o|@y)m~|Loyvk-I@)hkW-2vVV!7~9pNztz_{OM6tkPyB`1N2# zlbmx*Ob$Opll6;3DpTj}S=2eWW8a;g@Q>(Z{#93A00DYlFCu0nG>vkEksno>>oE(f2b{#)dae6F&gQxn^l!!g@D0(@ASaD#X$3|10ttGxp@yFF@W zakdKN<7grB3zgd0(|ONTf^q-+HScaSzI8Cc^>NMif?iJn)P^2cFKSi~xn_}ZV)73V zdo5_Mz`g*I6vk6<0B^H3*1d~rwdO>@FUr{NOWqVjw`~qP9=I001{{Ecj|t>!jNJC| zb=3OX2jN)9$0^A3z;cdQxptTb$@DpPU&MR^;HR2QI~jlsLAwM~ODA4`sD1R9@4-Fz z6L`zBJDvVHxNPiTe|I;;4gDG8!q^B({=jqN6>&v9%ZI9mK0A!kMd%my^CjEj9AzZ* zK9I9^b4iKq2;Hu10MLfjgw3=Q6-jbD}I(5OE=exS0Vs2dz%hW%=SSM0=>Qy8>p z2(LC=*IA8Zp3%Tbv`3}pquQYMRDgWW<{Zw3pOGe+x-|mKxyn zt(ZW(^VznZ29o(PFsn>b2Of z2>5IOf6&GDa7I1u;&~7_Zfe0j-DOiAbjra&00cfK4MrrkT)$0kH2%D&I?8S$>Rv|e z2r~|e^4q)%we^|CZPtR4tlk{h^1Z;07~<8dF#NoMvC;k$_C4J@tNdt@dOvengjj}S zTdSyRf-yD9Yo8QbC2Osm;;%)b2Eh>1wntG`s??Sc%anyk2Fd*2o4%UL|TkSw6XP%%#ZO!Tm+mDoSs~Jllvejaoh&xg! z{DLx;P;Nrz0Wk-h-}A|NT&+^&`|&C)_HR@!7bledLUK9+i($`9jIr`Mln$O-PERuo z0nc6NkL~ESud*xrYi9F}ej7|A5i6a_GIH!erJC(#|5D{?>`{N24z zss15OkDjd7FD7h`Ck!|WU_n2ue%~f80 z4xrV;koB35H;KQ^E&JW0VJ*`ni3Q&Ny-gacoi!C=U5Mrn|46vOxbq zouWUD(ZbI0kbQTp6M+`rKu9;MGtNcKOPFsGRnsaE`bNFwUY!aeAAJTM-bj7xNf zZQ8!Iq4-!$*RIzY<1f>n^;I(J$^$&kLlTJ~6fU^Pm-RXmIP{xgzs3U)K#q?kC*piL zg-hGg_JFLIKpKm7hq7+FZ5?2HbXKeLF%d~x1*J{AMjXvB-xHL_>E0r(-33Ynet#(f zYW9zR#iCF-;RnuHf{~b^*mw8jM)OHz6XDH5mCxg$|GgF<3@M!M`Eq@^-o|B zVGv~gAFM-&u$~slOY(Sg4B@<;XA2Y2=jq|PA*{cXIpCrW70l6Hn`sZ}?MKFC>_8~< zzdzcQLJ3P1s3H{gJM*xDFyalcqYQ?RyA+`t$4h$QL?BW=(br4Wk&t(yX}xC`<3;l0 zgir%>c|FOPbbe{}!?nN<{aCye%YGV@s5yxJxMBZzus6WSreif;8GGOR^t*pD1oYx- z{5lBC=^ggl{$t$N+COcv76%n2n{sW_YO&?Fr?uW#!O^|>7Xj`mI(B2ko8K48|4O4- z+&HQ9F$Ua_F_zPN5|ANBsBnegvp(#e8+-*frM*ZE*myqo(hNfp>j*Iz~bm){i*=wJ=!HZd^fWa1&Z&q`u^)N)7r4rp;;& zB0F_YW^Sx&;Aodoy4AAl1S7V7>=GOKoXGOZF?lur-Wkob{eyU5^nxJ>ZRuiXcQPrj)O{pjq(Fy?^zKlZ4?eZfiB3k!a{GffyR zM^i|Gp)UP)Yu_H0 zb9*&D?;zT2&QKVzk9*BGd%%XpOSG!l>dd4#Sg?@}tiV3K9_`S-#ZKtYp_=nGK;`h! zTy?wB!adUgwnIb;v2e1@OipPLq(R?dhM!{H`A7{uwyjsTHbQ^-JaH4?r$d5ke*HL} zBM}vqdOewYnK%;0xM<~bGlQMgVaNn|FWuBTK#<9Bw>>IVWv~PX@NnA-UwAjO@thU0 z!Wwn8dbe42+;lmyx_58csrmH#uFuH|6!X2%?dgOnrIglOStF2*r({PIioeg%vP)d- zJ5z|HD{gd=+l@EjE*^u=Yq!w5^Ppc$m#^F^Hqn9YZ;(PlXAT}JM2%MLmvY2YB$GNt znrMNC4FT0(^Cp;LtPY`xvSWHsQPmoL?oba})%KpyZ=;dXcabe9A_Xh?rQp zqcJ*v`)$K6n&( z{~0B(0Z=GNl+RiJj)!zww?V0fA6J_6NZ@}`M51!1C0y<)UZ%ulO0emw+kL%pq*TK` z^A)hl7RJ3f2>hp~Wr9@W(o*ypCR1lcQs^7rieFL*gi|xZMZu2yCZsd>>oWR<>~;}X zGSlJuWu+DM>PdBfUL?}?G-?u~*a%dvI|~F7iRUE|zhUkIA2&}*o9&}-DR&q5MBXSa zeXgD-4xLB#?;J}!3-yO>%7e?xsbwc8wk;0e&E8-S$4)SzPbVSeIZ7R?m_tdUmEfOI zulcqELo%=X7Jv0;ObMCrBI#2^%2Gt?@VmwKjt@k9%2ElL?eZ2wjIy!m497dp%_|AI zdlQhN7LQcLT&azi)*2aN)@$u9Xu|A$S34tQ5+kgPsEznRj18 zRV}Y9b=Mx(SFtPK%aAFtRLT@)2vUpeASU5t;SKTXR~YB38~MhNUaW!O*28$0_R0kW zw|KaL@G@$s`~j+bxRK;JekiKl1?|hlwH9f`tU<9?x))C2bL5?+(A14|TXA;r}+RVxI-o@3}vE)0Q4%|;Uj~vWkXRO}% z(N#9MqBFj3yl6O`q>+3z4XX;>L6dS6G!$rMCS&);C7bQuYmfRz&&$<$2Kw*7x6DB? z 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 Sn(1Z$0000 Date: Thu, 22 May 2025 09:45:56 +0000 Subject: [PATCH 117/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 69124c29e..124f3c84b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -32,6 +32,7 @@ hide: ### Internal +* 🔧 Update sponsors: Add InterviewPal. PR [#13728](https://github.com/fastapi/fastapi/pull/13728) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Google Analytics. PR [#13727](https://github.com/fastapi/fastapi/pull/13727) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove MongoDB. PR [#13725](https://github.com/fastapi/fastapi/pull/13725) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13711](https://github.com/fastapi/fastapi/pull/13711) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 61cc7014ccf5191f5d4da74b892615ea0ce5faf0 Mon Sep 17 00:00:00 2001 From: sungchan Yeo Date: Fri, 30 May 2025 22:10:41 +0900 Subject: [PATCH 118/455] =?UTF-8?q?=F0=9F=8C=90=20Update=20Korean=20transl?= =?UTF-8?q?ation=20for=20`docs/ko/docs/virtual-environments.md`=20(#13630)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ko/docs/virtual-environments.md | 846 +++++++++++++++++++++++++++ 1 file changed, 846 insertions(+) create mode 100644 docs/ko/docs/virtual-environments.md diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md new file mode 100644 index 000000000..0d10c3200 --- /dev/null +++ b/docs/ko/docs/virtual-environments.md @@ -0,0 +1,846 @@ +# 가상 환경 + +Python 프로젝트를 작업할 때는 **가상 환경** (또는 이와 유사한 도구)을 사용하는 것이 좋습니다. 각 프로젝트 마다 설치하는 패키지를 분리하여 관리할 수 있습니다. + +/// info | 정보 + +이미 가상 환경에 대해 잘 알고 있다면, 이 섹션은 건너 뛰어도 괜찮습니다. 🤓 + +/// + +/// tip | 팁 + +**가상 환경(Virtual Environment)** 은 **환경 변수(Environment Variable)** 와 다릅니다. + +**환경 변수**는 시스템에 존재하며, 프로그램이 사용할 수 있는 변수입니다. + +**가상 환경**은 몇몇 파일로 구성된 하나의 디렉터리입니다. + +/// + +/// info | 정보 + +이 페이지에서는 **가상 환경**의 사용 방법과 작동 방식을 설명합니다. + +만약 **모든 것을 관리해주는 도구** (Python 설치까지 포함)를 사용하고 싶다면 uv를 사용해보세요. + +/// + +## 프로젝트 생성 + +먼저, 프로젝트를 위한 디렉터리를 하나 생성합니다. + +보통 사용자 홈 디렉터리 안에 `code`라는 디렉터리를 만들고, 그 안에 프로젝트마다 하나씩 디렉터리를 만들어 관리합니다. + +

+ +```console +// 홈 디렉터리로 이동 +$ cd +// 모든 코드 프로젝트를 위한 디렉터리 생성 +$ mkdir code +// code 디렉터리로 이동 +$ cd code +// 이번 프로젝트를 위한 디렉터리 생성 +$ mkdir awesome-project +// 해당 프로젝트 디렉터리로 이동 +$ cd awesome-project +``` + +
+ +## 가상 환경 생성 + +Python 프로젝트를 **처음 시작할 때**, 가상 환경을 **프로젝트 내부**에 생성합니다. + +/// tip | 팁 + +이 작업은 **프로젝트를 처음 설정할 때 한번만** 해주면 됩니다. 이후 작업할 때 반복할 필요는 없습니다. + +/// + +//// tab | `venv` + +Python 표준 라이브러리에 포함된 venv 모듈을 사용해 가상 환경을 생성할 수 있습니다. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | 명령어 상세 설명 + +* `python`: `python` 프로그램을 실행합니다. +* `-m`: 특정 모듈을 스크립트처럼 실행합니다. 대상 모듈을 바로 뒤에 지정합니다. +* `venv`: Python 표준 라이브러리에 포함된 `venv` 모듈을 실행합니다. +* `.venv`: 가상 환경을 `.venv` 디렉터리에 생성합니다. + +/// + +//// + +//// tab | `uv` + +`uv`가 설치되어 있다면, uv를 통해 가상 환경을 생성할 수 있습니다. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | 팁 + +`uv`는 기본적으로 `.venv` 디렉터리에 가상 환경을 생성합니다. + +별도로 디렉터리 이름을 추가 인자로 넘겨 주면 경로를 지정 할 수 있습니다. + +/// + +//// + +해당 명령어는 `.venv` 디렉터리에 새로운 가상 환경을 생성합니다. + +/// details | `.venv` 또는 다른 이름 + +가상 환경을 다른 디렉터리에 생성할 수도 있지만, 관례적으로 `.venv` 디렉터리 이름을 사용합니다. + +/// + +## 가상 환경 활성화 + +이후 실행하는 Python 명령어와 패키지 설치가 가상 환경을 따르도록, 가상 환경을 활성화하세요. + +/// tip | 팁 + +**터미널을 새로 열고** 프로젝트 작업을 시작할 때는, **항상 이 작업을** 해주세요. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Windows에서 Bash(예: Git Bash)를 사용하는 경우: + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | 팁 + +가상 환경에 새로운 패키지를 설치할 때마다, 해당 환경을 다시 활성화하세요. + +이렇게 하면 해당 패키지로 설치된 **터미널(CLI) 프로그램**을 사용할 때, 전역에 설치된 다른 버전이 아니라, 가상 환경 안에 설치된 정확한 버전을 사용합니다. + +/// + +## 가상 환경이 활성화 여부 확인 + +가상 환경이 활성화되었는지 확인합니다. (이전 명령어가 제대로 작동했는지 확인합니다). + +/// tip | 팁 + +이 단계는 **선택 사항**이지만, 모든 것이 예상대로 작동하고 있는지, 그리고 의도한 가상 환경이 활성화 되었는 지 **확인**하는 좋은 방법입니다. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +`python` 위치가 프로젝트 내부(이 예시에서는 `awesome-project`)의 `.venv/bin/python` 경로로 표시된다면 성공입니다. 🎉 + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +`python` 위치가 프로젝트 내부(이 예시에서는 `awesome-project`)의 `.venv\bin\python` 경로로 표시된다면 성공입니다. 🎉 + +//// + +## pip 업그레이드 + +/// tip | 팁 + +`uv`를 사용한다면, `pip` 대신 `uv`로 패키지를 설치하게 되므로 `pip`을 업그레이드할 필요가 없습니다. 😎 + +/// + +`pip`을 사용하여 패키지를 설치하는 경우 (Python 표준 라이브러리에 포함되어 있습니다), **최신 버전으로 업그레이드**하는 것이 좋습니다. + +패키지 설치 중 발생하는 다양하고 특이한 에러들은 `pip` 업그레이드로 쉽게 해결되는 경우가 많습니다. + +/// tip | 팁 + +이 작업은 보통 가상 환경을 생성한 **직후 한 번만** 하면 됩니다. + +/// + +가상 환경이 활성화된 상태인지 확인한 후(앞서 설명한 명령어 사용), 아래 명령어를 실행하세요: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +## `.gitignore` 추가하기 + +**Git**을 사용하고 있다면 (사용하는 것이 좋습니다), `.gitignore` 파일을 추가해서 `.venv` 디렉터리 전체를 Git에서 제외하세요. + +/// tip | 팁 + +`uv`를 사용해 가상 환경을 생성했다면, 이미 이 작업이 자동으로 처리되어 있으므로 이 단계는 건너뛰어도 됩니다. 😎 + +/// + +/// tip | 팁 + +이 작업도 마찬가지로, 가상 환경을 생성한 **직후 한 번만** 하면 됩니다. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | 명령어 상세 설명 + +* `echo "*"`: 터미널에 `*` 텍스트를 "출력"합니다 (다음 설명에서 조금 바뀝니다) +* `>`: 왼쪽 명령어의 출력 내용을 터미널에 출력하지 않고, 오른쪽에 지정된 파일로 **기록(write)** 하라는 의미입니다. +* `.gitignore`: 출력된 텍스트가 기록될 파일 이름입니다. + +그리고 Git에서 `*`는 "모든 것"을 의미합니다. 따라서 `.venv` 디렉터리 안의 모든 것을 무시하게 됩니다. + +이 명령어는 다음과 같은 내용을 가진 `.gitignore` 파일을 생성합니다: + + +```gitignore +* +``` + +/// + +## 패키지 설치 + +가상 환경을 활성화한 후, 그 안에 필요한 패키지들을 설치할 수 있습니다. + +/// tip | 팁 + +프로젝트에서 필요한 패키지를 설치하거나 업그레이드할 때는 이 작업을 **한 번만** 하면 됩니다. + +만약 특정 패키지의 버전을 업그레이드하거나, 새로운 패키지를 추가할 필요가 생기면 **다시 이 작업을 반복**하면 됩니다. + +/// + +### 패키지 직접 설치 + +급하게 작업하거나, 프로젝트에 필요한 패키지 목록을 따로 파일로 관리하고 싶지 않은 경우, 패키지를 직접 설치할 수도 있습니다. + +/// tip | 팁 + +패키지 이름과 버전 정보를 파일에 정리해두는 것(예: `requirements.txt` 또는 `pyproject.toml`)은 (매우) 좋은 생각입니다. + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +`uv`를 사용하는 경우: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### `requirements.txt`에서 설치 + +`requirements.txt` 파일이 있다면, 그 안에 명시된 패키지들을 한 번에 설치할 수 있습니다. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +`uv`를 사용하는 경우: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +다음은 몇 가지 패키지를 포함한 `requirements.txt`의 예시입니다: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## 프로그램 실행 + +가상 환경을 활성화한 후에는 프로그램을 실행할 수 있습니다. 이때 해당 가상 환경에 설치된 Python과 패키지들이 사용됩니다. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## 에디터 설정 + +에디터를 사용할 경우, 앞서 만든 가상 환경을 사용하도록 설정하는 것이 좋습니다. (대부분의 에디터는 자동으로 감지하기도 합니다.) +이렇게 하면 자동 완성 기능이나 코드 내 오류 표시 기능을 제대로 사용할 수 있습니다. + +예시: + +* VS Code +* PyCharm + +/// tip | 팁 + +이 설정은 보통 가상 환경을 **처음 만들었을 때 한 번만** 해주면 됩니다. + +/// + +## 가상 환경 비활성화 + +프로젝트 작업이 끝났다면, 가상 환경을 **비활성화**할 수 있습니다. + +
+ +```console +$ deactivate +``` + +
+ +이렇게 하면 이후에 `python` 명령어를 실행했을 때, 가상 환경의 Python이나 그 안에 설치된 패키지들을 사용하지 않게 됩니다. + +## 이제 작업할 준비가 되었습니다 + +이제 프로젝트 작업을 시작할 준비가 완료되었습니다. + + +/// tip | 팁 + +위 내용을 더 깊이 이해하고 싶으신가요? + +그렇다면 계속 읽어 주세요. 👇🤓 + +/// + +## 가상 환경을 왜 사용하는가 + +FastAPI를 사용하려면 먼저 Python을 설치해야 합니다. + +그 후에는 FastAPI와 함께 사용할 **기타 패키지들**을 **설치**해야 합니다. + +패키지를 설치할 때 보통 Python에 기본 포함된 `pip` 명령어(또는 유사한 도구)를 사용합니다. + +하지만 `pip`을 그냥 직접 사용하면, 해당 패키지들은 **전역 Python 환경**(시스템 전체에 설치된 Python)에 설치됩니다. + +### 문제점 + +그렇다면, 전역 Python 환경에 패키지를 설치하면 어떤 문제가 발생할까요? + +어느 시점이 되면, **서로 다른 패키지들**에 의존하는 여러 개의 프로그램을 작성하게 될 것입니다. 그리고 이들 중 일부는 **같은 패키지의 서로 다른 버전**을 필요로 할 수 있습니다. 😱 + +예를 들어, `마법사의 돌(philosophers-stone)` 프로젝트를 만들었다고 가정해봅시다. 이 프로그램은 `해리 포터(harry)`라는 패키지의 `v1` 버전을 **의존**합니다. 따라서 `harry`를 설치해야 합니다. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +그런데 나중에 `아즈카반의 죄수(prisoner-of-azkaban)`이라는 또 다른 프로젝트를 만들게 되었고, 이 프로젝트도 역시 `harry` 패키지를 사용합니다. 그런데 이 프로젝트는 `harry`의 `v3` 버전이 필요합니다. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +하지만 이제 문제가 생깁니다. 로컬 가상 환경 대신에 전역 환경에 패키지를 설치하게 되면, 어떤 버전의 `harry`를 설치할지를 선택해야 하기 때문입니다. + +예를 들어, `마법사의 돌(philosophers-stone)`을 실행하고 싶다면 먼저 `harry` `v1` 버전을 다음과 같이 설치 해야 합니다: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +그러면 결국 전역 Python 환경에는 `harry` `v1`버전이 설치된 상태가 됩니다. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +하지만 이제 `아즈카반의 죄수(prisoner-of-azkaban)`을 실행하고 싶다면, `harry` `v1`버전을 제거하고 `harry` `v3`버전을 설치해야 합니다. (또는 단순히 `v3`버전을 설치하는 것만으로도 기존의 `v1`버전이 자동으로 제거됩니다.) + +
+ +```console +$ pip install "harry==3" +``` + +
+ +그렇게 하면 이제 전역 Python 환경에는 `harry` `v3`버전이 설치된 상태가 됩니다. + +그리고 다시 `마법사의 돌(philosophers-stone)`을 실행하려고 하면, **작동하지** 않을 수 있습니다. 왜냐하면 이 프로그램은 `harry` `v1`버전을 필요로 하기 때문입니다. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|⛔️| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | 팁 + +Python 패키지들은 **새 버전**에서 **호환성 문제(breaking changes)**가 발생하지 않도록 최대한 노력하는 것이 일반적입니다. 하지만 그래도 안전하게 작업하려면, 테스트를 실행해보면서 새 버전을 의도적으로 설치하는 것이 좋습니다. + +/// + +이제, 이런 일이 여러분의 **모든 프로젝트**가 사용하는 **수많은 패키지들**에서 동시에 발생한다고 상상해보세요. 이는 매우 관리하기 어려우며, 결국 **서로 호환되지 않는 버전**의 패키지로 프로젝트를 실행하게 될 가능성이 높고, 그로 인해 어떤 문제가 왜 발생하는지 알 수 없게 될 수 있습니다. + +또한 사용하는 운영체제(Linux, Windows, macOS 등)에 따라 Python이 **미리 설치되어 있을 수도** 있습니다. 이런 경우에는 운영체제의 동작에 필요한 특정 버전의 패키지들이 함께 설치되어 있을 수 있습니다. 이 상태에서 전역 Python 환경에 임의의 패키지를 설치하면, 운영체제에 포함된 프로그램 일부가 **깨질 위험**도 있습니다. + +## 패키지들은 어디에 설치되는가 + +Python을 설치하면, 컴퓨터에 여러 디렉터리와 파일들이 생성됩니다. + +이 중 일부 디렉터리는 사용자가 설치한 패키지들을 보관하는 역할을 합니다. + +예를 들어, 아래 명령어를 실행하면: + +
+ +```console +// 지금 실행하지 않아도 됩니다, 그냥 예제일 뿐이에요 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +해당 명령어는 FastAPI 코드를 포함한 압축 파일을 다운로드합니다. 이 파일은 보통 PyPI에서 받아옵니다. + +또한 FastAPI가 의존하는 다른 패키지들도 함께 **다운로드**됩니다. + +그리고 그 모든 파일들을 **압축 해제**한 뒤, 컴퓨터의 특정 디렉터리에 저장합니다. + +기본적으로 이 파일들은 Python이 설치된 디렉터리 안, 즉 **전역 환경**에 내의 디렉터리에 저장됩니다. + +## 가상 환경이란 + +전역 환경에 모든 패키지를 설치하면서 발생하는 문제에 대한 해결책은, 작업하는 **각 프로젝트마다 가상 환경**을 사용하는 것입니다. + +가상 환경은 전역 환경과 매우 유사한 하나의 **디렉터리**이며, 그 안에 해당 프로젝트를 위한 패키지들을 설치할 수 있습니다. + +이렇게 하면 각 프로젝트는 자체적인 가상 환경(`.venv` 디렉터리)을 가지게 되며, 그 안에 해당 프로젝트 전용 패키지들을 보유하게 됩니다. + + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## 가상 환경 활성화 의미 + +가상 환경을 활성화한다는 것은, 예를 들어 다음과 같은 명령어를 실행하는 것을 의미합니다: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Windows에서 Bash(예: Git Bash)를 사용하는 경우: + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +이 명령어는 이후에 실행될 명령어에서 사용될 [환경 변수](environment-variables.md){.internal-link target=_blank} 몇 개를 생성하거나 수정합니다. + +이 변수들 중 하나가 바로 `PATH` 변수입니다. + +/// tip | 팁 + +`PATH` 환경 변수에 대해 더 알고 싶다면 [환경 변수 문서의 PATH 환경 변수 섹션](environment-variables.md#path-environment-variable){.internal-link target=_blank}을 참고하세요. + +/// + +가상 환경을 활성화하면, 가상 환경의 경로인 `.venv/bin` (Linux와 macOS) 또는 `.venv\Scripts`(Windows)를 `PATH` 환경 변수에 추가됩니다. + +예를 들어, 가상 환경을 활성화하기 전의 `PATH` 변수는 다음과 같았다고 가정해봅시다: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +시스템은 다음 경로들에서 프로그램을 찾게 됩니다: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +시스템은 다음 경로들에서 프로그램을 찾게 됩니다: + +* `C:\Windows\System32` + +//// + +가상 환경을 활성화한 후에는, `PATH` 변수는 다음과 같은 형태가 됩니다: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +시스템은 가장 먼저 다음 경로에서 프로그램을 찾기 시작합니다: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +그 후에 다른 디렉터리들을 탐색합니다. + +따라서 터미널에 `python`을 입력하면, 시스템은 다음 위치에 있는 Python 프로그램을 찾게 됩니다: + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +그리고 해당 Python을 사용하게 됩니다. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +시스템은 가장 먼저 다음 경로에서 프로그램을 찾기 시작합니다: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +그 후에 다른 디렉터리들을 탐색합니다. + +따라서 터미널에 `python`을 입력하면, 시스템은 다음 경로에 있는 Python 프로그램을 찾게 됩니다: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +그리고 해당 Python을 사용하게 됩니다. + +//// + +중요한 세부 사항 중 하나는, 가상 환경의 경로가 `PATH` 변수의 가장 **앞**에 추가된다는 점입니다. 시스템은 사용 가능한 다른 Python들보다 **먼저** 이 경로를 찾습니다. 그래서 터미널에서 `python`을 실행하면, 전역 환경의 Python이 아닌 **가상 환경에 있는** Python이 사용됩니다. (예: 전역 환경에 설치된 `python`이 있더라도 그보다 우선합니다.) + +가상 환경을 활성화하면 이 외에도 몇 가지 다른 것들이 변경되지만, 이는 그중에서도 가장 중요한 변화 중 하나입니다. + +## 가상 환경 확인하기 + +가상 환경이 활성화 되었는지 확인하려면, 아래 명령어를 사용할 수 있습니다: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +즉, 현재 사용되는 `python` 프로그램은 **가상 환경 내부에 있는 것**입니다. + +Linux와 macOS에서는 `which`, Windows PowerShell에서는 `Get-Command` 명령어를 사용합니다. + +이 명령어는 `PATH` 환경 변수에 지정된 경로들을 **순서대로 탐색**하면서 `python`이라는 이름의 프로그램을 찾습니다. +찾는 즉시, 해당 프로그램의 **경로를 출력**합니다. + +중요한 점은 터미널에서 `python`을 실행했을 때, 실제로 실행되는 "`python`"이 어떤 것인지 정확히 알 수 있다는 것입니다. + +따라서 현재 올바른 가상 환경에 있는지 확인할 수 있습니다. + +/// tip | 팁 + +하나의 가상 환경을 활성화한 뒤, 해당 Python을 가진 상태에서 **또 다른 프로젝트**로 이동하는 것은 흔히 발생합니다. + +하지만 이때 이전 프로젝트의 가상 환경에 있는 **잘못된 Python 실행 파일**을 사용하게 되어 새 프로젝트가 **정상 작동하지 않을 수 있습니다.** + +그래서 현재 어떤 `python`이 사용되고 있는지 확인할 수 있는 능력은 매우 유용합니다. 🤓 + +/// + +## 가상 환경을 비활성화하는 이유 + +예를 들어 `마법사의 돌(philosophers-stone)`이라는 프로젝트에서 작업 중이라고 해보겠습니다. 이때 해당 **가상 환경을 활성화**하고, 필요한 패키지를 설치하며 작업을 진행합니다. + +그런데 이제는 **다른 프로젝트**인 `아즈카반의 죄수(prisoner-of-azkaban)`을 작업하고 싶어졌습니다. + +그래서 그 프로젝트 디렉터리로 이동합니다: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +만약 `마법사의 돌(philosophers-stone)`의 가상 환경을 비활성화하지 않았다면, 터미널에서 `python`을 실행할 때 여전히 `마법사의 돌(philosophers-stone)` 가상 환경의 Python을 사용하게 됩니다. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// sirius를 임포트하는 데 실패했습니다. 설치되어 있지 않아요 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +하지만 `마법사의 돌(philosophers-stone)`의 가상 환경을 비활성화한 다음, `아즈카반의 죄수(prisoner-of-azkaban)` 프로젝트의 가상 환경을 활성화하면, 이제 `python` 명령어는 `아즈카반의 죄수(prisoner-of-azkaban)` 가상 환경의 Python을 사용하게 됩니다. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// 이전 디렉터리에 있을 필요 없이, 어디서든 가상 환경을 비활성화할 수 있습니다. 다른 프로젝트 디렉터리로 이동한 후에도 괜찮아요 😎 +$ deactivate + +// prisoner-of-azkaban/.venv 가상 환경을 활성화합니다 🚀 +$ source .venv/bin/activate + +// 이제 python을 실행하면, 이 가상 환경에 설치된 sirius 패키지를 찾게 됩니다 ✨ +$ python main.py + +못된 짓을 꾸미고 있음을 엄숙히 맹세합니다.🧙 +ImportError는 이제 없습니다. 🐺 +``` + +
+ +## 대안들 + +이 문서는 여러분이 Python 프로젝트를 시작하고, **그 내부에서** 어떻게 돌아가는지 알려주는 간단한 가이드입니다. + +가상 환경, 패키지 의존성(Requirements), 프로젝트를 관리하는 방법에는 이 외에도 다양한 **대안**들이 존재합니다. + +만약 준비가 되었다면, **프로젝트 전체**, 패키지 의존성, 가상 환경 등을 통합적으로 **관리**할 수 있는 도구를 써보는 것도 좋습니다. 그럴 때 추천하는 도구가 바로 uv입니다. + +`uv`는 다양한 기능을 지원합니다: + +* 다양한 버전의 **Python 설치** +* 각 프로젝트 별 **가상 환경 관리** +* **패키지 설치** +* 프로젝트의 **의존성과 버전** 관리 +* 설치된 패키지들과 그 버전을 **정확히 고정(lock)**해서,개발 환경과 운영 환경이 완전히 동일하게 작동할 수 있도록 보장 +* 이 외에도 다양한 기능을 지원 + +## 결론 + +여기까지 모두 읽고 이해했다면, 이제 많은 개발자들보다 가상 환경을 **훨씬 더 깊이 있게 이해**하게 되셨습니다. 🤓 + +이런 세부적인 내용을 알고 있으면, 언젠가 복잡해 보이는 문제를 디버깅할 때 분명히 큰 도움이 될 것입니다. 이제는 **이 모든 것들이 내부에서 어떻게 작동하는지** 알고 있기 때문입니다. 😎 From 34856a27381c5deed62ce8ae6e153613d55e62b7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:11:03 +0000 Subject: [PATCH 119/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 124f3c84b..c6c615d55 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Update Korean translation for `docs/ko/docs/virtual-environments.md`. PR [#13630](https://github.com/fastapi/fastapi/pull/13630) by [@sungchan1](https://github.com/sungchan1). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-param-models.md`. PR [#13526](https://github.com/fastapi/fastapi/pull/13526) by [@minaton-ru](https://github.com/minaton-ru). * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/index.md`. PR [#13374](https://github.com/fastapi/fastapi/pull/13374) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#13324](https://github.com/fastapi/fastapi/pull/13324) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). From 5f84703beae6d535998861a9339e72ca7c203458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A1n=20Fal=C3=B3n?= Date: Fri, 30 May 2025 15:15:52 +0200 Subject: [PATCH 120/455] =?UTF-8?q?=F0=9F=93=9D=20Fix=20internal=20anchor?= =?UTF-8?q?=20link=20in=20Spanish=20deployment=20docs=20(#13737)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/es/docs/deployment/docker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md index ff204f078..3a39d3661 100644 --- a/docs/es/docs/deployment/docker.md +++ b/docs/es/docs/deployment/docker.md @@ -6,7 +6,7 @@ Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **re /// tip | Consejo -¿Tienes prisa y ya conoces esto? Salta al [`Dockerfile` más abajo 👇](#build-a-docker-image-for-fastapi). +¿Tienes prisa y ya conoces esto? Salta al [`Dockerfile` más abajo 👇](#construir-una-imagen-de-docker-para-fastapi). /// From 6c1e7fb4de03c20540b0d519ff929025f3d80baa Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:16:17 +0000 Subject: [PATCH 121/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c6c615d55..241448c83 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 📝 Fix internal anchor link in Spanish deployment docs. PR [#13737](https://github.com/fastapi/fastapi/pull/13737) by [@fabianfalon](https://github.com/fabianfalon). * 🌐 Update Korean translation for `docs/ko/docs/virtual-environments.md`. PR [#13630](https://github.com/fastapi/fastapi/pull/13630) by [@sungchan1](https://github.com/sungchan1). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-param-models.md`. PR [#13526](https://github.com/fastapi/fastapi/pull/13526) by [@minaton-ru](https://github.com/minaton-ru). * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/index.md`. PR [#13374](https://github.com/fastapi/fastapi/pull/13374) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). From 374626e0364fe373d7e7fdc75e289b2d5e9e5226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B3=D0=BE=D1=80=20=D0=9E=D0=BD=D0=B8=D1=89=D1=83?= =?UTF-8?q?=D0=BA?= <120256301+EgorOnishchuk@users.noreply.github.com> Date: Fri, 30 May 2025 16:17:36 +0300 Subject: [PATCH 122/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translat?= =?UTF-8?q?ion=20for=20`docs/ru/docs/tutorial/request-form-models.md`=20(#?= =?UTF-8?q?13552)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/docs/tutorial/request-form-models.md | 78 ++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/ru/docs/tutorial/request-form-models.md diff --git a/docs/ru/docs/tutorial/request-form-models.md b/docs/ru/docs/tutorial/request-form-models.md new file mode 100644 index 000000000..1034ed27f --- /dev/null +++ b/docs/ru/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# Модели форм + +Вы можете использовать **Pydantic-модели** для объявления **полей форм** в FastAPI. + +/// info | Дополнительная информация + +Чтобы использовать формы, сначала установите `python-multipart`. + +Убедитесь, что вы создали и активировали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, а затем установите пакет, например: + +```console +$ pip install python-multipart +``` + +/// + +/// note | Заметка + +Этот функционал доступен с версии `0.113.0`. 🤓 + +/// + +## Pydantic-модель для формы + +Вам просто нужно объявить **Pydantic-модель** с полями, которые вы хотите получить как **поля формы**, а затем объявить параметр как `Form`: + +{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} + +**FastAPI** **извлечёт** данные для **каждого поля** из **данных формы** в запросе и выдаст вам объявленную Pydantic-модель. + +## Проверка сгенерированной документации + +Вы можете посмотреть поля формы в графическом интерфейсе Документации по пути `/docs`: + +
+ +
+ +## Запрет дополнительных полей формы + +В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** поля формы только теми, которые объявлены в Pydantic-модели. И **запретить** любые **дополнительные** поля. + +/// note | Заметка + +Этот функционал доступен с версии `0.114.0`. 🤓 + +/// + +Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (`forbid`) все дополнительные (`extra`) поля: + +{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} + +Если клиент попробует отправить дополнительные данные, то в ответ он получит **ошибку**. + +Например, если клиент попытается отправить поля формы: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +То в ответ он получит **ошибку**, сообщающую ему, что поле `extra` не разрешено: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## Заключение + +Вы можете использовать Pydantic-модели для объявления полей форм в FastAPI. 😎 From 2e9e5dfeec7300abc144c0ade02645d0b8d728c4 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:18:34 +0000 Subject: [PATCH 123/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 241448c83..28db3039a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-form-models.md`. PR [#13552](https://github.com/fastapi/fastapi/pull/13552) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). * 📝 Fix internal anchor link in Spanish deployment docs. PR [#13737](https://github.com/fastapi/fastapi/pull/13737) by [@fabianfalon](https://github.com/fabianfalon). * 🌐 Update Korean translation for `docs/ko/docs/virtual-environments.md`. PR [#13630](https://github.com/fastapi/fastapi/pull/13630) by [@sungchan1](https://github.com/sungchan1). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-param-models.md`. PR [#13526](https://github.com/fastapi/fastapi/pull/13526) by [@minaton-ru](https://github.com/minaton-ru). From 4f9b737548bddbfeddef19ba28316799971e1d26 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Fri, 30 May 2025 16:31:13 +0300 Subject: [PATCH 124/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/handling-errors.md`=20page?= =?UTF-8?q?=20(#13420)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/handling-errors.md | 255 +++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 docs/uk/docs/tutorial/handling-errors.md diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md new file mode 100644 index 000000000..12a356cd0 --- /dev/null +++ b/docs/uk/docs/tutorial/handling-errors.md @@ -0,0 +1,255 @@ +# Обробка Помилок + +Є багато ситуацій, коли потрібно повідомити клієнта, який використовує Ваш API, про помилку. + +Цим клієнтом може бути браузер із фронтендом, код іншого розробника, IoT-пристрій тощо. + +Можливо, Вам потрібно повідомити клієнта, що: + +* У нього недостатньо прав для виконання цієї операції. +* Він не має доступу до цього ресурсу. +* Елемент, до якого він намагається отримати доступ, не існує. +* тощо. + +У таких випадках зазвичай повертається **HTTP статус-код** в діапазоні **400** (від 400 до 499). + +Це схоже на HTTP статус-коди 200 (від 200 до 299). Ці "200" статус-коди означають, що запит пройшов успішно. + +Статус-коди в діапазоні 400 означають, що сталася помилка з боку клієнта. + +Пам'ятаєте всі ці помилки **404 Not Found** (і жарти про них)? + +## Використання `HTTPException` + +Щоб повернути HTTP-відповіді з помилками клієнту, використовуйте `HTTPException`. + +### Імпорт `HTTPException` + +{* ../../docs_src/handling_errors/tutorial001.py hl[1] *} + +### Використання `HTTPException` у коді + +`HTTPException` — це звичайна помилка Python із додатковими даними, які стосуються API. + +Оскільки це помилка Python, Ви не `повертаєте` його, а `генеруєте` (генеруєте помилку). + +Це також означає, що якщо Ви перебуваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там генеруєте `HTTPException`, всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту. + +Перевага використання `генерації` (raise) помилки замість `повернення` значення (return) стане більш очевидним в розділі про Залежності та Безпеку. + +У цьому прикладі, якщо клієнт запитує елемент за ID, якого не існує, буде згенеровано помилку зі статус-кодом `404`: + +{* ../../docs_src/handling_errors/tutorial001.py hl[11] *} + +### Отримана відповідь + +Якщо клієнт робить запит за шляхом `http://example.com/items/foo` (де `item_id` `"foo"`), він отримає статус-код 200 і JSON відповідь: + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +Але якщо клієнт робить запит на `http://example.com/items/bar` (де `item_id` має не існуюче значення `"bar"`), то отримає статус-код 404 (помилка "не знайдено") та відповідь: + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | Порада + +Під час виклику `HTTPException` Ви можете передати будь-яке значення, яке може бути перетворене в JSON, як параметр `detail`, а не лише рядок (`str`). + +Ви можете передати `dict`, `list` тощо. + +Вони обробляються автоматично за допомогою **FastAPI** та перетворюються в JSON. + +/// + +## Додавання власних заголовків + +Іноді потрібно додати власні заголовки до HTTP-помилки, наприклад, для певних типів безпеки. + +Ймовірно, Вам не доведеться використовувати це безпосередньо у своєму коді. + +Але якщо Вам знадобиться це для складного сценарію, Ви можете додати власні заголовки: + +{* ../../docs_src/handling_errors/tutorial002.py hl[14] *} + +## Встановлення власних обробників помилок + +Ви можете додати власні обробники помилок за допомогою тих самих утиліт обробки помилок зі Starlette. + +Припустимо, у Вас є власний обʼєкт помилки `UnicornException`, яке Ви (або бібліотека, яку Ви використовуєте) може `згенерувати` (`raise`). + +І Ви хочете обробляти це виключення глобально за допомогою FastAPI. + +Ви можете додати власний обробник виключень за допомогою `@app.exception_handler()`: + +{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *} + +Тут, якщо Ви звернетеся до `/unicorns/yolo`, то згенерується помилка `UnicornException`. + +Але вона буде оброблена функцією-обробником `unicorn_exception_handler`. + +Отже, Ви отримаєте зрозумілу помилку зі HTTP-статусом `418` і JSON-відповіддю: + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | Технічні деталі + +Ви також можете використовувати `from starlette.requests import Request` і `from starlette.responses import JSONResponse`. + +**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette. Те ж саме стосується і `Request`. + +/// + +## Перевизначення обробників помилок за замовчуванням + +**FastAPI** має кілька обробників помилок за замовчуванням. + +Ці обробники відповідають за повернення стандартних JSON-відповідей, коли Ви `генеруєте` (`raise`) `HTTPException`, а також коли запит містить некоректні дані. + +Ви можете перевизначити ці обробники, створивши власні. + +### Перевизначення помилок валідації запиту + +Коли запит містить некоректні дані, **FastAPI** генерує `RequestValidationError`. + +І також включає обробник помилок за замовчуванням для нього. + +Щоб перевизначити його, імпортуйте `RequestValidationError` і використовуйте його з `@app.exception_handler(RequestValidationError)` для декорування обробника помилок. + +Обробник помилок отримує `Request` і саму помилку. + +{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *} + +Тепер, якщо Ви перейдете за посиланням `/items/foo`, замість того, щоб отримати стандартну JSON-помилку: + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +Ви отримаєте текстову версію: + +``` +1 validation error +path -> item_id + value is not a valid integer (type=type_error.integer) +``` + +#### `RequestValidationError` проти `ValidationError` + +/// warning | Увага + +Це технічні деталі, які Ви можете пропустити, якщо вони зараз не важливі для Вас. + +/// + +`RequestValidationError` є підкласом Pydantic `ValidationError`. + +**FastAPI** використовує його для того, якщо Ви використовуєте модель Pydantic у `response_model` і у ваших даних є помилка, Ви побачили помилку у своєму журналі. + +Але клієнт/користувач не побачить її. Натомість клієнт отримає "Internal Server Error" зі статусом HTTP `500`. + +Так має бути, якщо у Вас виникла `ValidationError` Pydantic у *відповіді* або деінде у вашому коді (не у *запиті* клієнта), це насправді є помилкою у Вашому коді. + +І поки Ви її виправляєте, клієнти/користувачі не повинні мати доступу до внутрішньої інформації про помилку, оскільки це може призвести до вразливості безпеки. + +### Перевизначення обробника помилок `HTTPException` + +Аналогічно, Ви можете перевизначити обробник `HTTPException`. + +Наприклад, Ви можете захотіти повернути текстову відповідь замість JSON для цих помилок: + +{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *} + +/// note | Технічні деталі + +Ви також можете використовувати `from starlette.responses import PlainTextResponse`. + +**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette. + +/// + +### Використання тіла `RequestValidationError` + +`RequestValidationError` містить `body`, який він отримав із некоректними даними. + +Ви можете використовувати це під час розробки свого додатка, щоб логувати тіло запиту та налагоджувати його, повертати користувачеві тощо. + +{* ../../docs_src/handling_errors/tutorial005.py hl[14] *} + +Тепер спробуйте надіслати некоректний елемент, наприклад: + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` +Ви отримаєте відповідь, яка повідомить Вам, які саме дані є некоректні у вашому тілі запиту: + + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### `HTTPException` FastAPI проти `HTTPException` Starlette + +**FastAPI** має власний `HTTPException`. + +І клас помилки `HTTPException` в **FastAPI** успадковується від класу помилки `HTTPException` в Starlette. + +Єдина різниця полягає в тому, що `HTTPException` в **FastAPI** приймає будь-які дані, які можна перетворити на JSON, для поля `detail`, тоді як `HTTPException` у Starlette приймає тільки рядки. + +Отже, Ви можете продовжувати використовувати `HTTPException` в **FastAPI** як зазвичай у своєму коді. + +Але коли Ви реєструєте обробник виключень, слід реєструвати його для `HTTPException` зі Starlette. + +Таким чином, якщо будь-яка частина внутрішнього коду Starlette або розширення чи плагін Starlette згенерує (raise) `HTTPException`, Ваш обробник зможе перехопити та обробити її. + +У цьому прикладі, щоб мати можливість використовувати обидва `HTTPException` в одному коді, помилка Starlette перейменовується на `StarletteHTTPException`: + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### Повторне використання обробників помилок **FastAPI** + +Якщо Ви хочете використовувати помилки разом із такими ж обробниками помилок за замовчуванням, як у **FastAPI**, Ви можете імпортувати та повторно використовувати їх із `fastapi.exception_handlers`: + +{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *} + +У цьому прикладі Ви просто використовуєте `print` для виведення дуже інформативного повідомлення, але Ви зрозуміли основну ідею. Ви можете обробити помилку та повторно використовувати обробники помилок за замовчуванням. From f0b3ebdf038dc63292a0337e9f10ba859d783628 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:31:35 +0000 Subject: [PATCH 125/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 28db3039a..4364e367d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/handling-errors.md` page. PR [#13420](https://github.com/fastapi/fastapi/pull/13420) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-form-models.md`. PR [#13552](https://github.com/fastapi/fastapi/pull/13552) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). * 📝 Fix internal anchor link in Spanish deployment docs. PR [#13737](https://github.com/fastapi/fastapi/pull/13737) by [@fabianfalon](https://github.com/fabianfalon). * 🌐 Update Korean translation for `docs/ko/docs/virtual-environments.md`. PR [#13630](https://github.com/fastapi/fastapi/pull/13630) by [@sungchan1](https://github.com/sungchan1). From aa2bb3e5699cb61f051654994f50b2c389f58907 Mon Sep 17 00:00:00 2001 From: Junbeom Lee Date: Fri, 30 May 2025 09:33:53 -0400 Subject: [PATCH 126/455] =?UTF-8?q?=F0=9F=8C=90=20Update=20Korean=20transl?= =?UTF-8?q?ation=20for=20`docs/ko/docs/advanced/events.md`=20(#13487)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ko/docs/advanced/events.md | 148 ++++++++++++++++++++++++++++---- 1 file changed, 130 insertions(+), 18 deletions(-) diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index ae349e7be..5f8fe0f1e 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -1,53 +1,165 @@ -# 이벤트: startup과 shutdown +# Lifespan 이벤트 -필요에 따라 응용 프로그램이 시작되기 전이나 종료될 때 실행되는 이벤트 핸들러(함수)를 정의할 수 있습니다. +애플리케이션 **시작 전**에 실행되어야 하는 로직(코드)을 정의할 수 있습니다. 이는 이 코드가 **한 번**만 실행되며, **애플리케이션이 요청을 받기 시작하기 전**에 실행된다는 의미입니다. -이 함수들은 `async def` 또는 평범하게 `def`으로 선언할 수 있습니다. +마찬가지로, 애플리케이션이 **종료될 때** 실행되어야 하는 로직(코드)을 정의할 수 있습니다. 이 경우, 이 코드는 **한 번**만 실행되며, **여러 요청을 처리한 후**에 실행됩니다. -/// warning | 경고 +이 코드가 애플리케이션이 **요청을 받기 시작하기 전에** 실행되고, 요청 처리가 끝난 후 **종료 직전에** 실행되기 때문에 전체 애플리케이션의 **수명(Lifespan)**을 다룹니다. (잠시 후 "수명"이라는 단어가 중요해집니다 😉) -이벤트 핸들러는 주 응용 프로그램에서만 작동합니다. [하위 응용 프로그램 - 마운트](./sub-applications.md){.internal-link target=_blank}에서는 작동하지 않습니다. +이 방법은 전체 애플리케이션에서 사용해야 하는 **자원**을 설정하거나 요청 간에 **공유되는** 자원을 설정하고, 또는 그 후에 **정리**하는 데 매우 유용할 수 있습니다. 예를 들어, 데이터베이스 연결 풀 또는 공유되는 머신러닝 모델을 로드하는 경우입니다. + + +## 사용 사례 + +먼저 **사용 사례**를 예로 들어보고, 이를 어떻게 해결할 수 있는지 살펴보겠습니다. + +우리가 요청을 처리하기 위해 사용하고 싶은 **머신러닝 모델**이 있다고 상상해 봅시다. 🤖 + +이 모델들은 요청 간에 공유되므로, 요청마다 모델이 하나씩 있는 것이 아니라, 여러 요청에서 동일한 모델을 사용합니다. + +모델을 로드하는 데 **상당한 시간이 걸린다고 상상해 봅시다**, 왜냐하면 모델이 **디스크에서 많은 데이터를 읽어야** 하기 때문입니다. 따라서 모든 요청에 대해 모델을 매번 로드하고 싶지 않습니다. + +모듈/파일의 최상위에서 모델을 로드할 수도 있지만, 그러면 **모델을 로드하는데** 시간이 걸리기 때문에, 단순한 자동화된 테스트를 실행할 때도 모델이 로드될 때까지 기다려야 해서 **테스트 속도가 느려집니다**. + +이 문제를 해결하려고 하는 것입니다. 요청을 처리하기 전에 모델을 로드하되, 애플리케이션이 요청을 받기 시작하기 직전에만 로드하고, 코드가 로드되는 동안은 로드하지 않도록 하겠습니다. + +## Lifespan + +`FastAPI` 애플리케이션의 `lifespan` 매개변수와 "컨텍스트 매니저"를 사용하여 *시작*과 *종료* 로직을 정의할 수 있습니다. (컨텍스트 매니저가 무엇인지 잠시 후에 설명드리겠습니다.) + +예제를 통해 시작하고, 그 후에 자세히 살펴보겠습니다. + +우리는 `yield`를 사용하여 비동기 함수 `lifespan()`을 다음과 같이 생성합니다: + +{* ../../docs_src/events/tutorial003.py hl[16,19] *} + +여기서 우리는 모델을 로드하는 비싼 *시작* 작업을 시뮬레이션하고 있습니다. `yield` 앞에서 (가짜) 모델 함수를 머신러닝 모델이 담긴 딕셔너리에 넣습니다. 이 코드는 **애플리케이션이 요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다. + +그리고 `yield` 직후에는 모델을 언로드합니다. 이 코드는 **애플리케이션이 요청 처리 완료 후**, *종료* 직전에 실행됩니다. 예를 들어, 메모리나 GPU와 같은 자원을 해제하는 작업을 할 수 있습니다. + +/// tip | 팁 + +`shutdown`은 애플리케이션을 **종료**할 때 발생합니다. + +새로운 버전을 시작해야 하거나, 그냥 실행을 멈추고 싶을 수도 있습니다. 🤷 /// -## `startup` 이벤트 +### Lifespan 함수 -응용 프로그램을 시작하기 전에 실행하려는 함수를 "startup" 이벤트로 선언합니다: +먼저 주목할 점은, `yield`를 사용하여 비동기 함수(async function)를 정의하고 있다는 것입니다. 이는 `yield`를 사용한 의존성과 매우 유사합니다. + +{* ../../docs_src/events/tutorial003.py hl[14:19] *} + +함수의 첫 번째 부분, 즉 `yield` 이전의 코드는 애플리케이션이 시작되기 **전에** 실행됩니다. + +그리고 `yield` 이후의 부분은 애플리케이션이 완료된 후 **나중에** 실행됩니다. + +### 비동기 컨텍스트 매니저 + +함수를 확인해보면, `@asynccontextmanager`로 장식되어 있습니다. + +이것은 함수를 "**비동기 컨텍스트 매니저**"라고 불리는 것으로 변환시킵니다. + +{* ../../docs_src/events/tutorial003.py hl[1,13] *} + +파이썬에서 **컨텍스트 매니저**는 `with` 문에서 사용할 수 있는 것입니다. 예를 들어, `open()`은 컨텍스트 매니저로 사용할 수 있습니다: + +```Python +with open("file.txt") as file: + file.read() +``` +최근 버전의 파이썬에서는 **비동기 컨텍스트 매니저**도 있습니다. 이를 `async with`와 함께 사용합니다: + +```Python +async with lifespan(app): + await do_stuff() +``` + +컨텍스트 매니저나 위와 같은 비동기 컨텍스트 매니저를 만들면, `with` 블록에 들어가기 전에 `yield` 이전의 코드가 실행되고, `with` 블록을 벗어난 후에는 `yield` 이후의 코드가 실행됩니다. + +위의 코드 예제에서는 직접 사용하지 않고, FastAPI에 전달하여 사용하도록 합니다. + +`FastAPI` 애플리케이션의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받기 때문에, 새로운 `lifespan` 비동기 컨텍스트 매니저를 FastAPI에 전달할 수 있습니다. + +{* ../../docs_src/events/tutorial003.py hl[22] *} + +## 대체 이벤트 (사용 중단) + +/// warning | 경고 + +*시작*과 *종료*를 처리하는 권장 방법은 위에서 설명한 대로 `FastAPI` 애플리케이션의 `lifespan` 매개변수를 사용하는 것입니다. `lifespan` 매개변수를 제공하면 `startup`과 `shutdown` 이벤트 핸들러는 더 이상 호출되지 않습니다. `lifespan`을 사용할지, 모든 이벤트를 사용할지 선택해야 하며 둘 다 사용할 수는 없습니다. + +이 부분은 건너뛰셔도 좋습니다. + +/// + +*시작*과 *종료* 동안 실행될 이 로직을 정의하는 대체 방법이 있습니다. + +애플리케이션이 시작되기 전에 또는 종료될 때 실행해야 하는 이벤트 핸들러(함수)를 정의할 수 있습니다. + +이 함수들은 `async def` 또는 일반 `def`로 선언할 수 있습니다. + +### `startup` 이벤트 + +애플리케이션이 시작되기 전에 실행되어야 하는 함수를 추가하려면, `"startup"` 이벤트로 선언합니다: {* ../../docs_src/events/tutorial001.py hl[8] *} -이 경우 `startup` 이벤트 핸들러 함수는 단순히 몇 가지 값으로 구성된 `dict` 형식의 "데이터베이스"를 초기화합니다. +이 경우, `startup` 이벤트 핸들러 함수는 "database"라는 항목(단지 `dict`)을 일부 값으로 초기화합니다. -하나 이상의 이벤트 핸들러 함수를 추가할 수도 있습니다. +여러 개의 이벤트 핸들러 함수를 추가할 수 있습니다. -그리고 응용 프로그램은 모든 `startup` 이벤트 핸들러가 완료될 때까지 요청을 받지 않습니다. +애플리케이션은 모든 `startup` 이벤트 핸들러가 완료될 때까지 요청을 받기 시작하지 않습니다. -## `shutdown` 이벤트 +### `shutdown` 이벤트 -응용 프로그램이 종료될 때 실행하려는 함수를 추가하려면 `"shutdown"` 이벤트로 선언합니다: +애플리케이션이 종료될 때 실행되어야 하는 함수를 추가하려면, `"shutdown"` 이벤트로 선언합니다: {* ../../docs_src/events/tutorial002.py hl[6] *} -이 예제에서 `shutdown` 이벤트 핸들러 함수는 `"Application shutdown"`이라는 텍스트가 적힌 `log.txt` 파일을 추가할 것입니다. +여기서, `shutdown` 이벤트 핸들러 함수는 `"Application shutdown"`이라는 텍스트를 `log.txt` 파일에 기록합니다. /// info | 정보 -`open()` 함수에서 `mode="a"`는 "추가"를 의미합니다. 따라서 이미 존재하는 파일의 내용을 덮어쓰지 않고 새로운 줄을 추가합니다. +`open()` 함수에서 `mode="a"`는 "추가"를 의미하므로, 파일에 있는 기존 내용은 덮어쓰지 않고 새로운 줄이 추가됩니다. /// /// tip | 팁 -이 예제에서는 파일과 상호작용 하기 위해 파이썬 표준 함수인 `open()`을 사용하고 있습니다. +이 경우, 우리는 표준 파이썬 `open()` 함수를 사용하여 파일과 상호작용하고 있습니다. -따라서 디스크에 데이터를 쓰기 위해 "대기"가 필요한 I/O (입력/출력) 작업을 수행합니다. +따라서 I/O(입출력) 작업이 포함되어 있어 디스크에 기록되는 것을 "기다리는" 과정이 필요합니다. -그러나 `open()`은 `async`와 `await`을 사용하지 않기 때문에 이벤트 핸들러 함수는 `async def`가 아닌 표준 `def`로 선언하고 있습니다. +하지만 `open()`은 `async`와 `await`를 사용하지 않습니다. + +그래서 우리는 이벤트 핸들러 함수를 `async def` 대신 일반 `def`로 선언합니다. /// +### `startup`과 `shutdown`을 함께 사용 + +*시작*과 *종료* 로직이 연결될 가능성이 높습니다. 예를 들어, 무언가를 시작한 후 끝내거나, 자원을 획득한 후 해제하는 등의 작업을 할 수 있습니다. + +이러한 작업을 별도의 함수로 처리하면 서로 로직이나 변수를 공유하지 않기 때문에 더 어려워집니다. 값들을 전역 변수에 저장하거나 비슷한 트릭을 사용해야 할 수 있습니다. + +그렇기 때문에 위에서 설명한 대로 `lifespan`을 사용하는 것이 권장됩니다. + +## 기술적 세부사항 + +호기심 많은 분들을 위한 기술적인 세부사항입니다. 🤓 + +ASGI 기술 사양에 따르면, 이는 Lifespan Protocol의 일부이며, `startup`과 `shutdown`이라는 이벤트를 정의합니다. + /// info | 정보 -이벤트 핸들러에 관한 내용은 Starlette 이벤트 문서에서 추가로 확인할 수 있습니다. +Starlette의 `lifespan` 핸들러에 대해 더 읽고 싶다면 Starlette의 Lifespan 문서에서 확인할 수 있습니다. + +이 문서에는 코드의 다른 영역에서 사용할 수 있는 lifespan 상태를 처리하는 방법도 포함되어 있습니다. /// + +## 서브 애플리케이션 + +🚨 이 lifespan 이벤트(`startup`과 `shutdown`)는 메인 애플리케이션에 대해서만 실행되며, [서브 애플리케이션 - Mounts](sub-applications.md){.internal-link target=_blank}에는 실행되지 않음을 유의하세요. From 57a7a706f3faeff2f8cc2e30fc230995a730fdf3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:34:17 +0000 Subject: [PATCH 127/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4364e367d..a20041b48 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Update Korean translation for `docs/ko/docs/advanced/events.md`. PR [#13487](https://github.com/fastapi/fastapi/pull/13487) by [@bom1215](https://github.com/bom1215). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/handling-errors.md` page. PR [#13420](https://github.com/fastapi/fastapi/pull/13420) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-form-models.md`. PR [#13552](https://github.com/fastapi/fastapi/pull/13552) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). * 📝 Fix internal anchor link in Spanish deployment docs. PR [#13737](https://github.com/fastapi/fastapi/pull/13737) by [@fabianfalon](https://github.com/fabianfalon). From 44c83dda0bd0aab1c5e54e7a8f0807add65040d6 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Fri, 30 May 2025 16:34:34 +0300 Subject: [PATCH 128/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/cors.md`=20page=20(#13519)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/cors.md | 89 +++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/uk/docs/tutorial/cors.md diff --git a/docs/uk/docs/tutorial/cors.md b/docs/uk/docs/tutorial/cors.md new file mode 100644 index 000000000..95b204d0f --- /dev/null +++ b/docs/uk/docs/tutorial/cors.md @@ -0,0 +1,89 @@ +# CORS (Обмін ресурсами між різними джерелами) + +CORS або "Обмін ресурсами між різними джерелами" є ситуація, коли фронтенд, що працює в браузері, містить JavaScript-код, який взаємодіє з бекендом, розташованим в іншому "джерелі" (origin). + +## Джерело (Origin) + +Джерело визначається комбінацією протоколу (`http`, `https`), домену (`myapp.com`, `localhost`, `localhost.tiangolo.com`), порту (`80`, `443`, `8080`). + + +Наприклад, такі адреси вважаються різними джерелами: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +Навіть якщо вони всі містять `localhost`, вони мають різні протоколи або порти, що робить їх окремими "джерелами". + +## Кроки + +Припустимо, що Ваш фронтенд працює в браузері на `http://localhost:8080`, а його JavaScript намагається відправити запит до бекенду, який працює на `http://localhost` (Оскільки ми не вказуємо порт, браузер за замовчуванням припускає порт `80`). + +Потім браузер надішле HTTP-запит `OPTIONS` до бекенду на порту `:80`, і якщо бекенд надішле відповідні заголовки, що дозволяють комунікацію з цього іншого джерела (`http://localhost:8080`), тоді браузер на порту `:8080` дозволить JavaScript у фронтенді надіслати свій запит до бекенду на порту `:80`. + +Щоб досягти цього, бекенд на порту `:80` повинен мати список "дозволених джерел". + +У цьому випадку список має містити `http://localhost:8080`, щоб фронтенд на порту `:8080` працював коректно. + +## Символьне підставляння + +Можна також оголосити список як `"*"` ("символьне підставляння"), що означає дозвіл для всіх джерел. + +Однак це дозволить лише певні типи комунікації, виключаючи все, що пов'язане з обліковими даними: Cookies, заголовки авторизації, такі як ті, що використовуються з Bearer токенами тощо. + +Тому для коректної роботи краще явно вказувати дозволені джерела. + +## Використання `CORSMiddleware` + +Ви можете налаштувати це у Вашому додатку **FastAPI** за допомогою `CORSMiddleware`. + +* Імпортуйте `CORSMiddleware`. +* Створіть список дозволених джерел (у вигляді рядків). +* Додайте його як "middleware" у Ваш додаток **FastAPI**. + + +Також можна вказати, чи дозволяє Ваш бекенд: + +* Облікові дані (заголовки авторизації, сookies, тощо). +* Конкретні HTTP-методи (`POST`, `PUT`) або всі за допомогою `"*"` +* Конкретні HTTP-заголовки або всі за допомогою `"*"`. + + +{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *} + +Параметри за замовчуванням у `CORSMiddleware` є досить обмеженими, тому Вам потрібно явно вказати конкретні джерела, методи або заголовки, щоб браузери могли використовувати їх у контексті запитів між різними доменами. + + +Підтримуються такі аргументи: + +* `allow_origins` - Список джерел, яким дозволено здійснювати міждоменні запити. Наприклад `['https://example.org', 'https://www.example.org']`. Ви можете використовувати ['*'], щоб дозволити всі джерела. +* `allow_origin_regex` - Рядок регулярного виразу для відповідності джерелам, яким дозволено здійснювати міждоменні запити. Наприклад, `'https://.*\.example\.org'`. +* `allow_methods` - Список HTTP-методів, дозволених для міждоменних запитів. За замовчуванням `['GET']`. Ви можете використовувати `['*']`, щоб дозволити всі стандартні методи. +* `allow_headers` - Список HTTP-заголовків, які підтримуються для міждоменних запитів. За замовчуванням `[]`. Ви можете використовувати `['*']`, щоб дозволити всі заголовки. Заголовки `Accept`, `Accept-Language`, `Content-Language` і `Content-Type` завжди дозволені для простих CORS-запитів. +* `allow_credentials` - Визначає, чи підтримуються файли cookie для міждоменних запитів. За замовчуванням `False`. Також, якщо потрібно дозволити обмін обліковими даними (`allow_credentials = True`), параметр `allow_origins` не може бути встановлений як `['*']`, необхідно вказати конкретні джерела. +* `expose_headers` - Вказує, які заголовки відповіді повинні бути доступні для браузера. За замовчуванням `[]`. +* `max_age` - Встановлює максимальний час (у секундах) для кешування CORS-відповідей у браузерах. За замовчуванням `600`. + +Цей middleware обробляє два типи HTTP-запитів... + +### Попередні CORS-запити (preflight requests) + +Це будь-які `OPTIONS` - запити, що містять заголовки `Origin` та `Access-Control-Request-Method`. + +У такому випадку middleware перехопить вхідний запит і відповість відповідними CORS-заголовками, повертаючи або `200`, або `400` для інформаційних цілей. + +### Прості запити + +Будь-які запити із заголовком `Origin`. У цьому випадку middleware пропустить запит як звичайний, але додасть відповідні CORS-заголовки у відповідь. + +## Додаткова інформація + +Більше про CORS можна дізнатися в документації Mozilla. + +/// note | Технічні деталі + +Також можна використовувати `from starlette.middleware.cors import CORSMiddleware`. + +**FastAPI** надає кілька middleware у `fastapi.middleware` для зручності розробників. Але більшість доступних middleware походять безпосередньо зі Starlette. + +/// From 45a40f8b1ce8f1c4ad6fdf0cdae226f886735902 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Fri, 30 May 2025 16:34:53 +0300 Subject: [PATCH 129/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/background-tasks.md`=20pag?= =?UTF-8?q?e=20(#13502)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/background-tasks.md | 85 +++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/uk/docs/tutorial/background-tasks.md diff --git a/docs/uk/docs/tutorial/background-tasks.md b/docs/uk/docs/tutorial/background-tasks.md new file mode 100644 index 000000000..912ba8c2a --- /dev/null +++ b/docs/uk/docs/tutorial/background-tasks.md @@ -0,0 +1,85 @@ +# Фонові задачі + +Ви можете створювати фонові задачі, які будуть виконуватися *після* повернення відповіді. + +Це корисно для операцій, які потрібно виконати після обробки запиту, але клієнту не обов’язково чекати завершення цієї операції перед отриманням відповіді. + +Приклади використання: + +* Надсилання email-сповіщень після виконання певної дії: + * Підключення до поштового сервера та надсилання листа може займати кілька секунд. Ви можете відразу повернути відповідь, а email відправити у фоні. +* Обробка даних: + * Наприклад, якщо отримано файл, який потрібно обробити довготривалим процесом, можна повернути відповідь "Accepted" ("Прийнято", HTTP 202) і виконати обробку файлу у фоні. + +## Використання `BackgroundTasks` + +Спочатку імпортуйте `BackgroundTasks` і додайте його як параметр у Вашу *функцію операції шляху* (path operation function) до `BackgroundTasks`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *} + +**FastAPI** автоматично створить об'єкт `BackgroundTasks` і передасть його у цей параметр. + + +## Створення функції задачі + +Створіть функцію, яка буде виконувати фонову задачу. + +Це звичайна функція, яка може отримувати параметри. + +Вона може бути асинхронною `async def` або звичайною `def` функцією – **FastAPI** обробить її правильно. + +У нашому випадку функція записує у файл (імітуючи надсилання email). + +І оскільки операція запису не використовує `async` та `await`, ми визначаємо функцію як звичайну `def`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *} + +## Додавання фонової задачі + +Усередині Вашої *функції обробки шляху*, передайте функцію задачі в об'єкт *background tasks*, використовуючи метод `.add_task()`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[14] *} + +`.add_task()` приймає аргументи: + +* Функція задача, яка буде виконуватися у фоновому режимі (`write_notification`). Зверніть увагу, що передається обʼєкт без дужок. +* Будь-яка послідовність аргументів, які потрібно передати у функцію завдання у відповідному порядку (`email`). +* Будь-які іменовані аргументи, які потрібно передати у функцію задачу (`message="some notification"`). + +## Впровадження залежностей + +Використання `BackgroundTasks` також працює з системою впровадження залежностей. Ви можете оголосити параметр типу `BackgroundTasks` на різних рівнях: у *функції операції шляху*, у залежності (dependable), у під залежності тощо. + +**FastAPI** знає, як діяти в кожному випадку і як повторно використовувати один і той самий об'єкт, щоб усі фонові задачі були об’єднані та виконувалися у фоновому режимі після завершення основного запиту. + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + +У цьому прикладі повідомлення будуть записані у файл `log.txt` *після* того, як відповідь буде надіслана. + +Якщо у запиті був переданий query-параметр, він буде записаний у лог у фоновій задачі. + +А потім інша фонова задача, яка створюється у *функції операції шляху*, запише повідомлення з використанням path параметра `email`. + +## Технічні деталі + +Клас `BackgroundTasks` походить безпосередньо з `starlette.background`. + +Він імпортується безпосередньо у FastAPI, щоб Ви могли використовувати його з `fastapi` і випадково не імпортували `BackgroundTask` (без s в кінці) з `starlette.background`. + +Якщо використовувати лише `BackgroundTasks` (а не `BackgroundTask`), то його можна передавати як параметр у *функції операції шляху*, і **FastAPI** подбає про все інше, так само як і про використання об'єкта `Request`. + +Також можна використовувати `BackgroundTask` окремо в FastAPI, але для цього Вам доведеться створити об'єкт у коді та повернути Starlette `Response`, включаючи його. + +Детальніше можна почитати в офіційній документації Starlette про фонові задачі . + +## Застереження + +Якщо Вам потрібно виконувати складні фонові обчислення, і при цьому нема потреби запускати їх у тому ж процесі (наприклад, не потрібно спільного доступу до пам’яті чи змінних), можливо, варто скористатися більш потужними інструментами, такими як Celery. + +Такі інструменти зазвичай потребують складнішої конфігурації та менеджера черги повідомлень/завдань, наприклад, RabbitMQ або Redis. Однак вони дозволяють виконувати фонові задачі в кількох процесах і навіть на кількох серверах. + +Якщо ж Вам потрібно отримати доступ до змінних і об’єктів із тієї ж **FastAPI** - програми або виконувати невеликі фонові завдання (наприклад, надсилати сповіщення електронною поштою), достатньо просто використовувати `BackgroundTasks`. + +## Підсумок + +Імпортуйте та використовуйте `BackgroundTasks` як параметр у *функціях операції шляху* та залежностях, щоб додавати фонові задачі. From c83a5bf14975a2aaec0c1ec1a0d14da51e5aaea2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:35:17 +0000 Subject: [PATCH 130/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a20041b48..9bab975b5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cors.md` page. PR [#13519](https://github.com/fastapi/fastapi/pull/13519) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Update Korean translation for `docs/ko/docs/advanced/events.md`. PR [#13487](https://github.com/fastapi/fastapi/pull/13487) by [@bom1215](https://github.com/bom1215). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/handling-errors.md` page. PR [#13420](https://github.com/fastapi/fastapi/pull/13420) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-form-models.md`. PR [#13552](https://github.com/fastapi/fastapi/pull/13552) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). From 950fb3f02d876a4ab6cad307dc0f4d4e9a83e8ab Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:35:25 +0000 Subject: [PATCH 131/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9bab975b5..ef6420ff1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/background-tasks.md` page. PR [#13502](https://github.com/fastapi/fastapi/pull/13502) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cors.md` page. PR [#13519](https://github.com/fastapi/fastapi/pull/13519) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Update Korean translation for `docs/ko/docs/advanced/events.md`. PR [#13487](https://github.com/fastapi/fastapi/pull/13487) by [@bom1215](https://github.com/bom1215). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/handling-errors.md` page. PR [#13420](https://github.com/fastapi/fastapi/pull/13420) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 3337c3b9be8154804935e529f22fd50b3956ec37 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Fri, 30 May 2025 16:35:33 +0300 Subject: [PATCH 132/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/middleware.md`=20page=20(#?= =?UTF-8?q?13520)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uk/docs/tutorial/middleware.md | 75 +++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 docs/uk/docs/tutorial/middleware.md diff --git a/docs/uk/docs/tutorial/middleware.md b/docs/uk/docs/tutorial/middleware.md new file mode 100644 index 000000000..807be484a --- /dev/null +++ b/docs/uk/docs/tutorial/middleware.md @@ -0,0 +1,75 @@ +# Middleware (Проміжний шар) + +У **FastAPI** можна додавати middleware (проміжний шар). + +"Middleware" — це функція, яка працює з кожним **запитом** перед його обробкою будь-якою конкретною *операцією шляху* (*path operation*), а також з кожною **відповіддю** перед її поверненням. + +* Middleware отримує кожен **запит**, що надходить до Вашого застосунку. +* Може виконати певні дії із цим **запитом** або запустити необхідний код. +* Далі передає **запит** для обробки основним застосунком (*операцією шляху*). +* Отримує **відповідь**, сформовану застосунком (*операцією шляху*). +* Може змінити цю **відповідь** або виконати додатковий код. +* Повертає **відповідь** клієнту. + +/// note | Технічні деталі + +Якщо у Вас є залежності з `yield`, код виходу виконається *після* middleware. + +Якщо були заплановані фонові задачі (background tasks - розглянуто далі), вони виконаються *після* всіх middleware. + +/// + +## Створення middleware + +Щоб створити middleware, Ви використовуєте декоратор `@app.middleware("http")` на функції. + +Функція middleware отримує: + +* `Запит`. +* Функцію `call_next`, яка приймає `запит` як параметр. + * Ця функція передає `запит` відповідній *операції шляху*. + * Потім вона повертає `відповідь`, згенеровану цією *операцією шляху*. + +* Ви можете ще змінити `відповідь` перед тим, як повернути її. + + +{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *} + +/// tip | Порада + +Не забувайте, що власні заголовки можна додавати, використовуючи префікс 'X-'. + +Але якщо у Вас є власні заголовки, які Ви хочете, щоб браузерний клієнт міг побачити, потрібно додати їх до Вашої конфігурації CORS (див. [CORS (Обмін ресурсами між різними джерелами)](cors.md){.internal-link target=_blank} за допомогою параметра `expose_headers`, описаного в документації Starlette по CORS. + +/// + +/// note | Технічні деталі + +Ви також можете використати `from starlette.requests import Request`. + +**FastAPI** надає це для Вашої зручності як розробника. Але він походить безпосередньо зі Starlette. + +/// + +### До і після `response`(`відповіді`) + +Ви можете додати код, який буде виконуватися з `запитом` (`request`), до того, як його обробить будь-яка *операція шляху* (*path operation*). + +Також Ви можете додати код, який буде виконуватися після того, як `відповідь` (`response`) буде згенеровано, перед тим як його повернути. + +Наприклад, Ви можете додати власний заголовок `X-Process-Time`, який міститиме час у секундах, який витратився на обробку запиту та генерацію відповіді: + +{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *} + + +/// tip | Підказка + +Тут ми використовуємо `time.perf_counter()` замість `time.time()` оскільки він може бути більш точним для таких випадків. 🤓 + +/// + +## Інші middlewares + +Ви можете пізніше прочитати більше про інші middlewares в [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}. + +Ви дізнаєтесь, як обробляти CORS за допомогою middleware в наступному розділі. From d6b8b8f59066101296d1bac270247c22d9a2912a Mon Sep 17 00:00:00 2001 From: Valentyn Date: Fri, 30 May 2025 16:35:49 +0300 Subject: [PATCH 133/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/path-params-numeric-valida?= =?UTF-8?q?tions.md`=20page=20(#13548)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../path-params-numeric-validations.md | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 docs/uk/docs/tutorial/path-params-numeric-validations.md diff --git a/docs/uk/docs/tutorial/path-params-numeric-validations.md b/docs/uk/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 000000000..281ee183c --- /dev/null +++ b/docs/uk/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,165 @@ +# Path Параметри та валідація числових даних + +Так само як Ви можете оголошувати додаткові перевірки та метадані для query параметрів за допомогою `Query`, Ви можете оголошувати той самий тип перевірок і метаданих для параметрів шляху за допомогою `Path`. + +## Імпорт Path + +Спочатку імпортуйте `Path` з `fastapi` і імпортуйте `Annotated`: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} + +/// info | Інформація + +FastAPI додав підтримку `Annotated` (і почав рекомендувати його використання) у версії 0.95.0. + +Якщо у Вас стара версія, при спробі використати `Annotated` можуть виникати помилки. + +Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} принаймні до версії 0.95.1 перед використанням `Annotated`. + +/// + +## Оголошення метаданих + +Ви можете оголошувати всі ті ж параметри, що і для `Query`. + +Наприклад, щоб оголосити значення метаданих `title` для параметра шляху `item_id`, Ви можете написати: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} + +/// note | Примітка + +Параметр шляху завжди є обов’язковим, оскільки він має бути частиною шляху. Навіть якщо Ви оголосите його зі значенням `None` або встановите значення за замовчуванням — він все одно залишатиметься обов’язковим. + +/// + +## Упорядковуйте параметри, як Вам потрібно + +/// tip | Підказка + +Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`. + +/// + +Припустимо, Ви хочете оголосити параметр запиту `q` як обов’язковий `str`. + +І Вам не потрібно оголошувати нічого іншого для цього параметра, тому немає потреби використовувати `Query`. + +Але Вам все одно потрібно використовувати `Path` для параметра шляху `item_id`. І з певних причин Ви не хочете використовувати `Annotated`. + +Python видасть помилку, якщо розмістити значення з "default" перед значенням, яке не має "default". + +Але Ви можете змінити порядок і розмістити значення без значення за замовчуванням (параметр запиту `q`) першим. + + +Для **FastAPI** порядок не має значення. Він визначає параметри за їх іменами, типами та значеннями за замовчуванням (`Query`, `Path` тощо) і не звертає уваги на порядок. + +Тому Ви можете оголосити Вашу функцію так: + +//// tab | Python 3.8 non-Annotated + +/// tip | Підказка + +За можливості віддавайте перевагу версії з використанням `Annotated`. + +/// + +{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} + +//// + +Але майте на увазі, що якщо Ви використовуєте `Annotated`, ця проблема не виникне, оскільки Ви не використовуєте значення за замовчуванням для параметрів `Query()` або `Path()`. + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} + +## Упорядковуйте параметри за потребою, хитрощі + +/// tip | Підказка + +Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`. + +/// + +Ось **невелика хитрість**, яка може стати в пригоді, хоча вона рідко знадобиться. + +Якщо Ви хочете: + +* оголосити параметр запиту `q` без використання `Query` або значення за замовчуванням +* оголосити параметр шляху `item_id`, використовуючи `Path` +* розмістити їх у різному порядку +* не використовувати `Annotated` + +...у Python є спеціальний синтаксис для цього. + +Передайте `*` як перший параметр функції. + +Python нічого не зробить із цією `*`, але розпізнає, що всі наступні параметри слід викликати як аргументи за ключовим словом (пари ключ-значення), також відомі як kwargs. Навіть якщо вони не мають значення за замовчуванням. + +{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *} + +### Краще з `Annotated` + +Майте на увазі, якщо Ви використовуєте `Annotated`, оскільки Ви не використовуєте значення за замовчуванням для параметрів функції, цієї проблеми не виникне, і, швидше за все, Вам не потрібно буде використовувати `*`. + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} + +## Валідація числових даних: більше або дорівнює + +За допомогою `Query` і `Path` (та інших, які Ви побачите пізніше) можна оголошувати числові обмеження. + +Тут, завдяки `ge=1`, `item_id` має бути цілим числом, яке "`g`reater than or `e`qual" (більше або дорівнює) `1`. + +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} + +## Валідація числових даних: більше ніж і менше або дорівнює + +Те саме застосовується до: + +* `gt`: `g`reater `t`han (більше ніж) +* `le`: `l`ess than or `e`qual (менше або дорівнює) + +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} + +## Валідація числових даних: float, більше ніж і менше ніж + +Валідація чисел також працює для значень типу `float`. + +Ось де стає важливо мати можливість оголошувати gt, а не тільки ge. Це дозволяє, наприклад, вимагати, щоб значення було більше `0`, навіть якщо воно менше `1`. + +Таким чином, значення `0.5` буде допустимим. Але `0.0` або `0` — ні. + +Те саме стосується lt. + +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} + +## Підсумок + +За допомогою `Query`, `Path` (і інших параметрів, які Ви ще не бачили) можна оголошувати метадані та перевірки рядків, так само як у [Query параметри та валідація рядків](query-params-str-validations.md){.internal-link target=_blank}. + +Також можна оголошувати числові перевірки: + +* `gt`: `g`reater `t`han (більше ніж) +* `ge`: `g`reater than or `e`qual (більше або дорівнює) +* `lt`: `l`ess `t`han (менше ніж) +* `le`: `l`ess than or `e`qual (менше або дорівнює) + +/// info | Інформація + +`Query`, `Path` та інші класи, які Ви побачите пізніше, є підкласами спільного класу `Param`. + +Всі вони мають однакові параметри для додаткових перевірок і метаданих, які Ви вже бачили. + +/// + +/// note | Технічні деталі + +Коли Ви імпортуєте `Query`, `Path` та інші з `fastapi`, насправді це функції. + +При виклику вони повертають екземпляри класів з такими ж іменами. + +Тобто Ви імпортуєте `Query`, яка є функцією. А коли Ви її викликаєте, вона повертає екземпляр класу, який теж називається `Query`. + +Ці функції створені таким чином (замість використання класів напряму), щоб Ваш редактор не відзначав їхні типи як помилки. + +Таким чином, Ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок. + +/// From 3855d808b0fd42766d23a3755ed3cb11217633c6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:36:27 +0000 Subject: [PATCH 134/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ef6420ff1..ace5fdd5b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/middleware.md` page. PR [#13520](https://github.com/fastapi/fastapi/pull/13520) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/background-tasks.md` page. PR [#13502](https://github.com/fastapi/fastapi/pull/13502) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cors.md` page. PR [#13519](https://github.com/fastapi/fastapi/pull/13519) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Update Korean translation for `docs/ko/docs/advanced/events.md`. PR [#13487](https://github.com/fastapi/fastapi/pull/13487) by [@bom1215](https://github.com/bom1215). From 57ed433befb782d45047944044ece386921cbd22 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:36:31 +0000 Subject: [PATCH 135/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ace5fdd5b..0a9275dda 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params-numeric-validations.md` page. PR [#13548](https://github.com/fastapi/fastapi/pull/13548) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/middleware.md` page. PR [#13520](https://github.com/fastapi/fastapi/pull/13520) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/background-tasks.md` page. PR [#13502](https://github.com/fastapi/fastapi/pull/13502) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cors.md` page. PR [#13519](https://github.com/fastapi/fastapi/pull/13519) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 7ebcd8761cf98b6010d2f818105f30f3db58d0ce Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 15:36:54 +0200 Subject: [PATCH 136/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13736)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.10 → v0.11.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.10...v0.11.11) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c7cee518..445676b8b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.10 + rev: v0.11.11 hooks: - id: ruff args: From bb05a685309817aab6b80f15ff7da9accecf87a9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:37:55 +0000 Subject: [PATCH 137/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0a9275dda..1b9cbd687 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -41,6 +41,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13736](https://github.com/fastapi/fastapi/pull/13736) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🔧 Update sponsors: Add InterviewPal. PR [#13728](https://github.com/fastapi/fastapi/pull/13728) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Google Analytics. PR [#13727](https://github.com/fastapi/fastapi/pull/13727) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove MongoDB. PR [#13725](https://github.com/fastapi/fastapi/pull/13725) by [@tiangolo](https://github.com/tiangolo). From 645d6457378e89fc2b21123db13386197225496e Mon Sep 17 00:00:00 2001 From: timothy <53824764+timothy-jeong@users.noreply.github.com> Date: Fri, 30 May 2025 22:38:33 +0900 Subject: [PATCH 138/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Korean=20translati?= =?UTF-8?q?on=20for=20`docs/ko/docs/tutorial/extra-models.md`=20(#13063)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ko/docs/tutorial/extra-models.md | 223 ++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 docs/ko/docs/tutorial/extra-models.md diff --git a/docs/ko/docs/tutorial/extra-models.md b/docs/ko/docs/tutorial/extra-models.md new file mode 100644 index 000000000..8e4559061 --- /dev/null +++ b/docs/ko/docs/tutorial/extra-models.md @@ -0,0 +1,223 @@ +# 추가 모델 + +지난 예제에 이어서, 연관된 모델을 여러개 갖는 것은 흔한 일입니다. + +특히 사용자 모델의 경우에 그러한데, 왜냐하면: + +* **입력 모델** 은 비밀번호를 가져야 합니다. +* **출력 모델** 은 비밀번호를 가지면 안됩니다. +* **데이터베이스 모델** 은 해시처리된 비밀번호를 가질 것입니다. + +/// danger | 위험 + +절대 사용자의 비밀번호를 평문으로 저장하지 마세요. 항상 이후에 검증 가능한 "안전한 해시(secure hash)"로 저장하세요. + +만약 이게 무엇인지 모르겠다면, [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.에서 비밀번호 해시에 대해 배울 수 있습니다. + +/// + +## 다중 모델 + +아래는 비밀번호 필드와 해당 필드가 사용되는 위치를 포함하여, 각 모델들이 어떤 형태를 가질 수 있는지 전반적인 예시입니다: + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + + +/// info | 정보 + +Pydantic v1에서는 해당 메서드가 `.dict()`로 불렸으며, Pydantic v2에서는 `.model_dump()`로 이름이 변경되었습니다. `.dict()`는 여전히 지원되지만 더 이상 권장되지 않습니다. + +여기에서 사용하는 예제는 Pydantic v1과의 호환성을 위해 `.dict()`를 사용하지만, Pydantic v2를 사용할 수 있다면 `.model_dump()`를 사용하는 것이 좋습니다. + +/// + +### `**user_in.dict()` 에 대하여 + +#### Pydantic의 `.dict()` + +`user_in`은 Pydantic 모델 클래스인 `UserIn`입니다. + +Pydantic 모델은 모델 데이터를 포함한 `dict`를 반환하는 `.dict()` 메서드를 제공합니다. + +따라서, 다음과 같이 Pydantic 객체 `user_in`을 생성할 수 있습니다: + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +그 다음, 다음과 같이 호출합니다: + +```Python +user_dict = user_in.dict() +``` + +이제 변수 `user_dict`에 데이터가 포함된 `dict`를 가지게 됩니다(이는 Pydantic 모델 객체가 아닌 `dict`입니다). + +그리고 다음과 같이 호출하면: + +```Python +print(user_dict) +``` + +Python의 `dict`가 다음과 같이 출력됩니다: + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### `dict` 언패킹(Unpacking) + +`user_dict`와 같은 `dict`를 함수(또는 클래스)에 `**user_dict`로 전달하면, Python은 이를 "언팩(unpack)"합니다. 이 과정에서 `user_dict`의 키와 값을 각각 키-값 인자로 직접 전달합니다. + +따라서, 위에서 생성한 `user_dict`를 사용하여 다음과 같이 작성하면: + +```Python +UserInDB(**user_dict) +``` + +다음과 같은 결과를 생성합니다: + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +혹은 더 정확히 말하자면, `user_dict`를 직접 사용하는 것은, 나중에 어떤 값이 추가되더라도 아래와 동일한 효과를 냅니다: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### 다른 모델 데이터로 새 Pydantic 모델 생성 + +위의 예제에서 `user_in.dict()`로부터 `user_dict`를 생성한 것처럼, 아래 코드는: + +```Python +user_dict = user_in.dict() +UserInDB(**user_dict) +``` + +다음과 동일합니다: + +```Python +UserInDB(**user_in.dict()) +``` + +...왜냐하면 `user_in.dict()`는 `dict`이며, 이를 `**`로 Python이 "언팩(unpack)"하도록 하여 `UserInDB`에 전달하기 때문입니다. + +따라서, 다른 Pydantic 모델의 데이터를 사용하여 새로운 Pydantic 모델을 생성할 수 있습니다. + +#### `dict` 언패킹(Unpacking)과 추가 키워드 + +그리고 다음과 같이 추가 키워드 인자 `hashed_password=hashed_password`를 추가하면: + +```Python +UserInDB(**user_in.dict(), 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, +) +``` + +/// warning | 경고 + +추가적으로 제공된 함수 `fake_password_hasher`와 `fake_save_user`는 데이터 흐름을 시연하기 위한 예제일 뿐이며, 실제 보안을 제공하지 않습니다. + +/// + +## 중복 줄이기 + +코드 중복을 줄이는 것은 **FastAPI**의 핵심 아이디어 중 하나입니다. + +코드 중복은 버그, 보안 문제, 코드 비동기화 문제(한 곳은 업데이트되었지만 다른 곳은 업데이트되지 않는 문제) 등의 가능성을 증가시킵니다. + +그리고 이 모델들은 많은 데이터를 공유하면서 속성 이름과 타입을 중복하고 있습니다. + +더 나은 방법이 있습니다. + +`UserBase` 모델을 선언하여 다른 모델들의 기본(base)으로 사용할 수 있습니다. 그런 다음 이 모델을 상속받아 속성과 타입 선언(유형 선언, 검증 등)을 상속하는 서브클래스를 만들 수 있습니다. + +모든 데이터 변환, 검증, 문서화 등은 정상적으로 작동할 것입니다. + +이렇게 하면 각 모델 간의 차이점만 선언할 수 있습니다(평문 `password`가 있는 경우, `hashed_password`만 있는 경우, 혹은 비밀번호가 없는 경우): + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` 또는 `anyOf` + +두 가지 이상의 타입을 포함하는 `Union`으로 응답을 선언할 수 있습니다. 이는 응답이 그 중 하나의 타입일 수 있음을 의미합니다. + +OpenAPI에서는 이를 `anyOf`로 정의합니다. + +이를 위해 표준 Python 타입 힌트인 `typing.Union`을 사용할 수 있습니다: + +/// note | 참고 + +`Union`을 정의할때는 더 구체적인 타입을 먼저 포함하고, 덜 구체적인 타입을 그 뒤에 나열해야합니다. 아래 예제에서는 `Union[PlaneItem, CarItem]` 를 보면, 더 구체적인 `PlaneItem`이 `CarItem`보다 앞에 위치합니다. + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + + +### Python 3.10에서 `Union` + +위의 예제에서는 `response_model` 인자 값으로 `Union[PlaneItem, CarItem]`을 전달합니다. + +이 경우, 이를 **타입 어노테이션(type annotation)** 이 아닌 **인자 값(argument value)** 으로 전달하고 있기 때문에 Python 3.10에서도 `Union`을 사용해야 합니다. + +만약 타입 어노테이션에 사용한다면, 다음과 같이 수직 막대(|)를 사용할 수 있습니다: + +```Python +some_variable: PlaneItem | CarItem +``` + +하지만 이를 `response_model=PlaneItem | CarItem`과 같이 할당하면 에러가 발생합니다. 이는 Python이 이를 타입 어노테이션으로 해석하지 않고, `PlaneItem`과 `CarItem` 사이의 **잘못된 연산(invalid operation)**을 시도하기 때문입니다 + +## 모델 리스트 + +마찬가지로, 객체 리스트 형태의 응답을 선언할 수도 있습니다. + +이를 위해 표준 Python의 `typing.List`를 사용하세요(또는 Python 3.9 이상에서는 단순히 `list`를 사용할 수 있습니다): + +{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} + + +## 임의의 `dict` 응답 + +Pydantic 모델을 사용하지 않고, 키와 값의 타입만 선언하여 평범한 임의의 `dict`로 응답을 선언할 수도 있습니다. + +이는 Pydantic 모델에 필요한 유효한 필드/속성 이름을 사전에 알 수 없는 경우에 유용합니다. + +이 경우, `typing.Dict`를 사용할 수 있습니다(또는 Python 3.9 이상에서는 단순히 `dict`를 사용할 수 있습니다): + +{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} + + +## 요약 + +여러 Pydantic 모델을 사용하고, 각 경우에 맞게 자유롭게 상속하세요. + +엔터티가 서로 다른 "상태"를 가져야 하는 경우, 엔터티당 단일 데이터 모델을 사용할 필요는 없습니다. 예를 들어, 사용자 "엔터티"가 `password`, `password_hash`, 또는 비밀번호가 없는 상태를 포함할 수 있는 경우처럼 말입니다. From cadb7f5c3a085ce1a88795f4a377067b93370b5f Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 13:38:55 +0000 Subject: [PATCH 139/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1b9cbd687..3164dbe79 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-models.md`. PR [#13063](https://github.com/fastapi/fastapi/pull/13063) by [@timothy-jeong](https://github.com/timothy-jeong). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params-numeric-validations.md` page. PR [#13548](https://github.com/fastapi/fastapi/pull/13548) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/middleware.md` page. PR [#13520](https://github.com/fastapi/fastapi/pull/13520) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/background-tasks.md` page. PR [#13502](https://github.com/fastapi/fastapi/pull/13502) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 02ca76136596aa1089764e545a4f408075fb4ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B3=D0=BE=D1=80=20=D0=9E=D0=BD=D0=B8=D1=89=D1=83?= =?UTF-8?q?=D0=BA?= <120256301+EgorOnishchuk@users.noreply.github.com> Date: Fri, 30 May 2025 17:14:42 +0300 Subject: [PATCH 140/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translat?= =?UTF-8?q?ion=20for=20`docs/ru/docs/tutorial/cookie-param-models.md`=20(#?= =?UTF-8?q?13616)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/docs/tutorial/cookie-param-models.md | 76 ++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/ru/docs/tutorial/cookie-param-models.md diff --git a/docs/ru/docs/tutorial/cookie-param-models.md b/docs/ru/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..3a57443bb --- /dev/null +++ b/docs/ru/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Модели параметров cookie + +Если у вас есть группа **cookies**, которые связаны между собой, вы можете создать **Pydantic-модель** для их объявления. 🍪 + +Это позволит вам **переиспользовать модель** в **разных местах**, а также объявить проверки и метаданные сразу для всех параметров. 😎 + +/// note | Заметка + +Этот функционал доступен с версии `0.115.0`. 🤓 + +/// + +/// tip | Совет + +Такой же подход применяется для `Query`, `Cookie`, и `Header`. 😎 + +/// + +## Pydantic-модель для cookies + +Объявите параметры **cookie**, которые вам нужны, в **Pydantic-модели**, а затем объявите параметр как `Cookie`: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** **извлечёт** данные для **каждого поля** из **cookies**, полученных в запросе, и выдаст вам объявленную Pydantic-модель. + +## Проверка сгенерированной документации + +Вы можете посмотреть объявленные cookies в графическом интерфейсе Документации по пути `/docs`: + +
+ +
+ +/// info | Дополнительная информация + +Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и под капотом, они **не** позволят **JavaScript** легко получить доступ к ним. + +Если вы перейдёте к **графическому интерфейсу документации API** по пути `/docs`, то сможете увидеть **документацию** по cookies для ваших *операций путей*. + +Но даже если вы **заполните данные** и нажмёте "Execute", поскольку графический интерфейс Документации работает с **JavaScript**, cookies не будут отправлены, и вы увидите сообщение об **ошибке** как будто не указывали никаких значений. + +/// + +## Запрет дополнительных cookies + +В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** cookies, которые вы хотите получать. + +Теперь ваш API сам решает, принимать ли cookies. 🤪🍪 + +Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (`forbid`) любые дополнительные (`extra`) поля: + +{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} + +Если клиент попробует отправить **дополнительные cookies**, то в ответ он получит **ошибку**. + +Бедные баннеры cookies, они всеми силами пытаются получить ваше согласие — и всё ради того, чтобы API его отклонил. 🍪 + +Например, если клиент попытается отправить cookie `santa_tracker` со значением `good-list-please`, то в ответ он получит **ошибку**, сообщающую ему, что cookie `santa_tracker` не разрешён: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please" + } + ] +} +``` + +## Заключение + +Вы можете использовать **Pydantic-модели** для объявления **cookies** в **FastAPI**. 😎 From be6cfd6cf508c2a4f699815be327e98c7b9ffe2c Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 14:15:08 +0000 Subject: [PATCH 141/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3164dbe79..0d2601530 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-param-models.md`. PR [#13616](https://github.com/fastapi/fastapi/pull/13616) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). * 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-models.md`. PR [#13063](https://github.com/fastapi/fastapi/pull/13063) by [@timothy-jeong](https://github.com/timothy-jeong). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params-numeric-validations.md` page. PR [#13548](https://github.com/fastapi/fastapi/pull/13548) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/middleware.md` page. PR [#13520](https://github.com/fastapi/fastapi/pull/13520) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From e48c526b62b209923d77f96ac8aed143da2e7860 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Fri, 30 May 2025 17:17:24 +0300 Subject: [PATCH 142/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/query-params-str-validatio?= =?UTF-8?q?ns.md`=20page=20(#13546)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tutorial/query-params-str-validations.md | 491 ++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 docs/uk/docs/tutorial/query-params-str-validations.md diff --git a/docs/uk/docs/tutorial/query-params-str-validations.md b/docs/uk/docs/tutorial/query-params-str-validations.md new file mode 100644 index 000000000..cd3f4ad93 --- /dev/null +++ b/docs/uk/docs/tutorial/query-params-str-validations.md @@ -0,0 +1,491 @@ +# Query параметри та валідація рядків + +**FastAPI** дозволяє оголошувати додаткову інформацію та виконувати валідацію для Ваших параметрів. + +Розглянемо цей додаток як приклад: + +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} + +Query параметр `q` має тип `str | None`, що означає, що він може бути як `str`, так і `None`. За замовчуванням він має значення `None`, тому FastAPI розуміє, що цей параметр не є обов'язковим. + +/// note | Примітка + +FastAPI знає, що `q` не є обов’язковим, завдяки значенню за замовчуванням `= None`. + +Використання `str | None` дозволить Вашому редактору коду надавати кращу підтримку та виявляти помилки. + +/// + +## Додаткова валідація + +Ми хочемо, щоб навіть якщо `q` є необов’язковим, **його довжина не перевищувала 50 символів**, якщо він все ж буде переданий. + +### Імпорт `Query` та `Annotated` + +Щоб це зробити, спочатку імпортуємо: + +* `Query` з `fastapi` +* `Annotated` з `typing` + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// info | Інформація + +FastAPI додав підтримку `Annotated` (і почав рекомендувати його) у версії 0.95.0. + +Якщо у Вас старіша версія, під час використання `Annotated` можуть виникати помилки. + +Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} до принаймні 0.95.1, перш ніж використовувати `Annotated`. + +/// + +## Використання `Annotated` у типі параметра `q` + +Пам’ятаєте, як я раніше розповідав, що `Annotated` можна використовувати для додавання метаданих до параметрів у [Вступі до типів Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}? + +Зараз саме час використати його разом із FastAPI. 🚀 + +Раніше ми мали таку анотацію типу: + +//// tab | Python 3.10+ + +```Python +q: str | None = None +``` + +//// + +//// tab | Python 3.8+ + +```Python +q: Union[str, None] = None +``` + +//// + +Тепер ми загорнемо її у `Annotated`, і отримаємо: + +//// tab | Python 3.10+ + +```Python +q: Annotated[str | None] = None +``` + +//// + +//// tab | Python 3.8+ + +```Python +q: Annotated[Union[str, None]] = None +``` + +//// + +Обидві ці версії означають одне й те саме: `q` — це параметр, який може бути `str` або `None`, і за замовчуванням має значення `None`. + +А тепер переходимо до цікавого! 🎉 + +## Додавання `Query` до `Annotated` у параметр `q` + +Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (зокрема валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`: + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +Зверніть увагу, що значення за замовчуванням усе ще `None`, тому параметр залишається необов'язковим. + +Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо **додаткову валідацію** для цього значення — воно має містити максимум 50 символів. 😎 + +/// tip | Підказка + +Ми використовуємо `Query()`, оскільки це **query параметр**. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`. + +/// + +Тепер FastAPI: + +* **Перевірить** дані, щоб переконатися, що їхня довжина не перевищує 50 символів +* Покажe **чітку помилку** клієнту, якщо дані недійсні +* **Задокументує** параметр в OpenAPI-схемі *операції шляху* (що відобразиться в **автоматично згенерованій документації**) + +## Альтернативний (застарілий) метод: Query як значення за замовчуванням + +У попередніх версіях FastAPI (до 0.95.0) `Query` використовувався як значення за замовчуванням для параметра, а не всередині `Annotated`. Ви, ймовірно, побачите код, який використовує цей підхід, тому варто розглянути його. + +/// tip | Підказка + +Для нового коду та коли це можливо, використовуйте `Annotated`, як показано вище. Це має багато переваг (пояснених нижче) і не має недоліків. 🍰 + +/// + +Раніше ми писали `Query()` як значення за замовчуванням для параметра функції, встановлюючи `max_length` у 50: + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +Оскільки в цьому випадку (без `Annotated`) нам потрібно замінити `None` у функції на `Query()`, тепер ми повинні явно встановити значення за замовчуванням через параметр `Query(default=None)`. Це виконує ту саму роль визначення значення за замовчуванням (принаймні для FastAPI). + +Таким чином: + +```Python +q: str | None = Query(default=None) +``` + +...робить параметр необов’язковим зі значенням за замовчуванням `None`, що еквівалентно: + + +```Python +q: str | None = None +``` +Але у версії з `Query` ми явно вказуємо, що це query параметр. + +Далі ми можемо передавати `Query` додаткові параметри, зокрема `max_length`, який застосовується до рядків: + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у схемі OpenAPI *операції шляху*. + +### `Query` як значення за замовчуванням або всередині `Annotated` + +Важливо пам’ятати, якщо використовувати `Query` всередині `Annotated`, не можна задавати параметр `default` у `Query`. + +Замість цього використовуйте значення за замовчуванням у самій функції. Інакше це буде нелогічно. + +Наприклад, цей варіант є некоректним: + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +...тому, що не зрозуміло, яке значення має бути значенням за замовчуванням: `"rick"` чи `"morty"`. + +Коректні варіанти: + +```Python +q: Annotated[str, Query()] = "rick" +``` + +...або у старих кодових базах Ви знайдете: + +```Python +q: str = Query(default="rick") +``` + +### Переваги використання `Annotated` + +**Використання `Annotated` є рекомендованим** замість задання значення за замовчуванням у параметрах функції, оскільки воно **краще** з кількох причин. 🤓 + +Значення **за замовчуванням** параметра **функції** є його **фактичним значенням за замовчуванням**, що є більш інтуїтивним у Python загалом. 😌 + +Ви можете **викликати** ту саму функцію **в інших місцях** без FastAPI, і вона **працюватиме очікувано**. Якщо параметр є **обов’язковим** (без значення за замовчуванням), Ваш **редактор** повідомить про помилку, а **Python** також видасть помилку, якщо Ви виконаєте функцію без передавання цього параметра. + +Якщо Ви не використовуєте `Annotated`, а використовуєте **(старий) стиль значень за замовчуванням**, то при виклику цієї функції без FastAPI **в інших місцях**, потрібно **не забути** передати їй аргументи, інакше значення будуть відрізнятися від очікуваних (наприклад, Ви отримаєте `QueryInfo` або подібне замість `str`). Ваш редактор не повідомить про помилку, і Python також не видасть помилку при запуску функції, поки не виникне помилка під час виконання операцій усередині. + +Оскільки `Annotated` може містити кілька анотацій метаданих, Ви навіть можете використовувати ту саму функцію з іншими інструментами, такими як Typer. 🚀 + +## Додавання додаткових валідацій + +Ви також можете додати параметр `min_length`: + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## Додавання регулярних виразів + +Ви можете визначити регулярний вираз pattern, якому має відповідати параметр: + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +Цей конкретний шаблон регулярного виразу перевіряє, що отримане значення параметра: + +* `^`: починається з наступних символів, перед якими немає інших символів. +* `fixedquery`: точно відповідає значенню `fixedquery`. +* `$`: закінчується тут, після `fixedquery` немає жодних символів. + +Якщо Ви почуваєтеся розгублено щодо **"регулярних виразів"**, не хвилюйтеся. Вони є складною темою для багатьох людей. Ви все одно можете зробити багато речей без їх використання. + +Але тепер Ви знаєте, що коли вони знадобляться, їх можна застосовувати у **FastAPI**. + +### Pydantic v1 `regex` замість `pattern` + +До версії Pydantic 2 і FastAPI 0.100.0 параметр називався `regex` замість `pattern`, але тепер він застарів. + +Ви все ще можете зустріти код, який використовує його: + +//// tab | Pydantic v1 + +{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *} + +//// + +Але майте на увазі, що він є застарілим і його слід оновити до нового параметра `pattern`. 🤓 + +## Значення за замовчуванням + +Ви можете використовувати значення за замовчуванням, відмінні від `None`. + +Наприклад, якщо Ви хочете оголосити параметр запиту `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`: + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} + +/// note | Технічні деталі + +Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (not required). + +/// + +## Обов’язкові параметри + +Якщо нам не потрібно вказувати додаткові перевірки або метадані, ми можемо зробити параметр `q` обов’язковим, просто не оголошуючи значення за замовчуванням, наприклад: + +```Python +q: str +``` + +замість: + +```Python +q: str | None = None +``` + +Але тепер ми оголошуємо його з `Query`, наприклад: + +//// tab | Annotated + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +//// + +Тому, якщо Вам потрібно зробити значення обов’язковим, використовуючи `Query`, просто не вказуйте значення за замовчуванням: + +{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} + +### Обов’язкове значення, яке може бути `None` + +Ви можете вказати, що параметр може приймати `None`, але при цьому залишається обов’язковим. Це змусить клієнтів надіслати значення, навіть якщо воно дорівнює `None`. + +Щоб зробити це, оголосіть, що `None` є допустимим типом, але не вказуйте значення за замовчуванням: + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## Список параметрів запиту / кілька значень + +Якщо Ви визначаєте параметр запиту за допомогою `Query`, Ви також можете дозволити отримання списку значень, тобто дозволити отримання кількох значень. + +Наприклад, щоб дозволити параметру запиту `q` з'являтися кілька разів в URL, можна написати: + +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} + +Тоді, у випадку запиту за URL: + +``` +http://localhost:8000/items/?q=foo&q=bar +``` + +Ви отримаєте кілька значень *query параметра* `q` (`foo` і `bar`) у вигляді списку `list` в Python у Вашій *функції обробки шляху*, у *параметрі функції* `q`. + +Отже, відповідь на цей URL буде: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +/// tip | Підказка + +Щоб оголосити параметр запиту з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту. + +/// + +Інтерактивна API-документація оновиться відповідно, дозволяючи передавати кілька значень: + + + +### Список параметрів запиту / кілька значень за замовчуванням + +Ви також можете визначити значення за замовчуванням для `list`, якщо жодне значення не було передане: + +{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} + +Якщо Ви перейдете за посиланням: + +``` +http://localhost:8000/items/ +``` + +то значення `q` за замовчуванням буде: `["foo", "bar"]`, і Ваша відповідь виглядатиме так: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +#### Використання тільки `list` + +Ви також можете використовувати `list` без уточнення типу, замість `list[str]`: + +{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} + +/// note | Технічні деталі + +Майте на увазі, що в цьому випадку FastAPI не перевірятиме вміст списку. + +Наприклад, `list[int]` перевірятиме (і документуватиме), що всі елементи списку є цілими числами. Але `list` без уточнення цього не робитиме. + +/// + +## Додавання додаткових метаданих + +Ви можете додати більше інформації про параметр. + +Ця інформація буде включена у згенерований OpenAPI та використана в інтерфейсах документації та зовнішніх інструментах. + +/// note | Технічні деталі + +Майте на увазі, що різні інструменти можуть мати різний рівень підтримки OpenAPI. + +Деякі з них можуть ще не відображати всю додаткову інформацію, хоча в більшості випадків ця функція вже запланована для розробки. + +/// + +Ви можете додати `title` : + +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} + +А також `description`: + +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} + +## Аліаси параметрів + +Уявіть, що Ви хочете, щоб параметр називався `item-query`. + +Наприклад: + +``` +http://127.0.0.1:8000/items/?item-query=foobaritems +``` + +Але `item-query` — це некоректна назва змінної в Python. + +Найближчий допустимий варіант — `item_query`. + +Проте Вам потрібно, щоб параметр залишався саме `item-query`... + +У такому випадку можна оголосити `alias`, і саме він буде використовуватися для отримання значення параметра: + +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} + +## Виведення параметрів як застарілих + +Припустимо, що Ви більше не хочете використовувати цей параметр. + +Вам потрібно залишити його на деякий час, оскільки ним користуються клієнти, але Ви хочете, щоб документація чітко показувала, що він є застарілим. + +Тоді Ви можете передати параметр `deprecated=True` до `Query`: + +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} + +Документація буде показувати це таким чином: + + + +## Виняток параметрів з OpenAPI + +Щоб виключити параметр запиту зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`: + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## Кастомна валідація + +Можуть бути випадки, коли Вам потрібно провести **кастомну валідацію**, яку не можна реалізувати за допомогою параметрів, показаних вище. + +У таких випадках ви можете використати **кастомну функцію валідації**, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`). + +Це можна досягти за допомогою Pydantic's `AfterValidator` в середині `Annotated`. + +/// tip | Підказка + +Pydantic також має `BeforeValidator` та інші. 🤓 + +/// + +Наприклад, цей кастомний валідатор перевіряє, чи починається ID елемента з `isbn-` для номера книги ISBN або з `imdb-` для ID URL фільму на IMDB: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | Інформація + +Це доступно з версії Pydantic 2 або вище. 😎 + +/// + +/// tip | Підказка + +Якщо Вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким **зовнішнім компонентом**, таким як база даних чи інший API, ви повинні замість цього використовувати **FastAPI Dependencies**. Ви дізнаєтесь про них пізніше. + +Ці кастомні валідатори використовуються для речей, які можна перевірити лише з **тими даними**, що надані в запиті. + +/// + +### Зрозумійте цей код + +Головний момент – це використання **`AfterValidator` з функцією всередині `Annotated`**. Можете пропустити цю частину, якщо хочете. 🤸 + +--- + +Але якщо Вам цікаво розібратися в цьому конкретному прикладі коду і Вам ще не набридло, ось кілька додаткових деталей. + +#### Рядок із `value.startswith()` + +Звернули увагу? Рядок із `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### Випадковий елемент + +За допомогою `data.items()` ми отримуємо ітерабельний об'єкт із кортежами, що містять ключ і значення для кожного елемента словника. + +Ми перетворюємо цей ітерабельний об'єкт у звичайний `list` за допомогою `list(data.items())`. + +Потім, використовуючи `random.choice()`, ми можемо отримати випадкове значення зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. + +Далі ми **присвоюємо ці два значення** кортежу змінним `id` і `name`. + +Тож, якщо користувач не вказав ID елемента, він все одно отримає випадкову рекомендацію. + +...і все це реалізовано в **одному рядку коду**. 🤯 Хіба не прекрасний Python? 🐍 + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## Підсумок + +Ви можете оголошувати додаткові валідації та метаінформацію для своїх параметрів. + +Загальні валідації та метаінформація: + +* `alias` +* `title` +* `description` +* `deprecated` + +Валідації, специфічні для рядків: + +* `min_length` +* `max_length` +* `pattern` + +Кастомні валідації за допомогою `AfterValidator`. + +У цих прикладах Ви побачили, як оголошувати валідації для значень `str`. + +Дивіться наступні розділи, щоб дізнатися, як оголошувати валідації для інших типів, наприклад чисел. From b2d742074c41b4435775e0b24500eb0fe0cb2ed3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 30 May 2025 14:17:45 +0000 Subject: [PATCH 143/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0d2601530..fa2ba1601 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params-str-validations.md` page. PR [#13546](https://github.com/fastapi/fastapi/pull/13546) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-param-models.md`. PR [#13616](https://github.com/fastapi/fastapi/pull/13616) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). * 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-models.md`. PR [#13063](https://github.com/fastapi/fastapi/pull/13063) by [@timothy-jeong](https://github.com/timothy-jeong). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params-numeric-validations.md` page. PR [#13548](https://github.com/fastapi/fastapi/pull/13548) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 751c7dc1799ec4a3979668b0d1899f080ca916f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Jun 2025 08:48:55 +0200 Subject: [PATCH 144/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#13749)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/contributors.yml | 6 ++-- docs/en/data/translation_reviewers.yml | 44 ++++++++++++++++---------- docs/en/data/translators.yml | 30 ++++++++++++------ 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index 7da07d8a1..f3f7c9133 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,11 +1,11 @@ tiangolo: login: tiangolo - count: 734 + count: 747 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 100 + count: 102 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: @@ -15,7 +15,7 @@ alejsdev: url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci - count: 27 + count: 30 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci github-actions: diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index b544633fd..aad3e4fac 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -10,7 +10,7 @@ Xewus: url: https://github.com/Xewus sodaMelon: login: sodaMelon - count: 124 + count: 125 avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 url: https://github.com/sodaMelon ceb10n: @@ -646,7 +646,7 @@ riroan: MinLee0210: login: MinLee0210 count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=175010b24bc3a15a5705424badf9b18823bfd67d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=3c4b6e9d69bff148d09fe022ddf867e564acaa44&v=4 url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai @@ -723,6 +723,11 @@ minaton-ru: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/53541518?u=67336ca11a85493f75031508aade588dad3b9910&v=4 url: https://github.com/minaton-ru +sungchan1: + login: sungchan1 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4 + url: https://github.com/sungchan1 Serrones: login: Serrones count: 7 @@ -768,11 +773,11 @@ d2a-raudenaerde: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 url: https://github.com/d2a-raudenaerde -sungchan1: - login: sungchan1 +Zerohertz: + login: Zerohertz count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4 - url: https://github.com/sungchan1 + avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=5ebf4d33e73b1ad373154f6cdee44f7cab4d05ba&v=4 + url: https://github.com/Zerohertz deniscapeto: login: deniscapeto count: 6 @@ -921,7 +926,7 @@ Wuerike: jvmazagao: login: jvmazagao count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/22477816?u=f3b2d503b53e6ec8c808f0601b756a063a07f06e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/22477816?u=2b57addf5830906bf6ae5f25cd4c8c2fa5c2d68e&v=4 url: https://github.com/jvmazagao cun3yt: login: cun3yt @@ -1003,11 +1008,6 @@ devluisrodrigues: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/103431660?u=d9674a3249edc4601d2c712cdebf899918503c3a&v=4 url: https://github.com/devluisrodrigues -Zerohertz: - login: Zerohertz - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=c6acda352c866b1747921e0ff8782b58571d849e&v=4 - url: https://github.com/Zerohertz 11kkw: login: 11kkw count: 5 @@ -1386,7 +1386,7 @@ tienduong-21: soroushgh1: login: soroushgh1 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=e4d791c982cf7899c69f6baeebc4d7bbe86635d1&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=5e26f6a5f66cdb32d7b56e6ab362bf18ba7858b9&v=4 url: https://github.com/soroushgh1 zbellos: login: zbellos @@ -1508,11 +1508,11 @@ tyzh-dev: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51972581?u=ba3882da7c009918a8e2d6b9ead31c89f09c922d&v=4 url: https://github.com/tyzh-dev -WaFeeAL: - login: WaFeeAL +yurkevich-dev: + login: yurkevich-dev count: 2 avatarUrl: https://avatars.githubusercontent.com/u/45145188?u=db2de8c186073d95693279dcf085fcebffab57d0&v=4 - url: https://github.com/WaFeeAL + url: https://github.com/yurkevich-dev emp7yhead: login: emp7yhead count: 2 @@ -1566,7 +1566,7 @@ raphaelauv: Fahad-Md-Kamal: login: Fahad-Md-Kamal count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=84abea85e59c30b2e3bc700ae42424f3fe704332&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=f96c6cbd25b06274e3ff96bc961ca91b3f876481&v=4 url: https://github.com/Fahad-Md-Kamal zxcq544: login: zxcq544 @@ -1733,6 +1733,11 @@ Heumhub: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/173761521?v=4 url: https://github.com/Heumhub +manumolina: + login: manumolina + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2404208?u=fdc5502910f8dec814b2477f89587b9e45fac846&v=4 + url: https://github.com/manumolina logan2d5: login: logan2d5 count: 2 @@ -1768,6 +1773,11 @@ EgorOnishchuk: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 url: https://github.com/EgorOnishchuk +iamantonreznik: + login: iamantonreznik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=bf6de9a1ab17326fe14de0709719fff3826526d0&v=4 + url: https://github.com/iamantonreznik Azazul123: login: Azazul123 count: 2 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index d8593f53f..51d05003b 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -13,6 +13,11 @@ ceb10n: count: 27 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n +valentinDruzhinin: + login: valentinDruzhinin + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin tokusumi: login: tokusumi count: 23 @@ -33,11 +38,6 @@ waynerv: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv -valentinDruzhinin: - login: valentinDruzhinin - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin AlertRED: login: AlertRED count: 16 @@ -328,6 +328,11 @@ nahyunkeem: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/174440096?u=e12401d492eee58570f8914d0872b52e421a776e&v=4 url: https://github.com/nahyunkeem +timothy-jeong: + login: timothy-jeong + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 + url: https://github.com/timothy-jeong gerry-sabar: login: gerry-sabar count: 3 @@ -468,6 +473,11 @@ imtiaz101325: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/54007087?u=194d972b501b9ea9d2ddeaed757c492936e0121a&v=4 url: https://github.com/imtiaz101325 +fabianfalon: + login: fabianfalon + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/3700760?u=95f69e31280b17ac22299cdcd345323b142fe0af&v=4 + url: https://github.com/fabianfalon waketzheng: login: waketzheng count: 2 @@ -498,11 +508,6 @@ saeye: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 url: https://github.com/saeye -timothy-jeong: - login: timothy-jeong - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 - url: https://github.com/timothy-jeong 11kkw: login: 11kkw count: 2 @@ -513,3 +518,8 @@ yes0ng: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/25501794?u=3aed18b0d491e0220a167a1e9e58bea3638c6707&v=4 url: https://github.com/yes0ng +EgorOnishchuk: + login: EgorOnishchuk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 + url: https://github.com/EgorOnishchuk From 54f255ecc8d199d53e58c6f01237511754352608 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 5 Jun 2025 06:49:21 +0000 Subject: [PATCH 145/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fa2ba1601..53271fe1c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -44,6 +44,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#13749](https://github.com/fastapi/fastapi/pull/13749) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13736](https://github.com/fastapi/fastapi/pull/13736) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🔧 Update sponsors: Add InterviewPal. PR [#13728](https://github.com/fastapi/fastapi/pull/13728) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Google Analytics. PR [#13727](https://github.com/fastapi/fastapi/pull/13727) by [@tiangolo](https://github.com/tiangolo). From c430ef1ac13f190a0d7669e394366ddd5eb75a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Jun 2025 08:58:14 +0200 Subject: [PATCH 146/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Sponsors=20(#13750)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 106 ++++++++++++++----------------- 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index e24f64edc..efc5cbfcc 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -2,6 +2,9 @@ sponsors: - - login: renderinc avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 url: https://github.com/renderinc + - login: Nixtla + avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 + url: https://github.com/Nixtla - login: andrew-propelauth avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4 url: https://github.com/andrew-propelauth @@ -14,19 +17,22 @@ sponsors: - login: coderabbitai avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 url: https://github.com/coderabbitai + - login: subtotal + avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 + url: https://github.com/subtotal - login: porter-dev avatarUrl: https://avatars.githubusercontent.com/u/62078005?v=4 url: https://github.com/porter-dev - - login: Nixtla - avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 - url: https://github.com/Nixtla - login: scalar avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 url: https://github.com/scalar - - login: ObliviousAI avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 url: https://github.com/ObliviousAI -- - login: svix +- - login: dribia + avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4 + url: https://github.com/dribia + - login: svix avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4 url: https://github.com/svix - login: stainless-api @@ -35,6 +41,9 @@ sponsors: - login: speakeasy-api avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4 url: https://github.com/speakeasy-api + - login: snapit-cypher + avatarUrl: https://avatars.githubusercontent.com/u/115662654?v=4 + url: https://github.com/snapit-cypher - login: databento avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4 url: https://github.com/databento @@ -68,6 +77,9 @@ sponsors: - - login: takashi-yoneya avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 url: https://github.com/takashi-yoneya + - login: Doist + avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4 + url: https://github.com/Doist - - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries @@ -83,18 +95,9 @@ sponsors: - - login: upciti avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 url: https://github.com/upciti - - login: f4rk4sh - avatarUrl: https://avatars.githubusercontent.com/u/90454259?v=4 - url: https://github.com/f4rk4sh - - login: freddiev4 - avatarUrl: https://avatars.githubusercontent.com/u/8339018?u=1aad5b4f5a04cb750852b843d5e1d8f4ce339c2e&v=4 - url: https://github.com/freddiev4 - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - - login: vincentkoc - avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 - url: https://github.com/vincentkoc - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky @@ -104,9 +107,6 @@ sponsors: - login: ashi-agrawal avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 url: https://github.com/ashi-agrawal - - login: sepsi77 - avatarUrl: https://avatars.githubusercontent.com/u/18682303?v=4 - url: https://github.com/sepsi77 - login: RaamEEIL avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 url: https://github.com/RaamEEIL @@ -125,9 +125,6 @@ sponsors: - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure - - login: roboflow - avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 - url: https://github.com/roboflow - login: kaoru0310 avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 url: https://github.com/kaoru0310 @@ -146,6 +143,9 @@ sponsors: - login: logic-automation avatarUrl: https://avatars.githubusercontent.com/u/144732884?v=4 url: https://github.com/logic-automation + - login: roboflow + avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 + url: https://github.com/roboflow - login: dudikbender avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 url: https://github.com/dudikbender @@ -185,15 +185,18 @@ sponsors: - login: anomaly avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 url: https://github.com/anomaly + - login: mj0331 + avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4 + url: https://github.com/mj0331 - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 url: https://github.com/gorhack - login: Ryandaydev avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 url: https://github.com/Ryandaydev - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog + - login: vincentkoc + avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 + url: https://github.com/vincentkoc - login: jstanden avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 url: https://github.com/jstanden @@ -215,9 +218,6 @@ sponsors: - login: wshayes avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes - - login: gaetanBloch - avatarUrl: https://avatars.githubusercontent.com/u/583199?u=50c49e83d6b4feb78a091901ea02ead1462f442b&v=4 - url: https://github.com/gaetanBloch - login: koxudaxi avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 url: https://github.com/koxudaxi @@ -227,9 +227,6 @@ sponsors: - login: mintuhouse avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 url: https://github.com/mintuhouse - - login: oliverxchen - avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 - url: https://github.com/oliverxchen - login: TrevorBenson avatarUrl: https://avatars.githubusercontent.com/u/9167887?u=dccbea3327a57750923333d8ebf1a0b3f1948949&v=4 url: https://github.com/TrevorBenson @@ -254,6 +251,12 @@ sponsors: - login: mjohnsey avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 url: https://github.com/mjohnsey + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog + - login: oliverxchen + avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 + url: https://github.com/oliverxchen - login: ternaus avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 url: https://github.com/ternaus @@ -263,9 +266,6 @@ sponsors: - login: FernandoCelmer avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4 url: https://github.com/FernandoCelmer - - login: simw - avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4 - url: https://github.com/simw - login: Rehket avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4 url: https://github.com/Rehket @@ -299,6 +299,9 @@ sponsors: - login: hgalytoby avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 url: https://github.com/hgalytoby + - login: browniebroke + avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 + url: https://github.com/browniebroke - login: joshuatz avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 url: https://github.com/joshuatz @@ -317,12 +320,12 @@ sponsors: - login: rlnchow avatarUrl: https://avatars.githubusercontent.com/u/28018479?u=a93ca9cf1422b9ece155784a72d5f2fdbce7adff&v=4 url: https://github.com/rlnchow - - login: dvlpjrs - avatarUrl: https://avatars.githubusercontent.com/u/32254642?u=fbd6ad0324d4f1eb6231cf775be1c7bd4404e961&v=4 - url: https://github.com/dvlpjrs - login: engineerjoe440 avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 url: https://github.com/engineerjoe440 + - login: lukzmu + avatarUrl: https://avatars.githubusercontent.com/u/175964415?u=83ea9b0b7b7b0f15bcb5747d93f303447a19a00b&v=4 + url: https://github.com/lukzmu - login: conservative-dude avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4 url: https://github.com/conservative-dude @@ -335,12 +338,6 @@ sponsors: - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ - - login: tochikuji - avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 - url: https://github.com/tochikuji - - login: browniebroke - avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 - url: https://github.com/browniebroke - login: miguelgr avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 url: https://github.com/miguelgr @@ -368,6 +365,9 @@ sponsors: - login: ceb10n avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n + - login: tochikuji + avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 + url: https://github.com/tochikuji - login: moonape1226 avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 url: https://github.com/moonape1226 @@ -428,10 +428,7 @@ sponsors: - login: hcristea avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=19092923a4ea5b338567961c8270b9206a6d81bb&v=4 url: https://github.com/hcristea -- - login: larsyngvelundin - avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 - url: https://github.com/larsyngvelundin - - login: andrecorumba +- - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba - login: rwxd @@ -446,27 +443,18 @@ sponsors: - login: Olegt0rr avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 url: https://github.com/Olegt0rr - - login: Miles-Arts - avatarUrl: https://avatars.githubusercontent.com/u/82297475?u=c41881e4b386d9dbf737218542b120336b5731a1&v=4 - url: https://github.com/Miles-Arts - - login: sandeepsalwan1 - avatarUrl: https://avatars.githubusercontent.com/u/118837112?u=fc9b0330fa4791950661b7decd9bf56f07599b43&v=4 - url: https://github.com/sandeepsalwan1 - - login: fabioantonioastore - avatarUrl: https://avatars.githubusercontent.com/u/132024075?u=b3a267f2e2c7ce2379f82163f88111bd2a2a2f1e&v=4 - url: https://github.com/fabioantonioastore - - login: zhandos256 - avatarUrl: https://avatars.githubusercontent.com/u/60260671?u=aa9ed698bc3cd06fb553d2ef91d3895bbb00cce1&v=4 - url: https://github.com/zhandos256 + - login: larsyngvelundin + avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 + url: https://github.com/larsyngvelundin - login: one-st-one avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 url: https://github.com/one-st-one + - login: federicsp + avatarUrl: https://avatars.githubusercontent.com/u/62903636?u=05004f4a2c590f1d18c200e17978bf2e17acb632&v=4 + url: https://github.com/federicsp - login: Toothwitch avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 url: https://github.com/Toothwitch - - login: ssbarnea - avatarUrl: https://avatars.githubusercontent.com/u/102495?u=c7bd9ddf127785286fc939dd18cb02db0a453bce&v=4 - url: https://github.com/ssbarnea - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi From c3de47858c5e73bf01b14a2588fd819f89ca6a51 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 5 Jun 2025 06:58:39 +0000 Subject: [PATCH 147/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 53271fe1c..ffeebcce1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -44,6 +44,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Sponsors. PR [#13750](https://github.com/fastapi/fastapi/pull/13750) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13749](https://github.com/fastapi/fastapi/pull/13749) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13736](https://github.com/fastapi/fastapi/pull/13736) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🔧 Update sponsors: Add InterviewPal. PR [#13728](https://github.com/fastapi/fastapi/pull/13728) by [@tiangolo](https://github.com/tiangolo). From e71d87d8ef00c6ff5e77366a29b10af4e59144ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Jun 2025 09:29:13 +0200 Subject: [PATCH 148/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#13754)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/topic_repos.yml | 384 +++++++++++++++++------------------ 1 file changed, 192 insertions(+), 192 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 169b62694..1f6ae55bd 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,266 +1,266 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 32337 + stars: 33079 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 29833 + stars: 30350 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21544 + stars: 21593 owner_login: jina-ai owner_html_url: https://github.com/jina-ai -- name: sqlmodel - html_url: https://github.com/fastapi/sqlmodel - stars: 15799 - owner_login: fastapi - owner_html_url: https://github.com/fastapi - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 15676 + stars: 17229 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin +- name: sqlmodel + html_url: https://github.com/fastapi/sqlmodel + stars: 16068 + 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: 12183 + stars: 12689 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 11594 + stars: 11965 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 9586 + stars: 9773 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8804 + stars: 8829 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 6688 + stars: 6779 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 6502 + stars: 6652 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: serge html_url: https://github.com/serge-chat/serge - stars: 5720 + stars: 5722 owner_login: serge-chat owner_html_url: https://github.com/serge-chat - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 5515 + stars: 5607 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: 5162 - owner_login: fastapi-users - owner_html_url: https://github.com/fastapi-users - name: polar html_url: https://github.com/polarsource/polar - stars: 5119 + stars: 5327 owner_login: polarsource owner_html_url: https://github.com/polarsource +- name: fastapi-users + html_url: https://github.com/fastapi-users/fastapi-users + stars: 5235 + owner_login: fastapi-users + owner_html_url: https://github.com/fastapi-users +- name: fastapi_mcp + html_url: https://github.com/tadata-org/fastapi_mcp + stars: 5193 + owner_login: tadata-org + owner_html_url: https://github.com/tadata-org +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 4833 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4302 + stars: 4307 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4244 + stars: 4281 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql -- name: fastapi_mcp - html_url: https://github.com/tadata-org/fastapi_mcp - stars: 4178 - owner_login: tadata-org - owner_html_url: https://github.com/tadata-org - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4112 + stars: 4110 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 3985 + stars: 4008 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: poem html_url: https://github.com/poem-web/poem - stars: 3918 + stars: 3977 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3287 + stars: 3317 owner_login: rashadphz owner_html_url: https://github.com/rashadphz - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3192 + stars: 3253 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: 3141 + stars: 3228 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: opyrator - html_url: https://github.com/ml-tooling/opyrator - stars: 3116 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3088 + stars: 3175 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3059 + stars: 3172 owner_login: pydantic owner_html_url: https://github.com/pydantic -- name: docarray - html_url: https://github.com/docarray/docarray - stars: 3052 - owner_login: docarray - owner_html_url: https://github.com/docarray +- name: opyrator + html_url: https://github.com/ml-tooling/opyrator + stars: 3122 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3025 + stars: 3110 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor +- name: docarray + html_url: https://github.com/docarray/docarray + stars: 3068 + owner_login: docarray + owner_html_url: https://github.com/docarray - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2883 + stars: 2892 owner_login: nsidnev owner_html_url: https://github.com/nsidnev +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 2883 + owner_login: remsky + owner_html_url: https://github.com/remsky - name: uvicorn-gunicorn-fastapi-docker html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker - stars: 2756 + stars: 2770 owner_login: tiangolo owner_html_url: https://github.com/tiangolo - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 2587 + stars: 2740 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2502 + stars: 2517 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 2500 - owner_login: remsky - owner_html_url: https://github.com/remsky - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2419 + stars: 2423 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2350 + stars: 2376 owner_login: Buuntu owner_html_url: https://github.com/Buuntu -- name: nextpy - html_url: https://github.com/dot-agent/nextpy - stars: 2277 - owner_login: dot-agent - owner_html_url: https://github.com/dot-agent - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2273 + stars: 2301 owner_login: s3rius owner_html_url: https://github.com/s3rius -- name: 30-Days-of-Python - html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2183 - owner_login: codingforentrepreneurs - owner_html_url: https://github.com/codingforentrepreneurs +- name: nextpy + html_url: https://github.com/dot-agent/nextpy + stars: 2289 + owner_login: dot-agent + owner_html_url: https://github.com/dot-agent - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2141 + stars: 2196 owner_login: aminalaee owner_html_url: https://github.com/aminalaee +- name: 30-Days-of-Python + html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python + stars: 2179 + owner_login: codingforentrepreneurs + owner_html_url: https://github.com/codingforentrepreneurs - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2070 + stars: 2098 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2063 + stars: 2077 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils -- name: solara - html_url: https://github.com/widgetti/solara - stars: 2028 - owner_login: widgetti - owner_html_url: https://github.com/widgetti - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 1996 + stars: 2047 owner_login: supabase owner_html_url: https://github.com/supabase +- name: solara + html_url: https://github.com/widgetti/solara + stars: 2044 + owner_login: widgetti + owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1870 + stars: 1905 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1827 + stars: 1823 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno -- name: SurfSense - html_url: https://github.com/MODSetter/SurfSense - stars: 1763 - owner_login: MODSetter - owner_html_url: https://github.com/MODSetter - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1743 + stars: 1754 owner_login: ycd owner_html_url: https://github.com/ycd - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1741 + stars: 1746 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official - name: ormar html_url: https://github.com/collerek/ormar - stars: 1730 + stars: 1742 owner_login: collerek owner_html_url: https://github.com/collerek - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1631 + stars: 1630 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: termpair html_url: https://github.com/cs01/termpair - stars: 1610 + stars: 1611 owner_login: cs01 owner_html_url: https://github.com/cs01 - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1588 + stars: 1609 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm - name: coronavirus-tracker-api @@ -270,137 +270,152 @@ owner_html_url: https://github.com/ExpDev07 - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1552 + stars: 1575 owner_login: long2ice owner_html_url: https://github.com/long2ice - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1536 + stars: 1568 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1491 + stars: 1508 owner_login: awtkns owner_html_url: https://github.com/awtkns - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1450 + stars: 1501 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1443 + stars: 1453 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1387 + stars: 1390 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx -- name: budgetml - html_url: https://github.com/ebhy/budgetml - stars: 1341 - owner_login: ebhy - owner_html_url: https://github.com/ebhy - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1331 + stars: 1353 owner_login: uriyyo owner_html_url: https://github.com/uriyyo +- name: budgetml + html_url: https://github.com/ebhy/budgetml + stars: 1342 + owner_login: ebhy + owner_html_url: https://github.com/ebhy - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1299 + stars: 1325 owner_login: teamhide owner_html_url: https://github.com/teamhide +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 1306 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1235 + stars: 1256 owner_login: amisadmin owner_html_url: https://github.com/amisadmin - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1222 + stars: 1245 owner_login: liaogx owner_html_url: https://github.com/liaogx -- name: vue-fastapi-admin - html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1190 - owner_login: mizhexiaoxiao - owner_html_url: https://github.com/mizhexiaoxiao - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1180 + stars: 1201 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi +- name: bracket + html_url: https://github.com/evroon/bracket + stars: 1201 + owner_login: evroon + owner_html_url: https://github.com/evroon - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1166 + stars: 1179 owner_login: slackapi owner_html_url: https://github.com/slackapi - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1134 + stars: 1147 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1127 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai -- name: odmantic - html_url: https://github.com/art049/odmantic - stars: 1115 - owner_login: art049 - owner_html_url: https://github.com/art049 - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1112 + stars: 1145 owner_login: trallnag owner_html_url: https://github.com/trallnag - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1107 + stars: 1143 owner_login: aws-samples owner_html_url: https://github.com/aws-samples +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1134 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai +- name: odmantic + html_url: https://github.com/art049/odmantic + stars: 1118 + owner_login: art049 + owner_html_url: https://github.com/art049 - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1094 + stars: 1110 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 +- name: fastcrud + html_url: https://github.com/benavlabs/fastcrud + stars: 1080 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: restish html_url: https://github.com/rest-sh/restish - stars: 1041 + stars: 1056 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: fastcrud - html_url: https://github.com/igorbenav/fastcrud - stars: 1036 - owner_login: igorbenav - owner_html_url: https://github.com/igorbenav -- name: runhouse - html_url: https://github.com/run-house/runhouse - stars: 1022 - owner_login: run-house - owner_html_url: https://github.com/run-house - name: fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 997 + stars: 1050 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices +- name: runhouse + html_url: https://github.com/run-house/runhouse + stars: 1034 + owner_login: run-house + owner_html_url: https://github.com/run-house +- name: autollm + html_url: https://github.com/viddexa/autollm + stars: 992 + owner_login: viddexa + owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky stars: 990 owner_login: ajndkr owner_html_url: https://github.com/ajndkr -- name: autollm - html_url: https://github.com/viddexa/autollm - stars: 990 - owner_login: viddexa - owner_html_url: https://github.com/viddexa +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 985 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs +- name: authx + html_url: https://github.com/yezz123/authx + stars: 938 + owner_login: yezz123 + owner_html_url: https://github.com/yezz123 - name: secure html_url: https://github.com/TypeError/secure - stars: 932 + stars: 935 owner_login: TypeError owner_html_url: https://github.com/TypeError - name: langcorn @@ -408,88 +423,73 @@ stars: 925 owner_login: msoedov owner_html_url: https://github.com/msoedov -- name: FastAPI-boilerplate - html_url: https://github.com/igorbenav/FastAPI-boilerplate - stars: 925 - owner_login: igorbenav - owner_html_url: https://github.com/igorbenav -- name: authx - html_url: https://github.com/yezz123/authx - stars: 913 - owner_login: yezz123 - owner_html_url: https://github.com/yezz123 - name: energy-forecasting html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 907 + stars: 913 owner_login: iusztinpaul owner_html_url: https://github.com/iusztinpaul - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 873 + stars: 886 owner_login: developmentseed owner_html_url: https://github.com/developmentseed +- name: flock + html_url: https://github.com/Onelevenvy/flock + stars: 866 + owner_login: Onelevenvy + owner_html_url: https://github.com/Onelevenvy - name: httpdbg html_url: https://github.com/cle-b/httpdbg - stars: 850 + stars: 863 owner_login: cle-b owner_html_url: https://github.com/cle-b - name: marker-api html_url: https://github.com/adithya-s-k/marker-api - stars: 844 + stars: 859 owner_login: adithya-s-k owner_html_url: https://github.com/adithya-s-k - name: ludic html_url: https://github.com/getludic/ludic - stars: 842 + stars: 845 owner_login: getludic owner_html_url: https://github.com/getludic -- name: flock - html_url: https://github.com/Onelevenvy/flock - stars: 805 - owner_login: Onelevenvy - owner_html_url: https://github.com/Onelevenvy -- name: fastapi-observability - html_url: https://github.com/blueswen/fastapi-observability - stars: 797 - owner_login: blueswen - owner_html_url: https://github.com/blueswen - name: fastapi-do-zero html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 786 + stars: 827 owner_login: dunossauro owner_html_url: https://github.com/dunossauro +- name: fastapi-observability + html_url: https://github.com/blueswen/fastapi-observability + stars: 823 + owner_login: blueswen + owner_html_url: https://github.com/blueswen +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 803 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: fastapi-mail html_url: https://github.com/sabuhish/fastapi-mail - stars: 781 + stars: 798 owner_login: sabuhish owner_html_url: https://github.com/sabuhish - name: starlette-admin html_url: https://github.com/jowilf/starlette-admin - stars: 764 + stars: 785 owner_login: jowilf owner_html_url: https://github.com/jowilf - name: lccn_predictor html_url: https://github.com/baoliay2008/lccn_predictor - stars: 759 + stars: 767 owner_login: baoliay2008 owner_html_url: https://github.com/baoliay2008 +- name: aktools + html_url: https://github.com/akfamily/aktools + stars: 759 + owner_login: akfamily + owner_html_url: https://github.com/akfamily - name: KonomiTV html_url: https://github.com/tsukumijima/KonomiTV - stars: 741 + stars: 748 owner_login: tsukumijima owner_html_url: https://github.com/tsukumijima -- name: FastAPI-Backend-Template - html_url: https://github.com/Aeternalis-Ingenium/FastAPI-Backend-Template - stars: 734 - owner_login: Aeternalis-Ingenium - owner_html_url: https://github.com/Aeternalis-Ingenium -- name: learn-generative-ai - html_url: https://github.com/panaverse/learn-generative-ai - stars: 731 - owner_login: panaverse - owner_html_url: https://github.com/panaverse -- name: annotated-py-projects - html_url: https://github.com/hhstore/annotated-py-projects - stars: 730 - owner_login: hhstore - owner_html_url: https://github.com/hhstore From 7421a19b7f7039ebff2f7a04f7f23eabcd2390f2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 5 Jun 2025 07:29:36 +0000 Subject: [PATCH 149/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ffeebcce1..a795f245c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -44,6 +44,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#13754](https://github.com/fastapi/fastapi/pull/13754) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13750](https://github.com/fastapi/fastapi/pull/13750) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13749](https://github.com/fastapi/fastapi/pull/13749) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13736](https://github.com/fastapi/fastapi/pull/13736) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 37c6913ce566706b4d5e1cbe10e6401fec4c5e3f Mon Sep 17 00:00:00 2001 From: Nazmus Sakib Sibly <101848801+SakibSibly@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:15:56 +0600 Subject: [PATCH 150/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Bengali=20translat?= =?UTF-8?q?ion=20for=20`docs/bn/docs/environment-variables.md`=20(#13629)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Bengali translation for docs/bn/docs/environment-variables.md Co-authored-by: Sofie Van Landeghem --- docs/bn/docs/environment-variables.md | 298 ++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 docs/bn/docs/environment-variables.md diff --git a/docs/bn/docs/environment-variables.md b/docs/bn/docs/environment-variables.md new file mode 100644 index 000000000..9122ca5bf --- /dev/null +++ b/docs/bn/docs/environment-variables.md @@ -0,0 +1,298 @@ +# এনভায়রনমেন্ট ভেরিয়েবলস + +/// tip + +আপনি যদি "এনভায়রনমেন্ট ভেরিয়েবলস" কী এবং সেগুলো কীভাবে ব্যবহার করতে হয় সেটা জানেন, তাহলে এই অংশটি স্কিপ করে যেতে পারেন। + +/// + +এনভায়রনমেন্ট ভেরিয়েবল (সংক্ষেপে "**env var**" নামেও পরিচিত) হলো এমন একটি ভেরিয়েবল যা পাইথন কোডের **বাইরে**, **অপারেটিং সিস্টেমে** থাকে এবং আপনার পাইথন কোড (বা অন্যান্য প্রোগ্রাম) দ্বারা যাকে রিড করা যায়। + +এনভায়রনমেন্ট ভেরিয়েবলস অ্যাপ্লিকেশনের **সেটিংস** পরিচালনা করতে, পাইথনের **ইনস্টলেশন** প্রক্রিয়ার অংশ হিসেবে, ইত্যাদি কাজে উপযোগী হতে পারে। + +## Env Vars তৈরী এবং ব্যবহার + +আপনি **শেল (টার্মিনাল)**-এ, পাইথনের প্রয়োজন ছাড়াই, এনভায়রনমেন্ট ভেরিয়েবলস **তৈরি** এবং ব্যবহার করতে পারবেনঃ + +//// tab | লিনাক্স, ম্যাকওএস, উইন্ডোজ Bash + +
+ +```console +// আপনি চাইলে MY_NAME নামে একটি env var তৈরি করতে পারেন +$ export MY_NAME="Wade Wilson" + +// তারপরে এটিকে চাইলে অন্যান্য প্রোগ্রামে ব্যবহার করতে পারেন +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | উইন্ডোজ পাওয়ারশেল + +
+ +```console +// MY_NAME নামে env var তৈরি +$ $Env:MY_NAME = "Wade Wilson" + +// অন্যান্য প্রোগ্রামে এটিকে ব্যবহার +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## পাইথনে env vars রিড করা + +আপনি চাইলে পাইথনের **বাইরে**, টার্মিনালে (বা অন্য কোনো উপায়ে) এনভায়রনমেন্ট ভেরিয়েবলস তৈরি করতে পারেন, এবং পরে সেগুলো **পাইথনে রিড** (অ্যাক্সেস করতে) পারেন। + +উদাহরণস্বরূপ, আপনার `main.py` নামে একটি ফাইল থাকতে পারেঃ + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +`os.getenv()` এর দ্বিতীয় আর্গুমেন্টটি হলো এর ডিফল্ট ভ্যালু যা রিটার্ন করা হবে। + +যদি এটি দেওয়া না হয়, ডিফল্টভাবে `None` ব্যবহৃত হবে, এখানে আমরা ডিফল্ট ভ্যালু হিসেবে `"World"` ব্যবহার করেছি। + +/// + +তারপরে পাইথন প্রোগ্রামটিকে নিম্নোক্তভাবে কল করা যাবেঃ + +//// tab | লিনাক্স, ম্যাকওএস, উইন্ডোজ Bash + +
+ +```console +// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি +$ python main.py + +// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি + +Hello World from Python + +// কিন্তু আমরা প্রথমে যদি একটা এনভায়রনমেন্ট ভারিয়েবল তৈরি করে নেই +$ export MY_NAME="Wade Wilson" + +// এবং তারপর আবার প্রোগ্রাটিকে কল করি +$ python main.py + +// এখন এটি এনভায়রনমেন্ট ভেরিয়েবল রিড করতে পারবে + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | উইন্ডোজ পাওয়ারশেল + +
+ +```console +// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি +$ python main.py + +// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি + +Hello World from Python + +// কিন্তু আমরা প্রথমে যদি একটা এনভায়রনমেন্ট ভারিয়েবল তৈরি করে নেই +$ $Env:MY_NAME = "Wade Wilson" + +// এবং তারপর আবার প্রোগ্রাটিকে কল করি +$ python main.py + +// এখন এটি এনভায়রনমেন্ট ভেরিয়েবল রিড করতে পারবে + +Hello Wade Wilson from Python +``` + +
+ +//// + +যেহেতু এনভায়রনমেন্ট ভেরিয়েবলস কোডের বাইরে সেট করা যায়, কিন্তু পরবর্তীতে কোড দ্বারা রিড করা যায়, এবং বাকি ফাইলগুলোর সাথে রাখতে (`git` এ কমিট) হয় না, তাই কনফিগারেশনস বা **সেটিংস** এর জন্য এগুলো সাধারণত ব্যবহৃত হয়ে থাকে। + +আপনি একটি এনভায়রনমেন্ট ভেরিয়েবল শুধুমাত্র একটি **নির্দিষ্ট প্রোগ্রাম ইনভোকেশনের** জন্যও তৈরি করতে পারেন, যা শুধুমাত্র সেই প্রোগ্রামের জন্যই এভেইলেবল থাকবে এবং শুধুমাত্র তার চলাকালীন সময় পর্যন্তই সক্রিয় থাকবে। + +এটি করতে, প্রোগ্রামটি রান করার ঠিক আগেই, একই লাইনে এনভায়রনমেন্ট ভেরিয়েবল তৈরি করুন: + +
+ +```console +// প্রোগ্রামটি কল করার সময় একই লাইনে MY_NAME এনভায়রনমেন্ট ভেরিয়েবল তৈরি করুন +$ MY_NAME="Wade Wilson" python main.py + +// এখন এটি এনভায়রনমেন্ট ভ্যরিয়েবলটিকে রিড করতে পারবে + +Hello Wade Wilson from Python + +// পরবর্তীতে এনভায়রনমেন্ট ভেরিয়েবলটিকে আর ব্যবহার করা যাচ্ছে না +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +এটি নিয়ে আরো বিস্তারিত পড়তে পারেন এখানে The Twelve-Factor App: Config। + +/// + +## টাইপস এবং ভ্যালিডেশন + +এই এনভায়রনমেন্ট ভেরিয়েবলগুলো শুধুমাত্র **টেক্সট স্ট্রিংস** হ্যান্ডেল করতে পারে, যেহেতু এগুলো পাইথনের বাইরে অবস্থিত এবং অন্যান্য প্রোগ্রাম এবং সিস্টেমের বাকি অংশের (এমনকি বিভিন্ন অপারেটিং সিস্টেম যেমন লিনাক্স, উইন্ডোজ, ম্যাকওএস) সাথে সামঞ্জস্যপূর্ণ হতে হয়। + +এর অর্থ হচ্ছে পাইথনে এনভায়রনমেন্ট ভেরিয়েবল থেকে রিড করা **যেকোনো ভ্যালু** একটি `str` হবে, এবং অন্য কোনো টাইপে কনভার্সন বা যেকোনো ভেলিডেশন কোডে আলাদাভাবে করতে হবে। + +এনভায়রনমেন্ট ভেরিয়েবল ব্যবহার করে **এপ্লিকেশন সেটিংস** হ্যান্ডেল করা নিয়ে আরো বিস্তারিত জানা যাবে [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank}. + +## `PATH` এনভায়রনমেন্ট ভেরিয়েবল + +**`PATH`** নামে একটি **বিশেষ** এনভায়রনমেন্ট ভেরিয়েবল রয়েছে, যেটি প্রোগ্রাম রান করার জন্য অপারেটিং সিস্টেমস (লিনাক্স, ম্যাকওএস, উইন্ডোজ) দ্বারা ব্যবহৃত হয়। + +`PATH` ভেরিয়েবল এর ভ্যালু হচ্ছে একটি বিশাল স্ট্রিং যা ডিরেক্টরিকে কোলন `:` দিয়ে আলাদা করার মাধ্যমে লিনাক্সে ও ম্যাকওএস এ, এবং সেমিকোলন `;` এর মাধ্যমে উইন্ডোজ এ তৈরি করা থাকে। + +উদাহরণস্বরূপ, `PATH` ভেরিয়েবল নিচের মতো দেখতে হতে পারেঃ + +//// tab | লিনাক্স, ম্যাকওএস + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +তারমানে হলো সিস্টেম প্রোগ্রামগুলোকে নিচের ডিরেক্টরিগুলোতে খুঁজবেঃ + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | উইন্ডোজ + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +তারমানে হলো সিস্টেম প্রোগ্রামগুলোকে নিচের ডিরেক্টরিগুলোতে খুঁজবেঃ + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +যখন আপনি টার্মিনালে কোনো **কমান্ড** লিখবেন, অপারেটিং সিস্টেম **প্রত্যেকটি ডিরেক্টরিতে** প্রোগ্রামটি **খুঁজবে** যেগুলো `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ লিস্ট করা আছে। + +উদাহরণস্বরূপ, যখন আপনি টার্মিনালে `python` টাইপ করবেন, অপারেটিং সিস্টেম এই লিস্ট এর **প্রথম ডিরেক্টরিতে** `python` নামের একটি প্রোগ্রাম খুঁজবে। + +যদি এটি খুঁজে পায়, তাহলে এটি প্রোগ্রামটিকে ব্যবহার করবে। অন্যথায় এটি **অন্যান্য ডিরেক্টরিগুলোতে** এটিকে খুঁজতে থাকবে। + +### পাইথন ইনস্টল এবং `PATH` আপডেট + +যখন আপনি পাইথন ইনস্টল করেন, আপনি `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান কিনা সেটা জিজ্ঞেস করা হতে পারে। + +//// tab | লিনাক্স, ম্যাকওএস + +ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `/opt/custompython/bin` ডিরেক্টরিতে ইনস্টল হচ্ছে। + +যদি আপনি "Yes" সিলেক্ট করে `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান, তাহলে ইনস্টলার `/opt/custompython/bin` কে `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ এড করে দিবে। + +এটা দেখতে এমনটা হতে পারেঃ + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +এইভাবে, আপনি যখন টার্মিনালে `python` টাইপ করেন, সিস্টেম পাইথন প্রোগ্রামটিকে `/opt/custompython/bin` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে। + +//// + +//// tab | উইন্ডোজ + +ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `C:\opt\custompython\bin` ডিরেক্টরিতে ইনস্টল হচ্ছে। + +যদি আপনি "Yes" সিলেক্ট করে `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান, তাহলে ইনস্টলার `C:\opt\custompython\bin` কে `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ এড করে দিবে। + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +এইভাবে, আপনি যখন টার্মিনালে `python` টাইপ করেন, সিস্টেম পাইথন প্রোগ্রামটিকে `C:\opt\custompython\bin` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে। + +//// + +তাই, আপনি যদি টাইপ করেনঃ + +
+ +```console +$ python +``` + +
+ +//// tab | লিনাক্স, ম্যাকওএস + +সিস্টেম `python` প্রোগ্রামকে `/opt/custompython/bin` এ **খুঁজে পাবে** এবং এটাকে রান করবে। + +এটা মোটামুটিভাবে নিচের মতো করে লেখার সমান হবেঃ + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | উইন্ডোজ + +সিস্টেম `python` প্রোগ্রামকে `C:\opt\custompython\bin\python` এ **খুঁজে পাবে** এবং এটাকে রান করবে। + +এটা মোটামুটিভাবে নিচের মতো করে লেখার সমান হবেঃ + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +এই তথ্যগুলো [ভার্চুয়াল এনভায়রনমেন্টস](virtual-environments.md){.internal-link target=_blank} শেখার ক্ষেত্রে সহায়ক হবে। + +## উপসংহার + +এর মাধ্যমে আপনি **এনভায়রনমেন্ট ভেরিয়েবলস** কি এবং এটিকে পাইথনে কিভাবে ব্যবহার করতে হয় তার সম্পর্কে বেসিক ধারনা পেলেন। + +চাইলে এই সম্পর্কে আরো বিস্তারিত পড়তে পারেন Wikipedia for Environment Variable এ। + +অনেক ক্ষেত্রে, দেখা মাত্রই এনভায়রনমেন্ট ভেরিয়েবল কীভাবে প্রয়োজন হবে তা স্পষ্ট হয় না। কিন্তু ডেভেলপমেন্টের সময় আপনি নানা রকম পরিস্থিতিতে এগুলোর সম্মুখীন হবেন, তাই এগুলো সম্পর্কে জেনে রাখা ভালো। + +উদাহরণস্বরূপ, আপনার এই ইনফরমেশনটি পরবর্তী, [ভার্চুয়াল এনভায়রনমেন্টস](virtual-environments.md) অংশে দরকার হবে। From 37e596599e6dcfb05b4a0180079c98eb991d5597 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 5 Jun 2025 08:16:18 +0000 Subject: [PATCH 151/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a795f245c..377698649 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params-str-validations.md` page. PR [#13546](https://github.com/fastapi/fastapi/pull/13546) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-param-models.md`. PR [#13616](https://github.com/fastapi/fastapi/pull/13616) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). * 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-models.md`. PR [#13063](https://github.com/fastapi/fastapi/pull/13063) by [@timothy-jeong](https://github.com/timothy-jeong). From eae3025ed21d1e913986e5d752bc60dfff76a85b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Jun 2025 12:00:47 +0200 Subject: [PATCH 152/455] =?UTF-8?q?=E2=AC=86=20Bump=20typer=20from=200.15.?= =?UTF-8?q?3=20to=200.16.0=20(#13752)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [typer](https://github.com/fastapi/typer) from 0.15.3 to 0.16.0. - [Release notes](https://github.com/fastapi/typer/releases) - [Changelog](https://github.com/fastapi/typer/blob/master/docs/release-notes.md) - [Commits](https://github.com/fastapi/typer/compare/0.15.3...0.16.0) --- updated-dependencies: - dependency-name: typer dependency-version: 0.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index bd0082304..9de608eb2 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -3,7 +3,7 @@ mkdocs-material==9.6.1 mdx-include >=1.4.1,<2.0.0 mkdocs-redirects>=1.2.1,<1.3.0 -typer == 0.15.3 +typer == 0.16.0 pyyaml >=5.3.1,<7.0.0 # For Material for MkDocs, Chinese search jieba==0.42.1 From b7a885066033d6e6dc86f93eded8fb1d22a6bbba Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 5 Jun 2025 10:01:12 +0000 Subject: [PATCH 153/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 377698649..1810527f7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -45,6 +45,7 @@ hide: ### Internal +* ⬆ Bump typer from 0.15.3 to 0.16.0. PR [#13752](https://github.com/fastapi/fastapi/pull/13752) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13754](https://github.com/fastapi/fastapi/pull/13754) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13750](https://github.com/fastapi/fastapi/pull/13750) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13749](https://github.com/fastapi/fastapi/pull/13749) by [@tiangolo](https://github.com/tiangolo). From 38c282039a1c7fe39a41bc41400ff4c3bac9a148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Jun 2025 13:51:48 +0200 Subject: [PATCH 154/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20add?= =?UTF-8?q?=20Dribia=20(#13771)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/en/data/sponsors.yml | 3 +++ docs/en/data/sponsors_badge.yml | 1 + docs/en/docs/img/sponsors/dribia.png | Bin 0 -> 14770 bytes 4 files changed, 5 insertions(+) create mode 100644 docs/en/docs/img/sponsors/dribia.png diff --git a/README.md b/README.md index 78ae6b10e..da9446e2b 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 14a1f3cf3..897ca7b8d 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -48,6 +48,9 @@ silver: - url: https://www.interviewpal.com/?utm_source=fastapi&utm_medium=open-source&utm_campaign=dev-hiring title: InterviewPal - AI Interview Coach for Engineers and Devs img: https://fastapi.tiangolo.com/img/sponsors/interviewpal.png + - url: https://dribia.com/en/ + title: Dribia - Data Science within your reach + img: https://fastapi.tiangolo.com/img/sponsors/dribia.png bronze: - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source title: Biosecurity risk assessments made easy. diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index fd34019b3..d145e7372 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -42,3 +42,4 @@ logins: - coderabbitai - permitio - LambdaTest-Inc + - dribia diff --git a/docs/en/docs/img/sponsors/dribia.png b/docs/en/docs/img/sponsors/dribia.png new file mode 100644 index 0000000000000000000000000000000000000000..a6760a47b8acba1ac4ba5f13fa479f6daf1b9b02 GIT binary patch literal 14770 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 Date: Thu, 5 Jun 2025 11:52:34 +0000 Subject: [PATCH 155/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1810527f7..b2f083e1c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -45,6 +45,7 @@ hide: ### Internal +* 🔧 Update sponsors: add Dribia. PR [#13771](https://github.com/fastapi/fastapi/pull/13771) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump typer from 0.15.3 to 0.16.0. PR [#13752](https://github.com/fastapi/fastapi/pull/13752) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13754](https://github.com/fastapi/fastapi/pull/13754) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Sponsors. PR [#13750](https://github.com/fastapi/fastapi/pull/13750) by [@tiangolo](https://github.com/tiangolo). From 736cce8329e79f7df2c0634762516c8f86bf0ad0 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Thu, 5 Jun 2025 15:12:04 +0300 Subject: [PATCH 156/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/query-param-models.md`=20(?= =?UTF-8?q?#13748)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Ukrainian translation for docs/uk/docs/tutorial/query-param-models.md page * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks * Update docs/uk/docs/tutorial/query-param-models.md Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --------- Co-authored-by: Valentyn Druzhynin Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/uk/docs/tutorial/query-param-models.md | 68 +++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 docs/uk/docs/tutorial/query-param-models.md diff --git a/docs/uk/docs/tutorial/query-param-models.md b/docs/uk/docs/tutorial/query-param-models.md new file mode 100644 index 000000000..97eb82fa1 --- /dev/null +++ b/docs/uk/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# Моделі Query параметрів + +Якщо у Вас є група **query параметрів**, які пов’язані між собою, Ви можете створити **Pydantic-модель** для їх оголошення. + +Це дозволить Вам **повторно використовувати модель** у **різних місцях**, а також оголошувати перевірки та метадані для всіх параметрів одночасно. 😎 + +/// note | Примітка + +Ця можливість підтримується, починаючи з версії FastAPI `0.115.0`. 🤓 + +/// + +## Query параметри з Pydantic-моделлю + +Оголосіть **query параметри**, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть цей параметр як `Query`: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI** буде **витягувати** дані для **кожного поля** з **query параметрів** у запиті та передавати їх у визначену вами Pydantic-модель. + +## Перевірте документацію + +Ви можете побачити параметри запиту в UI документації за `/docs`: + +
+ +
+ +## Заборона зайвих Query параметрів + +У деяких особливих випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** query параметри, які дозволено отримувати. + +Ви можете використати конфігурацію моделі Pydantic, щоб заборонити (`forbid`) будь-які зайві (`extra`) поля: + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +Якщо клієнт спробує надіслати **зайві** дані у **query параметрах**, він отримає **помилку**. + +Наприклад, якщо клієнт спробує надіслати query параметр `tool` зі значенням `plumbus`, як у цьому запиті: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +Він отримає відповідь з **помилкою**, яка повідомить, що query параметр `tool ` не дозволено: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## Підсумок + +Ви можете використовувати **Pydantic-моделі** для оголошення **query параметрів** у **FastAPI**. 😎 + +/// tip | Підказка + +Спойлер: Ви також можете використовувати Pydantic-моделі для оголошення cookie та заголовків, але про це Ви дізнаєтеся пізніше в цьому посібнику. 🤫 + +/// From 2e2180809411b0235b24bba6a40b8151ade593d0 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 5 Jun 2025 12:12:28 +0000 Subject: [PATCH 157/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b2f083e1c..c4150413d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params-str-validations.md` page. PR [#13546](https://github.com/fastapi/fastapi/pull/13546) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-param-models.md`. PR [#13616](https://github.com/fastapi/fastapi/pull/13616) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). From 2116d8aa564c9a70100225781f76ff2a7687bcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 5 Jun 2025 14:27:20 +0200 Subject: [PATCH 158/455] =?UTF-8?q?=F0=9F=8D=B1=20Update=20sponsors:=20Dri?= =?UTF-8?q?bia=20badge=20size=20(#13773)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/img/sponsors/dribia.png | Bin 14770 -> 19211 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/en/docs/img/sponsors/dribia.png b/docs/en/docs/img/sponsors/dribia.png index a6760a47b8acba1ac4ba5f13fa479f6daf1b9b02..f40e140863503d7d35622acc061c60acce9b0d5b 100644 GIT binary patch literal 19211 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 Date: Thu, 5 Jun 2025 12:27:46 +0000 Subject: [PATCH 159/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c4150413d..394b3fde6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -46,6 +46,7 @@ hide: ### Internal +* 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: add Dribia. PR [#13771](https://github.com/fastapi/fastapi/pull/13771) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump typer from 0.15.3 to 0.16.0. PR [#13752](https://github.com/fastapi/fastapi/pull/13752) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13754](https://github.com/fastapi/fastapi/pull/13754) by [@tiangolo](https://github.com/tiangolo). From 9c4a1d2105c84e8115378fce68a4751a38d58834 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Jun 2025 18:10:20 +0200 Subject: [PATCH 160/455] =?UTF-8?q?=E2=AC=86=20Bump=20griffe-typingdoc=20f?= =?UTF-8?q?rom=200.2.7=20to=200.2.8=20(#13751)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [griffe-typingdoc](https://github.com/mkdocstrings/griffe-typingdoc) from 0.2.7 to 0.2.8. - [Release notes](https://github.com/mkdocstrings/griffe-typingdoc/releases) - [Changelog](https://github.com/mkdocstrings/griffe-typingdoc/blob/main/CHANGELOG.md) - [Commits](https://github.com/mkdocstrings/griffe-typingdoc/compare/0.2.7...0.2.8) --- updated-dependencies: - dependency-name: griffe-typingdoc dependency-version: 0.2.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 9de608eb2..606314926 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -12,7 +12,7 @@ pillow==11.1.0 # For image processing by Material for MkDocs cairosvg==2.7.1 mkdocstrings[python]==0.26.1 -griffe-typingdoc==0.2.7 +griffe-typingdoc==0.2.8 # For griffe, it formats with black black==25.1.0 mkdocs-macros-plugin==1.3.7 From f7ab09884dd39e8c9bd090b97d66f51fd3a7f401 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 5 Jun 2025 16:10:42 +0000 Subject: [PATCH 161/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 394b3fde6..80beb2189 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -46,6 +46,7 @@ hide: ### Internal +* ⬆ Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: add Dribia. PR [#13771](https://github.com/fastapi/fastapi/pull/13771) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump typer from 0.15.3 to 0.16.0. PR [#13752](https://github.com/fastapi/fastapi/pull/13752) by [@dependabot[bot]](https://github.com/apps/dependabot). From 7b3463de32cd751b68de885771fa9e07395fa537 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 16:08:32 +0200 Subject: [PATCH 162/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13757)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.11 → v0.11.12](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.11...v0.11.12) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 445676b8b..21413fc66 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.11 + rev: v0.11.12 hooks: - id: ruff args: From 9ab43cc5eda66c7622ea8f4ecf70f76b7499d772 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 6 Jun 2025 14:08:55 +0000 Subject: [PATCH 163/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 80beb2189..2769abd8c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -46,6 +46,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: add Dribia. PR [#13771](https://github.com/fastapi/fastapi/pull/13771) by [@tiangolo](https://github.com/tiangolo). From 4b12a2818a7eb4ac45da8afedeb29d7030104f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charlie=20=E2=9C=A8?= <18888351756@163.com> Date: Mon, 9 Jun 2025 12:15:17 +0800 Subject: [PATCH 164/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Remove=20redundant?= =?UTF-8?q?=20words=20in=20docs/zh/docs/python-types.md=20(#13774)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/python-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 5126cb847..ba767da87 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -228,7 +228,7 @@ John Doe ## Pydantic 模型 -Pydantic 是一个用来用来执行数据校验的 Python 库。 +Pydantic 是一个用来执行数据校验的 Python 库。 你可以将数据的"结构"声明为具有属性的类。 From 37c8e7d76b4b47eb2c4cced6b4de59eb3d5f08eb Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 9 Jun 2025 04:15:43 +0000 Subject: [PATCH 165/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2769abd8c..b5d7f8d3a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* ✏️ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params-str-validations.md` page. PR [#13546](https://github.com/fastapi/fastapi/pull/13546) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 14a55d864d7c30c7933b4fb5ea16e724a59b54f2 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Mon, 9 Jun 2025 22:35:48 +0300 Subject: [PATCH 166/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/schema-extra-example.md`?= =?UTF-8?q?=20(#13769)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Ukrainian translation for docs/uk/docs/tutorial/schema-extra-example.md page * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Co-authored-by: Valentyn Druzhynin Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/uk/docs/tutorial/schema-extra-example.md | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 docs/uk/docs/tutorial/schema-extra-example.md diff --git a/docs/uk/docs/tutorial/schema-extra-example.md b/docs/uk/docs/tutorial/schema-extra-example.md new file mode 100644 index 000000000..853fd5e65 --- /dev/null +++ b/docs/uk/docs/tutorial/schema-extra-example.md @@ -0,0 +1,222 @@ +# Декларування прикладів вхідних даних + +Ви можете задати приклади даних, які Ваш застосунок може отримувати. + +Ось кілька способів, як це зробити. + +## Додаткові дані JSON-схеми в моделях Pydantic + +Ви можете задати `examples` для моделі Pydantic, які буде додано до згенерованої JSON-схеми. + +//// tab | Pydantic v2 + +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} + +//// + +//// tab | Pydantic v1 + +{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *} + +//// + +Ця додаткова інформація буде додана як є до **JSON-схеми**, і вона буде використовуватися в документації до API. + +//// tab | Pydantic v2 + +У версії Pydantic 2 використовується атрибут `model_config`, який приймає `dict`, як описано в документації Pydantic: Конфігурація. + +Ви можете встановити `"json_schema_extra"` як `dict`, що містить будь-які додаткові дані, які Ви хочете відобразити у згенерованій JSON-схемі, включаючи `examples`. + +//// + +//// tab | Pydantic v1 + +У версії Pydantic 1 використовується внутрішній клас `Config` і параметр `schema_extra`, як описано в документації Pydantic: Налаштування схеми. + +Ви можете задати `schema_extra` як `dict`, що містить будь-які додаткові дані, які Ви хочете бачити у згенерованій JSON-схемі, включаючи `examples`. + +//// + +/// tip | Підказка + +Ви можете використати ту ж техніку, щоб розширити JSON-схему і додати власну додаткову інформацію. + +Наприклад, Ви можете використати її для додавання метаданих для інтерфейсу користувача на фронтенді тощо. + +/// + +/// info | Інформація + +OpenAPI 3.1.0 (який використовується починаючи з FastAPI 0.99.0) додав підтримку `examples`, що є частиною стандарту **JSON-схеми**. + +До цього підтримувався лише ключ `example` з одним прикладом. Він все ще підтримується в OpenAPI 3.1.0, але є застарілим і не входить до стандарту JSON Schema. Тому рекомендується перейти з `example` на `examples`. 🤓 + +Більше про це можна прочитати в кінці цієї сторінки. + +/// + +## Додаткові аргументи `Field` + +Коли ви використовуєте `Field()` у моделях Pydantic, Ви також можете вказати додаткові `examples`: + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## `examples` у JSON-схемі — OpenAPI + +При використанні будь-кого з наступного: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +Ви також можете задати набір `examples` з додатковою інформацією, яка буде додана до їхніх **JSON-схем** у **OpenAPI**. + +### `Body` з `examples` + +Тут ми передаємо `examples`, які містять один приклад очікуваних даних у `Body()`: + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### Приклад у UI документації + +За допомогою будь-якого з наведених вище методів це виглядатиме так у документації за `/docs`: + + + +### `Body` з кількома `examples` + +Звичайно, Ви також можете передати кілька `examples`: + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +Коли Ви це робите, приклади будуть частиною внутрішньої **JSON-схеми** для цих даних. + +Втім, на момент написання цього (26 серпня 2023), Swagger UI — інструмент, який відповідає за відображення UI документації — не підтримує показ кількох прикладів у **JSON-схеми**. Але нижче можна прочитати про обхідний шлях. + +### Специфічні для OpenAPI `examples` + +Ще до того, як **JSON-схема** почала підтримувати `examples`, OpenAPI вже мала підтримку поля з такою ж назвою — `examples`. + +Це **специфічне для OpenAPI** поле `examples` розміщується в іншій частині специфікації OpenAPI — у **деталях кожної *операції шляху***, а не всередині самої JSON-схеми. + +Swagger UI вже давно підтримує це поле `examples`. Тому Ви можете використовувати його, щоб **відображати** кілька **прикладів у документації**. + +Це поле `examples` у специфікації OpenAPI — це `dict` (словник) з **кількома прикладами** (а не список `list`), кожен із яких може містити додаткову інформацію, що буде додана до **OpenAPI**. + +Воно не включається до JSON Schema кожного параметра, а розміщується зовні, безпосередньо в *операції шляху*. + +### Використання параметра `openapi_examples` + +Ви можете оголосити специфічні для OpenAPI `examples` у FastAPI за допомогою параметра `openapi_examples` для: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +Ключі словника (`dict`) ідентифікують кожен приклад, а кожне значення `dict` — кожен специфічний словник `dict` в `examples` може містити: + +* `summary`: короткий опис прикладу. +* `description`: розгорнутий опис (може містити Markdown). +* `value`: сам приклад, наприклад, словник (`dict`). +* `externalValue`: альтернатива `value`, URL-адреса, що вказує на приклад. Проте ця опція може не підтримуватися більшістю інструментів, на відміну від `value`. + +Використання виглядає так: + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### Приклади OpenAPI у UI документації + +З параметром `openapi_examples`, доданим до `Body()`, документація `/docs` виглядатиме так: + + + +## Технічні деталі + +/// tip | Підказка + +Якщо Ви вже використовуєте **FastAPI** версії **0.99.0 або вище**, Ви можете **пропустити** цей розділ. + +Він більш актуальний для старих версій, до появи OpenAPI 3.1.0. + +Можна вважати це коротким **історичним екскурсом** у OpenAPI та JSON Schema. 🤓 + +/// + +/// warning | Попередження + +Це дуже технічна інформація про стандарти **JSON Schema** і **OpenAPI**. + +Якщо вищезгадані ідеї вже працюють у Вас — можете не заглиблюватися в ці деталі. + +/// + +До OpenAPI 3.1.0 специфікація використовувала стару та модифіковану версію **JSON Schema**. + +Оскільки JSON Schema раніше не підтримувала `examples`, OpenAPI додала власне поле `examples`. + +OpenAPI також додала `example` і `examples` до інших частин специфікації: + +* `Parameter Object` (в специфікації) використовується FastAPI для: + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* `Request Body Object`, в полі `content`, в `Media Type Object` (в специфікації) використовується FastAPI для: + * `Body()` + * `File()` + * `Form()` + +/// info | Інформація + +Цей старий параметр `examples`, специфічний для OpenAPI, тепер називається `openapi_examples`, починаючи з FastAPI версії `0.103.0`. + +/// + +### Поле `examples` у JSON Schema + +Пізніше JSON Schema додала поле `examples` у нову версію специфікації. + +І вже OpenAPI 3.1.0 базується на цій новій версії (JSON Schema 2020-12), яка включає поле `examples`. + +Тепер це поле `examples` є пріоритетним і замінює старе (і кастомне) поле `example`, яке стало застарілим. + +Нове поле `examples` у JSON Schema — це **просто список (`list`)** прикладів, без додаткових метаданих (на відміну від OpenAPI). + +/// info | Інформація + +Навіть після того, як з'явився OpenAPI 3.1.0, який підтримував examples у JSON Schema, інструмент Swagger UI ще деякий час не підтримував цю версію (підтримка з’явилась з версії 5.0.0 🎉). + +Через це версії FastAPI до 0.99.0 все ще використовували версії OpenAPI нижчі за 3.1.0. + +/// + +### `Examples` в Pydantic і FastAPI + +Коли Ви додаєте `examples` у модель Pydantic через `schema_extra` або `Field(examples=["something"])`, ці приклади додаються до **JSON Schema** цієї моделі. + +І ця **JSON Schema** Pydantic-моделі включається до **OpenAPI** Вашого API, а потім використовується в UI документації (docs UI). + +У версіях FastAPI до 0.99.0 (починаючи з 0.99.0 використовується новіший OpenAPI 3.1.0), коли Ви використовували `example` або `examples` з іншими утилітами (`Query()`, `Body()` тощо), ці приклади не додавалися до JSON Schema, який описує ці дані (навіть не до власної версії JSON Schema у OpenAPI). Натомість вони додавалися безпосередньо до опису *обробника шляху* *(path operation)* в OpenAPI (тобто поза межами частин, які використовують JSON Schema). + +Але тепер, коли FastAPI 0.99.0 і вище використовують OpenAPI 3.1.0, а той — JSON Schema 2020-12, разом із Swagger UI 5.0.0 і вище — все стало більш узгодженим, і examples тепер включаються до JSON Schema. + +### Swagger UI та специфічні для OpenAPI `examples` + +Раніше (станом на 26 серпня 2023 року) Swagger UI не підтримував кілька прикладів у JSON Schema, тому користувачі не мали можливості показати декілька прикладів у документації. + +Щоб вирішити це, FastAPI починаючи з версії 0.103.0 **додав підтримку** старого **OpenAPI-специфічного** поля `examples` через новий параметр `openapi_examples`. 🤓 + +### Підсумок + +Раніше я казав, що не люблю історію... а тепер ось я — розповідаю "технічні історичні" лекції. 😅 + +Коротко: **оновіться до FastAPI 0.99.0 або вище** — і все стане значно **простішим, узгодженим та інтуїтивно зрозумілим**, і Вам не доведеться знати всі ці історичні деталі. 😎 From b8a3cccb75e11997b9b48b32db20f1f29b54f75a Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 9 Jun 2025 19:36:09 +0000 Subject: [PATCH 167/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b5d7f8d3a..a9747b9da 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/schema-extra-example.md`. PR [#13769](https://github.com/fastapi/fastapi/pull/13769) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✏️ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly). From cdd5d6ce709bfe16c9f6268d41a6a192b222f84b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 21:40:54 +0200 Subject: [PATCH 168/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13781)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.12 → v0.11.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.12...v0.11.13) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21413fc66..7af88b5aa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.12 + rev: v0.11.13 hooks: - id: ruff args: From 98fa4bd4374f736b1e516c29cb5447182455ac61 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 9 Jun 2025 19:41:14 +0000 Subject: [PATCH 169/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a9747b9da..267384c6b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -48,6 +48,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13781](https://github.com/fastapi/fastapi/pull/13781) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo). From 44d5abffc164b787832e2e3a83990e0a027a7eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 10 Jun 2025 18:52:33 +0200 Subject: [PATCH 170/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20rem?= =?UTF-8?q?ove=20Porter=20(#13783)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - docs/en/data/sponsors.yml | 3 --- docs/en/overrides/main.html | 6 ------ 3 files changed, 10 deletions(-) diff --git a/README.md b/README.md index da9446e2b..44fa2d3ac 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,6 @@ The key features are: - diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 897ca7b8d..b06e51477 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -5,9 +5,6 @@ gold: - url: https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023 title: "Build, run and scale your apps on a modern, reliable, and secure PaaS." img: https://fastapi.tiangolo.com/img/sponsors/platform-sh.png - - url: https://www.porter.run - title: Deploy FastAPI on AWS with a few clicks - img: https://fastapi.tiangolo.com/img/sponsors/porter.png - url: https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge title: "Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files" img: https://fastapi.tiangolo.com/img/sponsors/scalar.svg diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 89c8171d0..21a1d6906 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -38,12 +38,6 @@
-
From 5ba94612c1d5bab8ff7cdc627bebf76edfea36ba Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 10 Jun 2025 16:52:55 +0000 Subject: [PATCH 171/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 267384c6b..54c1275c2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -48,6 +48,7 @@ hide: ### Internal +* 🔧 Update sponsors: remove Porter. PR [#13783](https://github.com/fastapi/fastapi/pull/13783) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13781](https://github.com/fastapi/fastapi/pull/13781) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot). From 095dcc8a633a5a14059bbf7ed5d63c0d7744e482 Mon Sep 17 00:00:00 2001 From: ChaeYeong Hwang <79563565+NinaHwang@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:32:09 +0200 Subject: [PATCH 172/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Korean=20translati?= =?UTF-8?q?on=20for=20`docs/ko/docs/advanced/sub-applications.md`=20(#4543?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * This PR translates advanced/sub-applications.md in Korean. Test complete related: #2017 * Update sub-applications.md * Update sub-applications.md * Update sub-applications.md * remove .DS_Store * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks * Update docs/ko/docs/advanced/sub-applications.md * Update docs/ko/docs/advanced/sub-applications.md * Update docs/ko/docs/advanced/sub-applications.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/ko/docs/advanced/sub-applications.md | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/ko/docs/advanced/sub-applications.md diff --git a/docs/ko/docs/advanced/sub-applications.md b/docs/ko/docs/advanced/sub-applications.md new file mode 100644 index 000000000..c5835de15 --- /dev/null +++ b/docs/ko/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# 하위 응용프로그램 - 마운트 + +만약 각각의 독립적인 OpenAPI와 문서 UI를 갖는 두 개의 독립적인 FastAPI 응용프로그램이 필요하다면, 메인 어플리케이션에 하나 (또는 그 이상의) 하위-응용프로그램(들)을 “마운트"해서 사용할 수 있습니다. + +## **FastAPI** 응용프로그램 마운트 + +“마운트"이란 완전히 “독립적인" 응용프로그램을 특정 경로에 추가하여 해당 하위 응용프로그램에서 선언된 *경로 동작*을 통해 해당 경로 아래에 있는 모든 작업들을 처리할 수 있도록 하는 것을 의미합니다. + +### 최상단 응용프로그램 + +먼저, 메인, 최상단의 **FastAPI** 응용프로그램과 이것의 *경로 동작*을 생성합니다: + +{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *} + +### 하위 응용프로그램 + +다음으로, 하위 응용프로그램과 이것의 *경로 동작*을 생성합니다: + +이 하위 응용프로그램은 또 다른 표준 FastAPI 응용프로그램입니다. 다만 이것은 “마운트”될 것입니다: + +{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *} + +### 하위 응용프로그램 마운트 + +최상단 응용프로그램, `app`에 하위 응용프로그램, `subapi`를 마운트합니다. + +이 예시에서, 하위 응용프로그램션은 `/subapi` 경로에 마운트 될 것입니다: + +{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *} + +### 자동으로 생성된 API 문서 확인 + +이제, `uvicorn`으로 메인 응용프로그램을 실행하십시오. 당신의 파일이 `main.py`라면, 이렇게 실행합니다: + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +그리고
http://127.0.0.1:8000/docs에서 문서를 여십시오. + +메인 응용프로그램의 *경로 동작*만을 포함하는, 메인 응용프로그램에 대한 자동 API 문서를 확인할 수 있습니다: + + + +다음으로, http://127.0.0.1:8000/subapi/docs에서 하위 응용프로그램의 문서를 여십시오. + +하위 경로 접두사 `/subapi` 아래에 선언된 *경로 동작* 을 포함하는, 하위 응용프로그램에 대한 자동 API 문서를 확인할 수 있습니다: + + + +두 사용자 인터페이스 중 어느 하나를 사용해야하는 경우, 브라우저는 특정 응용프로그램 또는 하위 응용프로그램과 각각 통신할 수 있기 때문에 올바르게 동작할 것입니다. + +### 기술적 세부사항: `root_path` + +위에 설명된 것과 같이 하위 응용프로그램을 마운트하는 경우, FastAPI는 `root_path`라고 하는 ASGI 명세의 매커니즘을 사용하여 하위 응용프로그램에 대한 마운트 경로 통신을 처리합니다. + +이를 통해, 하위 응용프로그램은 문서 UI를 위해 경로 접두사를 사용해야 한다는 사실을 인지합니다. + +하위 응용프로그램에도 역시 다른 하위 응용프로그램을 마운트하는 것이 가능하며 FastAPI가 모든 `root_path` 들을 자동적으로 처리하기 때문에 모든 것은 올바르게 동작할 것입니다. + +`root_path`와 이것을 사용하는 방법에 대해서는 [프록시의 뒷단](./behind-a-proxy.md){.internal-link target=_blank} 섹션에서 배울 수 있습니다. From 1f79531a5b96654e41df14bdcff322ec3c3d707c Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 12 Jun 2025 07:32:29 +0000 Subject: [PATCH 173/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 54c1275c2..46dbf7536 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Korean translation for `docs/ko/docs/advanced/sub-applications.md`. PR [#4543](https://github.com/fastapi/fastapi/pull/4543) by [@NinaHwang](https://github.com/NinaHwang). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/schema-extra-example.md`. PR [#13769](https://github.com/fastapi/fastapi/pull/13769) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✏️ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 49fe5bac2ea90488156783c094bb13f61c2ea716 Mon Sep 17 00:00:00 2001 From: Mohammad <116789737+Mohammad222PR@users.noreply.github.com> Date: Mon, 16 Jun 2025 14:13:07 +0330 Subject: [PATCH 174/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Persian=20translat?= =?UTF-8?q?ion=20for=20`docs/fa/docs/learn/index.md`=20(#13518)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Persian translation for docs/fa/docs/learn/index.md * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/fa/docs/learn/index.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/fa/docs/learn/index.md diff --git a/docs/fa/docs/learn/index.md b/docs/fa/docs/learn/index.md new file mode 100644 index 000000000..06aa7f00e --- /dev/null +++ b/docs/fa/docs/learn/index.md @@ -0,0 +1,5 @@ +# یادگیری + +اینجا بخش‌های مقدماتی و آموزش‌هایی هستن که برای یادگیری **FastAPI** بهت کمک می‌کنن. + +می‌تونی اینو یه **کتاب**، یه **دوره آموزشی**، یا راه **رسمی** و پیشنهادی برای یادگیری FastAPI در نظر بگیری. 😎 From c7302ea99e32974edf7e97e5a1a649fece4368b3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 16 Jun 2025 10:43:29 +0000 Subject: [PATCH 175/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 46dbf7536..1fe954b58 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Persian translation for `docs/fa/docs/learn/index.md`. PR [#13518](https://github.com/fastapi/fastapi/pull/13518) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Korean translation for `docs/ko/docs/advanced/sub-applications.md`. PR [#4543](https://github.com/fastapi/fastapi/pull/4543) by [@NinaHwang](https://github.com/NinaHwang). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/schema-extra-example.md`. PR [#13769](https://github.com/fastapi/fastapi/pull/13769) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✏️ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa). From 6cbdcd3961552856045756ffaeee0eea20175142 Mon Sep 17 00:00:00 2001 From: Naves <79222417+NavesSapnis@users.noreply.github.com> Date: Mon, 16 Jun 2025 14:11:10 +0300 Subject: [PATCH 176/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20Translat?= =?UTF-8?q?ion=20for=20`docs/ru/docs/advanced/response-change-status-code.?= =?UTF-8?q?md`=20(#13791)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🌐 Add Russian Translation for docs/ru/docs/advanced/response-change-status-code.md --- .../advanced/response-change-status-code.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 docs/ru/docs/advanced/response-change-status-code.md diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md new file mode 100644 index 000000000..37dade99f --- /dev/null +++ b/docs/ru/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# Response - Изменение cтатус кода + +Вы, вероятно, уже читали о том, что можно установить [Состояние ответа по умолчанию](../tutorial/response-status-code.md){.internal-link target=_blank}. + +Но в некоторых случаях вам нужно вернуть код состояния, отличный от установленного по умолчанию. + +## Пример использования + +Например, представьте, что вы хотите возвращать HTTP код состояния "OK" `200` по умолчанию. + +Но если данные не существовали, вы хотите создать их и вернуть HTTP код состояния "CREATED" `201`. + +При этом вы всё ещё хотите иметь возможность фильтровать и преобразовывать возвращаемые данные с помощью `response_model`. + +Для таких случаев вы можете использовать параметр `Response`. + +## Использование параметра `Response` + +Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (так же как для cookies и headers). + +И затем вы можете установить `status_code` в этом *временном* объекте ответа. + +{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *} + +После этого вы можете вернуть любой объект, который вам нужен, как обычно (`dict`, модель базы данных и т.д.). + +И если вы объявили `response_model`, он всё равно будет использоваться для фильтрации и преобразования возвращаемого объекта. + +**FastAPI** будет использовать этот *временный* ответ для извлечения кода состояния (а также cookies и headers) и поместит их в финальный ответ, который содержит возвращаемое вами значение, отфильтрованное любым `response_model`. + +Вы также можете объявить параметр `Response` в зависимостях и установить код состояния в них. Но помните, что последнее установленное значение будет иметь приоритет. From 3ac38eb19580b22db77fcaebd40dfced40439b14 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 16 Jun 2025 11:11:36 +0000 Subject: [PATCH 177/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1fe954b58..1d0f9c0e9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Translations +* 🌐 Add Russian Translation for `docs/ru/docs/advanced/response-change-status-code.md`. PR [#13791](https://github.com/fastapi/fastapi/pull/13791) by [@NavesSapnis](https://github.com/NavesSapnis). * 🌐 Add Persian translation for `docs/fa/docs/learn/index.md`. PR [#13518](https://github.com/fastapi/fastapi/pull/13518) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Korean translation for `docs/ko/docs/advanced/sub-applications.md`. PR [#4543](https://github.com/fastapi/fastapi/pull/4543) by [@NinaHwang](https://github.com/NinaHwang). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/schema-extra-example.md`. PR [#13769](https://github.com/fastapi/fastapi/pull/13769) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From 590abc4b9634fa8363cfec85487bb8825520a7e3 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Tue, 17 Jun 2025 09:42:41 +0200 Subject: [PATCH 178/455] =?UTF-8?q?=F0=9F=93=9D=20Clarify=20the=20middlewa?= =?UTF-8?q?re=20execution=20order=20in=20docs=20(#13699)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/tutorial/middleware.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/en/docs/tutorial/middleware.md b/docs/en/docs/tutorial/middleware.md index 4f7980165..b7c03a319 100644 --- a/docs/en/docs/tutorial/middleware.md +++ b/docs/en/docs/tutorial/middleware.md @@ -65,6 +65,29 @@ Here we use Date: Tue, 17 Jun 2025 09:46:27 +0200 Subject: [PATCH 180/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20truncating=20the?= =?UTF-8?q?=20model's=20description=20with=20form=20feed=20(`\f`)=20charac?= =?UTF-8?q?ter=20for=20Pydantic=20V2=20(#13698)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- fastapi/_compat.py | 5 +++ ...napi_model_description_trim_on_formfeed.py | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/test_openapi_model_description_trim_on_formfeed.py diff --git a/fastapi/_compat.py b/fastapi/_compat.py index c07e4a3b0..227ad837d 100644 --- a/fastapi/_compat.py +++ b/fastapi/_compat.py @@ -16,6 +16,7 @@ from typing import ( Tuple, Type, Union, + cast, ) from fastapi.exceptions import RequestErrorModel @@ -231,6 +232,10 @@ if PYDANTIC_V2: field_mapping, definitions = schema_generator.generate_definitions( inputs=inputs ) + for item_def in cast(Dict[str, Dict[str, Any]], definitions).values(): + if "description" in item_def: + item_description = cast(str, item_def["description"]).split("\f")[0] + item_def["description"] = item_description return field_mapping, definitions # type: ignore[return-value] def is_scalar_field(field: ModelField) -> bool: diff --git a/tests/test_openapi_model_description_trim_on_formfeed.py b/tests/test_openapi_model_description_trim_on_formfeed.py new file mode 100644 index 000000000..e18d4f6b2 --- /dev/null +++ b/tests/test_openapi_model_description_trim_on_formfeed.py @@ -0,0 +1,31 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel + +app = FastAPI() + + +class MyModel(BaseModel): + """ + A model with a form feed character in the title. + \f + Text after form feed character. + """ + + +@app.get("/foo") +def foo(v: MyModel): # pragma: no cover + pass + + +client = TestClient(app) + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + openapi_schema = response.json() + + assert openapi_schema["components"]["schemas"]["MyModel"]["description"] == ( + "A model with a form feed character in the title.\n" + ) From 6e11a2d1c4eaedd891708d808a5b4c5d127db5db Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 07:46:49 +0000 Subject: [PATCH 181/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 57c7d27ee..fcca4f762 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Fix truncating the model's description with form feed (`\f`) character for Pydantic V2. PR [#13698](https://github.com/fastapi/fastapi/pull/13698) by [@YuriiMotov](https://github.com/YuriiMotov). + ### Upgrades * ⬆️ Update ReDoc to version 2.x. PR [#9700](https://github.com/fastapi/fastapi/pull/9700) by [@joakimnordling](https://github.com/joakimnordling). From 7c04182724f87e78c39d18d63803ee0108d159f6 Mon Sep 17 00:00:00 2001 From: Emmanuel Ferdman Date: Tue, 17 Jun 2025 10:50:19 +0300 Subject: [PATCH 182/455] =?UTF-8?q?=F0=9F=94=A8=20Resolve=20Pydantic=20dep?= =?UTF-8?q?recation=20warnings=20in=20internal=20script=20(#13696)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Emmanuel Ferdman --- scripts/label_approved.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/label_approved.py b/scripts/label_approved.py index 271444504..81de92efb 100644 --- a/scripts/label_approved.py +++ b/scripts/label_approved.py @@ -27,7 +27,7 @@ if settings.debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) -logging.debug(f"Using config: {settings.json()}") +logging.debug(f"Using config: {settings.model_dump_json()}") g = Github(settings.token.get_secret_value()) repo = g.get_repo(settings.github_repository) for pr in repo.get_pulls(state="open"): @@ -48,7 +48,7 @@ for pr in repo.get_pulls(state="open"): ] config = settings.config or default_config for approved_label, conf in config.items(): - logging.debug(f"Processing config: {conf.json()}") + logging.debug(f"Processing config: {conf.model_dump_json()}") if conf.await_label is None or (conf.await_label in pr_label_by_name): logging.debug(f"Processable PR: {pr.number}") if len(approved_reviews) >= conf.number: From 7dc9901f358f1097535fe5c5500a14edbfa34268 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 07:50:39 +0000 Subject: [PATCH 183/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fcca4f762..a561108a9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -56,6 +56,7 @@ hide: ### Internal +* 🔨 Resolve Pydantic deprecation warnings in internal script. PR [#13696](https://github.com/fastapi/fastapi/pull/13696) by [@emmanuel-ferdman](https://github.com/emmanuel-ferdman). * 🔧 Update sponsors: remove Porter. PR [#13783](https://github.com/fastapi/fastapi/pull/13783) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13781](https://github.com/fastapi/fastapi/pull/13781) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 97fdbdd0d8b3e24b3d850865033f6746ee13f82c Mon Sep 17 00:00:00 2001 From: Timon Date: Tue, 17 Jun 2025 10:05:34 +0200 Subject: [PATCH 184/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20exclude-paramet?= =?UTF-8?q?ers-from-openapi=20documentation=20links=20(#13600)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/applications.py | 18 +++++++++--------- fastapi/routing.py | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/fastapi/applications.py b/fastapi/applications.py index 6d427cdc2..194f088cd 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -748,7 +748,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -1720,7 +1720,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2093,7 +2093,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2471,7 +2471,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2849,7 +2849,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3222,7 +3222,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3595,7 +3595,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3968,7 +3968,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -4346,7 +4346,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, diff --git a/fastapi/routing.py b/fastapi/routing.py index 457481e32..bf61a65c1 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -814,7 +814,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -1626,7 +1626,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2003,7 +2003,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2385,7 +2385,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2767,7 +2767,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3144,7 +3144,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3521,7 +3521,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3903,7 +3903,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -4285,7 +4285,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, From 10bf65f27288db90a2b6ab2f1e37368473b6d004 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 08:05:54 +0000 Subject: [PATCH 185/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a561108a9..988791fbe 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Docs +* 📝 Update exclude-parameters-from-openapi documentation links. PR [#13600](https://github.com/fastapi/fastapi/pull/13600) by [@timonrieger](https://github.com/timonrieger). * 📝 Clarify the middleware execution order in docs. PR [#13699](https://github.com/fastapi/fastapi/pull/13699) by [@YuriiMotov](https://github.com/YuriiMotov). * 🍱 Update Drawio diagrams SVGs, single file per diagram, sans-serif font. PR [#13706](https://github.com/fastapi/fastapi/pull/13706) by [@tiangolo](https://github.com/tiangolo). * 📝 Update docs for "Help FastAPI", simplify and reduce "sponsor" section. PR [#13670](https://github.com/fastapi/fastapi/pull/13670) by [@tiangolo](https://github.com/tiangolo). From 6d78b228d8ffa7fe977bb2ccc25f0743af361f51 Mon Sep 17 00:00:00 2001 From: Swastik Pradhan <66001704+swastikpradhan1999@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:47:08 +0530 Subject: [PATCH 186/455] =?UTF-8?q?=F0=9F=93=9D=20Clarify=20guidance=20on?= =?UTF-8?q?=20using=20`async=20def`=20without=20`await`=20(#13642)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- docs/en/docs/async.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md index 63bd8ca68..8207ec480 100644 --- a/docs/en/docs/async.md +++ b/docs/en/docs/async.md @@ -40,7 +40,7 @@ def results(): --- -If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`. +If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`, even if you don't need to use `await` inside. --- From 1daf9fddfdf81515e6cab84327cd4b4e89e3fc15 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:17:31 +0000 Subject: [PATCH 187/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 988791fbe..9dff69cbb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Docs +* 📝 Clarify guidance on using `async def` without `await`. PR [#13642](https://github.com/fastapi/fastapi/pull/13642) by [@swastikpradhan1999](https://github.com/swastikpradhan1999). * 📝 Update exclude-parameters-from-openapi documentation links. PR [#13600](https://github.com/fastapi/fastapi/pull/13600) by [@timonrieger](https://github.com/timonrieger). * 📝 Clarify the middleware execution order in docs. PR [#13699](https://github.com/fastapi/fastapi/pull/13699) by [@YuriiMotov](https://github.com/YuriiMotov). * 🍱 Update Drawio diagrams SVGs, single file per diagram, sans-serif font. PR [#13706](https://github.com/fastapi/fastapi/pull/13706) by [@tiangolo](https://github.com/tiangolo). From b4524145e66b2ab873769bbbb8b1cbd13bf4ba78 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 17 Jun 2025 12:18:00 +0200 Subject: [PATCH 188/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typo=20in=20?= =?UTF-8?q?docstring=20(#13532)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/applications.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/applications.py b/fastapi/applications.py index 194f088cd..7a1db2532 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -4425,7 +4425,7 @@ class FastAPI(Starlette): app = FastAPI() - @app.put("/items/{item_id}") + @app.trace("/items/{item_id}") def trace_item(item_id: str): return None ``` From 4e4715b1318931dc69292255b449bfc026f75486 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:18:31 +0000 Subject: [PATCH 189/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9dff69cbb..ac4003d84 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Docs +* ✏️ Fix typo in docstring. PR [#13532](https://github.com/fastapi/fastapi/pull/13532) by [@comp64](https://github.com/comp64). * 📝 Clarify guidance on using `async def` without `await`. PR [#13642](https://github.com/fastapi/fastapi/pull/13642) by [@swastikpradhan1999](https://github.com/swastikpradhan1999). * 📝 Update exclude-parameters-from-openapi documentation links. PR [#13600](https://github.com/fastapi/fastapi/pull/13600) by [@timonrieger](https://github.com/timonrieger). * 📝 Clarify the middleware execution order in docs. PR [#13699](https://github.com/fastapi/fastapi/pull/13699) by [@YuriiMotov](https://github.com/YuriiMotov). From da4605b039d838a849b4edf0e57cf10230eaf956 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Tue, 17 Jun 2025 06:24:10 -0400 Subject: [PATCH 190/455] =?UTF-8?q?=E2=9C=85=20Simplify=20tests=20for=20`v?= =?UTF-8?q?alidate=5Fresponse=5Frecursive`=20(#13507)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Valentyn Druzhynin --- .../{app_pv1.py => app.py} | 12 +++-- .../app_pv2.py | 51 ------------------- ...py => test_validate_response_recursive.py} | 5 +- .../test_validate_response_recursive_pv2.py | 33 ------------ 4 files changed, 9 insertions(+), 92 deletions(-) rename tests/test_validate_response_recursive/{app_pv1.py => app.py} (79%) delete mode 100644 tests/test_validate_response_recursive/app_pv2.py rename tests/test_validate_response_recursive/{test_validate_response_recursive_pv1.py => test_validate_response_recursive.py} (90%) delete mode 100644 tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py diff --git a/tests/test_validate_response_recursive/app_pv1.py b/tests/test_validate_response_recursive/app.py similarity index 79% rename from tests/test_validate_response_recursive/app_pv1.py rename to tests/test_validate_response_recursive/app.py index 4cfc4b3ee..d23d27980 100644 --- a/tests/test_validate_response_recursive/app_pv1.py +++ b/tests/test_validate_response_recursive/app.py @@ -1,6 +1,7 @@ from typing import List from fastapi import FastAPI +from fastapi._compat import PYDANTIC_V2 from pydantic import BaseModel app = FastAPI() @@ -11,9 +12,6 @@ class RecursiveItem(BaseModel): name: str -RecursiveItem.update_forward_refs() - - class RecursiveSubitemInSubmodel(BaseModel): sub_items2: List["RecursiveItemViaSubmodel"] = [] name: str @@ -24,7 +22,13 @@ class RecursiveItemViaSubmodel(BaseModel): name: str -RecursiveSubitemInSubmodel.update_forward_refs() +if PYDANTIC_V2: + RecursiveItem.model_rebuild() + RecursiveSubitemInSubmodel.model_rebuild() + RecursiveItemViaSubmodel.model_rebuild() +else: + RecursiveItem.update_forward_refs() + RecursiveSubitemInSubmodel.update_forward_refs() @app.get("/items/recursive", response_model=RecursiveItem) diff --git a/tests/test_validate_response_recursive/app_pv2.py b/tests/test_validate_response_recursive/app_pv2.py deleted file mode 100644 index 8c93a8349..000000000 --- a/tests/test_validate_response_recursive/app_pv2.py +++ /dev/null @@ -1,51 +0,0 @@ -from typing import List - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class RecursiveItem(BaseModel): - sub_items: List["RecursiveItem"] = [] - name: str - - -RecursiveItem.model_rebuild() - - -class RecursiveSubitemInSubmodel(BaseModel): - sub_items2: List["RecursiveItemViaSubmodel"] = [] - name: str - - -class RecursiveItemViaSubmodel(BaseModel): - sub_items1: List[RecursiveSubitemInSubmodel] = [] - name: str - - -RecursiveSubitemInSubmodel.model_rebuild() -RecursiveItemViaSubmodel.model_rebuild() - - -@app.get("/items/recursive", response_model=RecursiveItem) -def get_recursive(): - return {"name": "item", "sub_items": [{"name": "subitem", "sub_items": []}]} - - -@app.get("/items/recursive-submodel", response_model=RecursiveItemViaSubmodel) -def get_recursive_submodel(): - return { - "name": "item", - "sub_items1": [ - { - "name": "subitem", - "sub_items2": [ - { - "name": "subsubitem", - "sub_items1": [{"name": "subsubsubitem", "sub_items2": []}], - } - ], - } - ], - } diff --git a/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py b/tests/test_validate_response_recursive/test_validate_response_recursive.py similarity index 90% rename from tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py rename to tests/test_validate_response_recursive/test_validate_response_recursive.py index de578ae03..21a299ab8 100644 --- a/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py +++ b/tests/test_validate_response_recursive/test_validate_response_recursive.py @@ -1,12 +1,9 @@ from fastapi.testclient import TestClient -from ..utils import needs_pydanticv1 +from .app import app -@needs_pydanticv1 def test_recursive(): - from .app_pv1 import app - client = TestClient(app) response = client.get("/items/recursive") assert response.status_code == 200, response.text diff --git a/tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py b/tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py deleted file mode 100644 index 7d45e7fe4..000000000 --- a/tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py +++ /dev/null @@ -1,33 +0,0 @@ -from fastapi.testclient import TestClient - -from ..utils import needs_pydanticv2 - - -@needs_pydanticv2 -def test_recursive(): - from .app_pv2 import app - - client = TestClient(app) - response = client.get("/items/recursive") - assert response.status_code == 200, response.text - assert response.json() == { - "sub_items": [{"name": "subitem", "sub_items": []}], - "name": "item", - } - - response = client.get("/items/recursive-submodel") - assert response.status_code == 200, response.text - assert response.json() == { - "name": "item", - "sub_items1": [ - { - "name": "subitem", - "sub_items2": [ - { - "name": "subsubitem", - "sub_items1": [{"name": "subsubsubitem", "sub_items2": []}], - } - ], - } - ], - } From 45fefe88cfecdae7798a56c7294640205ad21831 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:25:13 +0000 Subject: [PATCH 191/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ac4003d84..9aa0f796d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 🐛 Fix truncating the model's description with form feed (`\f`) character for Pydantic V2. PR [#13698](https://github.com/fastapi/fastapi/pull/13698) by [@YuriiMotov](https://github.com/YuriiMotov). +### Refactors + +* ✅ Simplify tests for `validate_response_recursive`. PR [#13507](https://github.com/fastapi/fastapi/pull/13507) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + ### Upgrades * ⬆️ Update ReDoc to version 2.x. PR [#9700](https://github.com/fastapi/fastapi/pull/9700) by [@joakimnordling](https://github.com/joakimnordling). From 85a2eed88836dde7d6c8e275c2abc36f4572e78d Mon Sep 17 00:00:00 2001 From: Valentyn Date: Tue, 17 Jun 2025 06:25:20 -0400 Subject: [PATCH 192/455] =?UTF-8?q?=E2=9C=85=20Simplify=20tests=20for=20`s?= =?UTF-8?q?ettings`=20(#13505)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Valentyn Druzhynin --- .../test_settings/test_tutorial001.py | 20 +++++++++++++++---- .../test_settings/test_tutorial001_pv1.py | 19 ------------------ 2 files changed, 16 insertions(+), 23 deletions(-) delete mode 100644 tests/test_tutorial/test_settings/test_tutorial001_pv1.py diff --git a/tests/test_tutorial/test_settings/test_tutorial001.py b/tests/test_tutorial/test_settings/test_tutorial001.py index eb30dbcee..92a5782d4 100644 --- a/tests/test_tutorial/test_settings/test_tutorial001.py +++ b/tests/test_tutorial/test_settings/test_tutorial001.py @@ -1,14 +1,26 @@ +import importlib + +import pytest from fastapi.testclient import TestClient from pytest import MonkeyPatch -from ...utils import needs_pydanticv2 +from ...utils import needs_pydanticv1, needs_pydanticv2 -@needs_pydanticv2 -def test_settings(monkeypatch: MonkeyPatch): +@pytest.fixture( + name="app", + params=[ + pytest.param("tutorial001", marks=needs_pydanticv2), + pytest.param("tutorial001_pv1", marks=needs_pydanticv1), + ], +) +def get_app(request: pytest.FixtureRequest, monkeypatch: MonkeyPatch): monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com") - from docs_src.settings.tutorial001 import app + mod = importlib.import_module(f"docs_src.settings.{request.param}") + return mod.app + +def test_settings(app): client = TestClient(app) response = client.get("/info") assert response.status_code == 200, response.text diff --git a/tests/test_tutorial/test_settings/test_tutorial001_pv1.py b/tests/test_tutorial/test_settings/test_tutorial001_pv1.py deleted file mode 100644 index e4659de66..000000000 --- a/tests/test_tutorial/test_settings/test_tutorial001_pv1.py +++ /dev/null @@ -1,19 +0,0 @@ -from fastapi.testclient import TestClient -from pytest import MonkeyPatch - -from ...utils import needs_pydanticv1 - - -@needs_pydanticv1 -def test_settings(monkeypatch: MonkeyPatch): - monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com") - from docs_src.settings.tutorial001_pv1 import app - - client = TestClient(app) - response = client.get("/info") - assert response.status_code == 200, response.text - assert response.json() == { - "app_name": "Awesome API", - "admin_email": "admin@example.com", - "items_per_user": 50, - } From 01c3ad2eb26fd029e5bebb3bd7eded3e56ae4a29 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:25:45 +0000 Subject: [PATCH 193/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9aa0f796d..2f7bda4b2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Refactors +* ✅ Simplify tests for `settings`. PR [#13505](https://github.com/fastapi/fastapi/pull/13505) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✅ Simplify tests for `validate_response_recursive`. PR [#13507](https://github.com/fastapi/fastapi/pull/13507) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). ### Upgrades From 3f908a47d9cd7f58ec12137626d74a82be93d350 Mon Sep 17 00:00:00 2001 From: Diego Fioravanti Date: Tue, 17 Jun 2025 12:36:59 +0200 Subject: [PATCH 194/455] =?UTF-8?q?=F0=9F=93=9D=20Clarify=20in=20CORS=20do?= =?UTF-8?q?cs=20that=20wildcards=20and=20credentials=20are=20mutually=20ex?= =?UTF-8?q?clusive=20(#9829)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sofie Van Landeghem Co-authored-by: Alejandra <90076947+alejsdev@users.noreply.github.com> Co-authored-by: Michael Jones Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: User Co-authored-by: Sebastián Ramírez --- docs/en/docs/tutorial/cors.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/tutorial/cors.md b/docs/en/docs/tutorial/cors.md index cf31cfcf5..5ca4437b3 100644 --- a/docs/en/docs/tutorial/cors.md +++ b/docs/en/docs/tutorial/cors.md @@ -57,7 +57,10 @@ The following arguments are supported: * `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`. * `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods. * `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for simple CORS requests. -* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified. +* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. + + None of `allow_origins`, `allow_methods` and `allow_headers` can be set to `['*']` if `allow_credentials` is set to `True`. All of them must be explicitly specified. + * `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`. * `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`. From 6b5b26fa61ee1f710467e6f8c8452a7e93104eae Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:37:30 +0000 Subject: [PATCH 195/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2f7bda4b2..3f20b8618 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -22,6 +22,7 @@ hide: ### Docs +* 📝 Clarify in CORS docs that wildcards and credentials are mutually exclusive. PR [#9829](https://github.com/fastapi/fastapi/pull/9829) by [@dfioravanti](https://github.com/dfioravanti). * ✏️ Fix typo in docstring. PR [#13532](https://github.com/fastapi/fastapi/pull/13532) by [@comp64](https://github.com/comp64). * 📝 Clarify guidance on using `async def` without `await`. PR [#13642](https://github.com/fastapi/fastapi/pull/13642) by [@swastikpradhan1999](https://github.com/swastikpradhan1999). * 📝 Update exclude-parameters-from-openapi documentation links. PR [#13600](https://github.com/fastapi/fastapi/pull/13600) by [@timonrieger](https://github.com/timonrieger). From 30b9dfb11cbef5257cd0006d73884a3c1920b7d4 Mon Sep 17 00:00:00 2001 From: oogee Date: Tue, 17 Jun 2025 05:41:59 -0500 Subject: [PATCH 196/455] =?UTF-8?q?=F0=9F=9A=B8=20Set=20format=20to=20pass?= =?UTF-8?q?word=20for=20fields=20`password`=20and=20`client=5Fsecret`=20in?= =?UTF-8?q?=20`OAuth2PasswordRequestForm`,=20make=20docs=20show=20password?= =?UTF-8?q?=20fields=20for=20passwords=20(#11032)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- fastapi/security/oauth2.py | 4 ++-- .../test_tutorial/test_security/test_tutorial003.py | 13 +++++++++++-- .../test_tutorial/test_security/test_tutorial005.py | 13 +++++++++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 5ffad5986..42ace07a3 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -85,7 +85,7 @@ class OAuth2PasswordRequestForm: ], password: Annotated[ str, - Form(), + Form(json_schema_extra={"format": "password"}), Doc( """ `password` string. The OAuth2 spec requires the exact field name @@ -130,7 +130,7 @@ class OAuth2PasswordRequestForm: ] = None, client_secret: Annotated[ Union[str, None], - Form(), + Form(json_schema_extra={"format": "password"}), Doc( """ If there's a `client_password` (and a `client_id`), they can be sent diff --git a/tests/test_tutorial/test_security/test_tutorial003.py b/tests/test_tutorial/test_security/test_tutorial003.py index 37fc2618f..2bbb2e851 100644 --- a/tests/test_tutorial/test_security/test_tutorial003.py +++ b/tests/test_tutorial/test_security/test_tutorial003.py @@ -163,7 +163,11 @@ def test_openapi_schema(client: TestClient): } ), "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, + "password": { + "title": "Password", + "type": "string", + "format": "password", + }, "scope": {"title": "Scope", "type": "string", "default": ""}, "client_id": IsDict( { @@ -179,11 +183,16 @@ def test_openapi_schema(client: TestClient): { "title": "Client Secret", "anyOf": [{"type": "string"}, {"type": "null"}], + "format": "password", } ) | IsDict( # TODO: remove when deprecating Pydantic v1 - {"title": "Client Secret", "type": "string"} + { + "title": "Client Secret", + "type": "string", + "format": "password", + } ), }, }, diff --git a/tests/test_tutorial/test_security/test_tutorial005.py b/tests/test_tutorial/test_security/test_tutorial005.py index 88c3d7815..ad644d61b 100644 --- a/tests/test_tutorial/test_security/test_tutorial005.py +++ b/tests/test_tutorial/test_security/test_tutorial005.py @@ -377,7 +377,11 @@ def test_openapi_schema(mod: ModuleType): } ), "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, + "password": { + "title": "Password", + "type": "string", + "format": "password", + }, "scope": {"title": "Scope", "type": "string", "default": ""}, "client_id": IsDict( { @@ -393,11 +397,16 @@ def test_openapi_schema(mod: ModuleType): { "title": "Client Secret", "anyOf": [{"type": "string"}, {"type": "null"}], + "format": "password", } ) | IsDict( # TODO: remove when deprecating Pydantic v1 - {"title": "Client Secret", "type": "string"} + { + "title": "Client Secret", + "type": "string", + "format": "password", + } ), }, }, From 64834d4a601bb9c9b648a737a88582a3edded297 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:42:46 +0000 Subject: [PATCH 197/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3f20b8618..cf73b0d47 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Refactors +* 🚸 Set format to password for fields `password` and `client_secret` in `OAuth2PasswordRequestForm`, make docs show password fields for passwords. PR [#11032](https://github.com/fastapi/fastapi/pull/11032) by [@Thodoris1999](https://github.com/Thodoris1999). * ✅ Simplify tests for `settings`. PR [#13505](https://github.com/fastapi/fastapi/pull/13505) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✅ Simplify tests for `validate_response_recursive`. PR [#13507](https://github.com/fastapi/fastapi/pull/13507) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From aebff5006fee3f45c634861ccd15885058ba0965 Mon Sep 17 00:00:00 2001 From: Salar Nosrati-Ershad Date: Tue, 17 Jun 2025 14:16:49 +0330 Subject: [PATCH 198/455] =?UTF-8?q?=E2=9C=A8=20Add=20`refreshUrl`=20parame?= =?UTF-8?q?ter=20in=20`OAuth2PasswordBearer`=20(#11460)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Salar Nosrati-Ershad Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alejandra <90076947+alejsdev@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- fastapi/security/oauth2.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 42ace07a3..88e394db1 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -457,11 +457,26 @@ class OAuth2PasswordBearer(OAuth2): """ ), ] = True, + refreshUrl: Annotated[ + Optional[str], + Doc( + """ + The URL to refresh the token and obtain a new one. + """ + ), + ] = None, ): if not scopes: scopes = {} flows = OAuthFlowsModel( - password=cast(Any, {"tokenUrl": tokenUrl, "scopes": scopes}) + password=cast( + Any, + { + "tokenUrl": tokenUrl, + "refreshUrl": refreshUrl, + "scopes": scopes, + }, + ) ) super().__init__( flows=flows, From 9957956ef8be8f5e4947f3bc201bd95491fb4680 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:47:13 +0000 Subject: [PATCH 199/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index cf73b0d47..341baf77f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Refactors +* ✨ Add `refreshUrl` parameter in `OAuth2PasswordBearer`. PR [#11460](https://github.com/fastapi/fastapi/pull/11460) by [@snosratiershad](https://github.com/snosratiershad). * 🚸 Set format to password for fields `password` and `client_secret` in `OAuth2PasswordRequestForm`, make docs show password fields for passwords. PR [#11032](https://github.com/fastapi/fastapi/pull/11032) by [@Thodoris1999](https://github.com/Thodoris1999). * ✅ Simplify tests for `settings`. PR [#13505](https://github.com/fastapi/fastapi/pull/13505) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✅ Simplify tests for `validate_response_recursive`. PR [#13507](https://github.com/fastapi/fastapi/pull/13507) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From dfe9dde982fe63261aecc13f564670b82011846c Mon Sep 17 00:00:00 2001 From: Gabriel Date: Tue, 17 Jun 2025 06:48:10 -0400 Subject: [PATCH 200/455] =?UTF-8?q?=F0=9F=93=9D=20Add=20annotations=20to?= =?UTF-8?q?=20HTTP=20middleware=20example=20(#11530)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sofie Van Landeghem Co-authored-by: Sebastián Ramírez --- fastapi/applications.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fastapi/applications.py b/fastapi/applications.py index 7a1db2532..05c7bd2be 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -4515,14 +4515,17 @@ class FastAPI(Starlette): ```python import time + from typing import Awaitable, Callable - from fastapi import FastAPI, Request + from fastapi import FastAPI, Request, Response app = FastAPI() @app.middleware("http") - async def add_process_time_header(request: Request, call_next): + async def add_process_time_header( + request: Request, call_next: Callable[[Request], Awaitable[Response]] + ) -> Response: start_time = time.time() response = await call_next(request) process_time = time.time() - start_time From cdf6b315055a6a10c5fa86a248a7398d310082c4 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 10:48:39 +0000 Subject: [PATCH 201/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 341baf77f..77cf98cbc 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Docs +* 📝 Add annotations to HTTP middleware example. PR [#11530](https://github.com/fastapi/fastapi/pull/11530) by [@Kilo59](https://github.com/Kilo59). * 📝 Clarify in CORS docs that wildcards and credentials are mutually exclusive. PR [#9829](https://github.com/fastapi/fastapi/pull/9829) by [@dfioravanti](https://github.com/dfioravanti). * ✏️ Fix typo in docstring. PR [#13532](https://github.com/fastapi/fastapi/pull/13532) by [@comp64](https://github.com/comp64). * 📝 Clarify guidance on using `async def` without `await`. PR [#13642](https://github.com/fastapi/fastapi/pull/13642) by [@swastikpradhan1999](https://github.com/swastikpradhan1999). From 4734df1db89607c9579d2bb9795b02214e1e1d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 17 Jun 2025 13:41:24 +0200 Subject: [PATCH 202/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?5.13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 77cf98cbc..f21f3e101 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.115.13 + ### Fixes * 🐛 Fix truncating the model's description with form feed (`\f`) character for Pydantic V2. PR [#13698](https://github.com/fastapi/fastapi/pull/13698) by [@YuriiMotov](https://github.com/YuriiMotov). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 80eb783da..1768d0204 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.115.12" +__version__ = "0.115.13" from starlette import status as status From 7d9195a248a7bf29a1bc700a49399804b7b7ea00 Mon Sep 17 00:00:00 2001 From: Nolan Di Mare Sullivan Date: Tue, 17 Jun 2025 04:53:56 -0700 Subject: [PATCH 203/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20Speakeasy=20URL?= =?UTF-8?q?=20to=20Speakeasy=20Sandbox=20(#13697)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/de/docs/advanced/generate-clients.md | 2 +- docs/en/data/sponsors.yml | 2 +- docs/en/docs/advanced/generate-clients.md | 2 +- docs/es/docs/advanced/generate-clients.md | 2 +- docs/pt/docs/advanced/generate-clients.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 44fa2d3ac..ab5143084 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ The key features are: - + diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md index 38a69031c..f491d29af 100644 --- a/docs/de/docs/advanced/generate-clients.md +++ b/docs/de/docs/advanced/generate-clients.md @@ -20,7 +20,7 @@ Einige von diesen ✨ [**sponsern FastAPI**](../help-fastapi.md#den-autor-sponse Und es zeigt deren wahres Engagement für FastAPI und seine **Community** (Sie), da diese Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie über ein **gutes und gesundes Framework** verfügen, FastAPI. 🙇 -Beispielsweise könnten Sie Speakeasy ausprobieren. +Beispielsweise könnten Sie Speakeasy ausprobieren. Es gibt auch mehrere andere Unternehmen, welche ähnliche Dienste anbieten und die Sie online suchen und finden können. 🤓 diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index b06e51477..f712b6179 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -30,7 +30,7 @@ silver: - url: https://databento.com/ title: Pay as you go for market data img: https://fastapi.tiangolo.com/img/sponsors/databento.svg - - url: https://speakeasy.com?utm_source=fastapi+repo&utm_medium=github+sponsorship + - url: https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship title: SDKs for your API | Speakeasy img: https://fastapi.tiangolo.com/img/sponsors/speakeasy.png - url: https://www.svix.com/ diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index b2aef5037..55e6a08b1 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -22,7 +22,7 @@ And it shows their true commitment to FastAPI and its **community** (you), as th For example, you might want to try: -* Speakeasy +* Speakeasy * Stainless * liblab diff --git a/docs/es/docs/advanced/generate-clients.md b/docs/es/docs/advanced/generate-clients.md index bf2e5cb4f..b664bceac 100644 --- a/docs/es/docs/advanced/generate-clients.md +++ b/docs/es/docs/advanced/generate-clients.md @@ -22,7 +22,7 @@ Y muestra su verdadero compromiso con FastAPI y su **comunidad** (tú), ya que n Por ejemplo, podrías querer probar: -* Speakeasy +* Speakeasy * Stainless * liblab diff --git a/docs/pt/docs/advanced/generate-clients.md b/docs/pt/docs/advanced/generate-clients.md index 04d7c0071..dc6b29511 100644 --- a/docs/pt/docs/advanced/generate-clients.md +++ b/docs/pt/docs/advanced/generate-clients.md @@ -22,7 +22,7 @@ E isso mostra o verdadeiro compromisso deles com o FastAPI e sua **comunidade** Por exemplo, você pode querer experimentar: -* Speakeasy +* Speakeasy * Stainless * liblab From ac160885e15627073ba950c4a5203e3d168dee05 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 17 Jun 2025 11:54:19 +0000 Subject: [PATCH 204/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f21f3e101..683266f96 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Update Speakeasy URL to Speakeasy Sandbox. PR [#13697](https://github.com/fastapi/fastapi/pull/13697) by [@ndimares](https://github.com/ndimares). + ## 0.115.13 ### Fixes From b2923282caaf47d7af13991d3cae74b5c042b4b3 Mon Sep 17 00:00:00 2001 From: Naves <79222417+NavesSapnis@users.noreply.github.com> Date: Wed, 18 Jun 2025 11:40:59 +0300 Subject: [PATCH 205/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translat?= =?UTF-8?q?ion=20for=20`docs/ru/docs/advanced/index.md`=20(#13797)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Russian Translation for `docs/ru/docs/advanced/index.md` * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/ru/docs/advanced/index.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/ru/docs/advanced/index.md diff --git a/docs/ru/docs/advanced/index.md b/docs/ru/docs/advanced/index.md new file mode 100644 index 000000000..b5cb733e7 --- /dev/null +++ b/docs/ru/docs/advanced/index.md @@ -0,0 +1,21 @@ +# Расширенное руководство пользователя + +## Дополнительные возможности + +Основное [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} должно быть достаточно, чтобы познакомить вас со всеми основными функциями **FastAPI**. + +В следующих разделах вы увидите другие варианты, конфигурации и дополнительные возможности. + +/// tip + +Следующие разделы **не обязательно являются "продвинутыми"**. + +И вполне возможно, что для вашего случая использования решение находится в одном из них. + +/// + +## Сначала прочитайте Учебник - Руководство пользователя + +Вы все еще можете использовать большинство функций **FastAPI** со знаниями из [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank}. + +И следующие разделы предполагают, что вы уже прочитали его, и предполагают, что вы знаете эти основные идеи. From 8d9ef5d343998e9db3cae165e3ff15a23b967e51 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 18 Jun 2025 08:41:19 +0000 Subject: [PATCH 206/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 683266f96..be5d4e2e1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📝 Update Speakeasy URL to Speakeasy Sandbox. PR [#13697](https://github.com/fastapi/fastapi/pull/13697) by [@ndimares](https://github.com/ndimares). +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis). + ## 0.115.13 ### Fixes From 9026f3b1bdfba4ac33ba5d88a9fa4bed83f84108 Mon Sep 17 00:00:00 2001 From: Naves <79222417+NavesSapnis@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:22:18 +0300 Subject: [PATCH 207/455] Misprint (#13800) --- docs/en/docs/advanced/response-directly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md index 691b1e7cd..759b762b5 100644 --- a/docs/en/docs/advanced/response-directly.md +++ b/docs/en/docs/advanced/response-directly.md @@ -58,7 +58,7 @@ You could put your XML content in a string, put that in a `Response`, and return ## Notes -When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically. +When you return a `Response` directly its data is not validated, converted (serialized), or documented automatically. But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}. From 28038f19cfae040c826ad7a89f511fc854d9d44f Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 18 Jun 2025 18:22:42 +0000 Subject: [PATCH 208/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index be5d4e2e1..68eeaae7b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* Misprint. PR [#13800](https://github.com/fastapi/fastapi/pull/13800) by [@NavesSapnis](https://github.com/NavesSapnis). * 📝 Update Speakeasy URL to Speakeasy Sandbox. PR [#13697](https://github.com/fastapi/fastapi/pull/13697) by [@ndimares](https://github.com/ndimares). ### Translations From 041a37bb1feae2990e99379ed44ea45556a81e09 Mon Sep 17 00:00:00 2001 From: Hirokatsu Endo Date: Sun, 22 Jun 2025 23:34:53 +0900 Subject: [PATCH 209/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typo=20in=20?= =?UTF-8?q?`docs/ja/docs/tutorial/body-fields.md`=20(#13802)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ja/docs/tutorial/body-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ja/docs/tutorial/body-fields.md b/docs/ja/docs/tutorial/body-fields.md index 0466320f1..ce5630351 100644 --- a/docs/ja/docs/tutorial/body-fields.md +++ b/docs/ja/docs/tutorial/body-fields.md @@ -44,7 +44,7 @@ 追加情報は`Field`や`Query`、`Body`などで宣言することができます。そしてそれは生成されたJSONスキーマに含まれます。 -後に例を用いて宣言を学ぶ際に、追加情報を句悪方法を学べます。 +後に例を用いて宣言を学ぶ際に、追加情報を追加する方法を学べます。 ## まとめ From e9c33debaa4e6dea3e56b60ec80479c0eb3520ed Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 22 Jun 2025 14:35:16 +0000 Subject: [PATCH 210/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 68eeaae7b..e5f2cf100 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ✏️ Fix typo in `docs/ja/docs/tutorial/body-fields.md`. PR [#13802](https://github.com/fastapi/fastapi/pull/13802) by [@ruzia](https://github.com/ruzia). * 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis). ## 0.115.13 From 487f940e91b6d7a39a0b2e3b722baa956c72e1cd Mon Sep 17 00:00:00 2001 From: Hirokatsu Endo Date: Sun, 22 Jun 2025 23:35:27 +0900 Subject: [PATCH 211/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typo=20in=20?= =?UTF-8?q?`docs/ja/docs/tutorial/handling-errors.md`=20(#13814)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ja/docs/tutorial/handling-errors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ja/docs/tutorial/handling-errors.md b/docs/ja/docs/tutorial/handling-errors.md index 9a46cc738..37315b087 100644 --- a/docs/ja/docs/tutorial/handling-errors.md +++ b/docs/ja/docs/tutorial/handling-errors.md @@ -63,7 +63,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。 `HTTPException`を発生させる際には、`str`だけでなく、JSONに変換できる任意の値を`detail`パラメータとして渡すことができます。 -`dist`や`list`などを渡すことができます。 +`dict`や`list`などを渡すことができます。 これらは **FastAPI** によって自動的に処理され、JSONに変換されます。 From baeeafa1e1f2622c4b5115d37bf75653dff071ea Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 22 Jun 2025 14:35:47 +0000 Subject: [PATCH 212/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e5f2cf100..3fd184a1f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ✏️ Fix typo in `docs/ja/docs/tutorial/handling-errors.md`. PR [#13814](https://github.com/fastapi/fastapi/pull/13814) by [@ruzia](https://github.com/ruzia). * ✏️ Fix typo in `docs/ja/docs/tutorial/body-fields.md`. PR [#13802](https://github.com/fastapi/fastapi/pull/13802) by [@ruzia](https://github.com/ruzia). * 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis). From dcb223d8507b3eb8d28da781a2d96a09e1008fd0 Mon Sep 17 00:00:00 2001 From: Hirokatsu Endo Date: Sun, 22 Jun 2025 23:36:05 +0900 Subject: [PATCH 213/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typo=20in=20?= =?UTF-8?q?`docs/ja/docs/tutorial/encoder.md`=20(#13815)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ja/docs/tutorial/encoder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ja/docs/tutorial/encoder.md b/docs/ja/docs/tutorial/encoder.md index 409ebeec6..309cf8857 100644 --- a/docs/ja/docs/tutorial/encoder.md +++ b/docs/ja/docs/tutorial/encoder.md @@ -8,7 +8,7 @@ ## `jsonable_encoder`の使用 -JSON互換のデータのみを受信するデータベース`fase_db`があるとしましょう。 +JSON互換のデータのみを受信するデータベース`fake_db`があるとしましょう。 例えば、`datetime`オブジェクトはJSONと互換性がないので、このデーターベースには受け取られません。 From 1cf4b8c2de1cb737b1442b102422d910b4168696 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 22 Jun 2025 14:37:15 +0000 Subject: [PATCH 214/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3fd184a1f..00effecf0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* ✏️ Fix typo in `docs/ja/docs/tutorial/encoder.md`. PR [#13815](https://github.com/fastapi/fastapi/pull/13815) by [@ruzia](https://github.com/ruzia). * ✏️ Fix typo in `docs/ja/docs/tutorial/handling-errors.md`. PR [#13814](https://github.com/fastapi/fastapi/pull/13814) by [@ruzia](https://github.com/ruzia). * ✏️ Fix typo in `docs/ja/docs/tutorial/body-fields.md`. PR [#13802](https://github.com/fastapi/fastapi/pull/13802) by [@ruzia](https://github.com/ruzia). * 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis). From 937af92ba7573799613c707046777e3731b3499f Mon Sep 17 00:00:00 2001 From: Valentyn Date: Tue, 24 Jun 2025 14:57:48 -0400 Subject: [PATCH 215/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/security/index.md`=20(#138?= =?UTF-8?q?05)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes after review Co-authored-by: Valentyn Druzhynin --- docs/uk/docs/tutorial/security/index.md | 104 ++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 docs/uk/docs/tutorial/security/index.md diff --git a/docs/uk/docs/tutorial/security/index.md b/docs/uk/docs/tutorial/security/index.md new file mode 100644 index 000000000..c3d94be8d --- /dev/null +++ b/docs/uk/docs/tutorial/security/index.md @@ -0,0 +1,104 @@ +# Безпека + +Існує багато способів реалізувати безпеку, автентифікацію та авторизацію. + +Це зазвичай складна і "непроста" тема. + +У багатьох фреймворках і системах забезпечення безпеки та автентифікації займає величезну частину зусиль і коду (іноді — понад 50% всього написаного коду). + +**FastAPI** надає кілька інструментів, які допоможуть Вам впоратися з **безпекою** легко, швидко, стандартним способом, без необхідності вивчати всі специфікації безпеки. + +Але спочатку — кілька коротких понять. + +## Поспішаєте? + +Якщо Вам не цікаві всі ці терміни й просто потрібно *швидко* додати автентифікацію за логіном і паролем — переходьте до наступних розділів. + +## OAuth2 + +OAuth2 — це специфікація, що описує кілька способів обробки автентифікації та авторизації. + +Це досить об'ємна специфікація, яка охоплює складні випадки використання. + +Вона включає способи автентифікації через "третю сторону". + +Саме це лежить в основі "входу через Google, Facebook, X (Twitter), GitHub" тощо. + +### OAuth 1 + +Раніше існував OAuth 1, який значно відрізняється від OAuth2 і є складнішим, оскільки містив специфікації для шифрування комунікацій. + +Зараз майже не використовується. + +OAuth2 не вказує, як саме шифрувати з'єднання — воно очікує, що ваш застосунок працює через HTTPS. + +/// tip | Порада + +У розділі про **деплой** Ви побачите, як налаштувати HTTPS безкоштовно з Traefik та Let's Encrypt. + +/// + +## OpenID Connect + +OpenID Connect — ще одна специфікація, побудована на основі **OAuth2**. + +Вона розширює OAuth2, уточнюючи деякі неоднозначності для досягнення кращої сумісності. + +Наприклад, вхід через Google використовує OpenID Connect (який базується на OAuth2). + +Але вхід через Facebook — ні. Він має власну реалізацію на базі OAuth2. + +### OpenID (не "OpenID Connect") + +Існувала також специфікація "OpenID", яка намагалася розвʼязати ті самі задачі, що й **OpenID Connect**, але не базувалась на OAuth2. + +Це була зовсім інша система, і сьогодні вона майже не використовується. + +## OpenAPI + +OpenAPI (раніше Swagger) — це специфікація для побудови API (тепер під егідою Linux Foundation). + +**FastAPI** базується на **OpenAPI**. + +Завдяки цьому Ви отримуєте автоматичну інтерактивну документацію, генерацію коду та багато іншого. + +OpenAPI дозволяє описувати різні "схеми" безпеки. + +Використовуючи їх, Ви можете скористатися всіма цими інструментами, що базуються на стандартах, зокрема інтерактивними системами документації. + +OpenAPI визначає такі схеми безпеки: + +* `apiKey`: специфічний для застосунку ключ, який може передаватися через: + * Параметр запиту. + * Заголовок. + * Cookie. +* `http`: стандартні методи HTTP-автентифікації, включаючи: + * `bearer`: заголовок `Authorization` зі значенням `Bearer` та токеном. Це успадковано з OAuth2. + * HTTP Basic автентифікація + * HTTP Digest, тощо. +* `oauth2`: усі способи обробки безпеки за допомогою OAuth2 (так звані «потоки»). + * Деякі з цих потоків підходять для створення власного провайдера автентифікації OAuth 2.0 (наприклад, Google, Facebook, X (Twitter), GitHub тощо): + * `implicit`— неявний + * `clientCredentials`— облікові дані клієнта + * `authorizationCode` — код авторизації + * Але є один окремий «потік», який ідеально підходить для реалізації автентифікації всередині одного додатку: + * `password`: у наступних розділах буде приклад використання цього потоку. +* `openIdConnect`: дозволяє автоматично виявляти параметри автентифікації OAuth2. + * Це автоматичне виявлення визначається у специфікації OpenID Connect. + + +/// tip | Порада + +Інтеграція інших провайдерів автентифікації/авторизації, таких як Google, Facebook, X (Twitter), GitHub тощо — також можлива і відносно проста. + +Найскладніше — це створити власного провайдера автентифікації/авторизації, як Google чи Facebook. Але **FastAPI** надає Вам інструменти, щоб зробити це легко, беручи на себе важку частину роботи. + +/// + +## Інструменти **FastAPI** + +FastAPI надає кілька інструментів для кожної з описаних схем безпеки в модулі `fastapi.security`, які спрощують використання цих механізмів захисту. + +У наступних розділах Ви побачите, як додати безпеку до свого API за допомогою цих інструментів **FastAPI**. + +А також побачите, як вона автоматично інтегрується в інтерактивну документацію вашого API. From 666890ac7f3211d15e70503002f284fd18107125 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 24 Jun 2025 18:58:10 +0000 Subject: [PATCH 216/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 00effecf0..52e197cb9 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/security/index.md`. PR [#13805](https://github.com/fastapi/fastapi/pull/13805) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✏️ Fix typo in `docs/ja/docs/tutorial/encoder.md`. PR [#13815](https://github.com/fastapi/fastapi/pull/13815) by [@ruzia](https://github.com/ruzia). * ✏️ Fix typo in `docs/ja/docs/tutorial/handling-errors.md`. PR [#13814](https://github.com/fastapi/fastapi/pull/13814) by [@ruzia](https://github.com/ruzia). * ✏️ Fix typo in `docs/ja/docs/tutorial/body-fields.md`. PR [#13802](https://github.com/fastapi/fastapi/pull/13802) by [@ruzia](https://github.com/ruzia). From c30821ff6ed3d0506ee11a4f4f28cd25c13e7ec8 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Tue, 24 Jun 2025 15:14:01 -0400 Subject: [PATCH 217/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/response-model.md`=20(#137?= =?UTF-8?q?92)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Ukrainian translation for docs/uk/docs/tutorial/response-model.md * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks * Fix review comments --------- Co-authored-by: Valentyn Druzhynin Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/uk/docs/tutorial/response-model.md | 358 ++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 docs/uk/docs/tutorial/response-model.md diff --git a/docs/uk/docs/tutorial/response-model.md b/docs/uk/docs/tutorial/response-model.md new file mode 100644 index 000000000..def1f8a2d --- /dev/null +++ b/docs/uk/docs/tutorial/response-model.md @@ -0,0 +1,358 @@ +# Модель відповіді — Тип, що повертається + +Ви можете оголосити тип, який використовуватиметься у відповіді, за допомогою *анотації типу, що повертається* *функцією операцією шляху* (path operation) + +**Анотацію типу** можна вказати так само як і для вхідних **параметрів** функції: це можуть бути моделі Pydantic, списки (lists), словники (dictionaries), скалярні значення, як-от цілі числа (integers), булеві значення (booleans) тощо. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI використовуватиме цей тип, щоб: + +* **Перевірити правильність** повернених даних. + * Якщо дані не валідні (наприклад, відсутнє поле), це означає, що Ваш код додатку працює некоректно і не повертає те, що повинен. У такому випадку FastAPI поверне помилку сервера, замість того щоб віддати недопустимі дані. Так Ви та Ваші клієнти будете впевнені, що отримуєте очікувані дані у правильному форматі. + +* Додати **JSON Schema** відповіді до специфікації OpenAPI в *операціях шляху*. + * Це буде використано в **автоматичній документації**. + * А також інструментами, які автоматично генерують клієнтський код. + +Але найголовніше: + +* FastAPI **обмежить та відфільтрує** вихідні дані відповідно до типу, вказаного у відповіді. + * Це особливо важливо для **безпеки**. Деталі нижче. + +## Параметр `response_model` + +Іноді Вам потрібно або зручно повертати інші типи даних, ніж ті, що зазначені як тип відповіді. + +Наприклад, Ви можете **повертати словник** або об’єкт бази даних, але **оголосити модель Pydantic** як модель відповіді. Тоді модель Pydantic автоматично оброблятиме валідацію, документацію тощо. + +Якщо Ви додасте анотацію типу для повернення, редактор коду або mypy можуть поскаржитися, що функція повертає інший тип (наприклад, dict замість Item). + +У таких випадках можна скористатися параметром `response_model` в декораторі маршруту (наприклад, @app.get()). + +Параметр `response_model` працює з будь-яким *оператором шляху*: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* тощо. + +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} + +/// note | Примітка + +Зверніть увагу, що `response_model` є параметром методу-декоратора (`get`, `post`, тощо), а не *функцією операцією шляху* (path operation function), як це робиться з параметрами або тілом запиту. + +/// + +`response_model` приймає такий самий тип, який Ви б вказали для поля моделі Pydantic. Тобто це може бути як Pydantic-модель, так і, наприклад, `list` із моделей Pydantic — `List[Item]`. + +FastAPI використовуватиме `response_model` для створення документації, валідації даних та — найважливіше — **перетворення та фільтрації вихідних даних** згідно з оголошеним типом. + +/// tip | Порада + +Якщо у Вас увімкнено сувору перевірку типів у редакторі, mypy тощо, Ви можете оголосити тип повернення функції як `Any`. + +Таким чином, Ви повідомляєте редактору, що свідомо повертаєте будь-що. Але FastAPI усе одно виконуватиме створення документації, валідацію, фільтрацію тощо за допомогою параметра `response_model`. + +/// + +### Пріоритет `response_model` + +Якщо Ви вказуєте і тип повернення, і `response_model`, то FastAPI використовуватиме `response_model` з пріоритетом. + +Таким чином, Ви можете додати правильні анотації типів до ваших функцій, навіть якщо вони повертають тип, відмінний від `response_model`. Це буде корисно для редакторів коду та інструментів, таких як mypy. І при цьому FastAPI продовжить виконувати валідацію даних, генерувати документацію тощо на основі `response_model`. + +Ви також можете використати `response_model=None`, щоб вимкнути створення моделі відповіді для цієї *операції шляху*. Це може знадобитися, якщо Ви додаєте анотації типів до об'єктів, які не є допустимими полями Pydantic — приклад цього Ви побачите в одному з наступних розділів. + +## Повернути ті самі вхідні дані + +Тут ми оголошуємо модель `UserIn`, яка містить звичайний текстовий пароль: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} + +/// info | Інформація + +Щоб використовувати `EmailStr`, спочатку встановіть `email-validator`. + +Переконайтесь, що Ви створили [віртуальне середовище](../virtual-environments.md){.internal-link target=_blank}, активували його, а потім встановили пакет, наприклад: + +```console +$ pip install email-validator +``` + +or with: + +```console +$ pip install "pydantic[email]" +``` + +/// + +І ми використовуємо цю модель, щоб оголосити і вхідні, і вихідні дані: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +Тепер, коли браузер створює користувача з паролем, API поверне той самий пароль у відповіді. + +У цьому випадку це може не бути проблемою, адже саме користувач надіслав пароль. + +Але якщо ми використаємо цю ж модель для іншої операції шляху, ми можемо випадково надіслати паролі наших користувачів кожному клієнту. + +/// danger | Обережно + +Ніколи не зберігайте пароль користувача у відкритому вигляді та не надсилайте його у відповіді, якщо тільки Ви не знаєте всі ризики і точно розумієте, що робите. + +/// + +## Додайте окрему вихідну модель + +Замість цього ми можемо створити вхідну модель з відкритим паролем і вихідну модель без нього: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +Тут, навіть якщо *функція операції шляху* повертає об'єкт користувача, який містить пароль: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +...ми оголосили `response_model` як нашу модель `UserOut`, яка не містить пароля: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +Таким чином, **FastAPI** автоматично відфільтрує всі дані, які не вказані у вихідній моделі (за допомогою Pydantic). + +### `response_model` або тип повернення + +У цьому випадку, оскільки дві моделі різні, якщо ми анотуємо тип повернення функції як `UserOut`, редактор і такі інструменти, як mypy, видадуть помилку, бо фактично ми повертаємо інший тип. + +Тому в цьому прикладі ми використовуємо параметр `response_model`, а не анотацію типу повернення. + +...але читайте далі, щоб дізнатися, як обійти це обмеження. + +## Тип повернення і фільтрація даних + +Продовжимо з попереднього прикладу. Ми хотіли **анотувати функцію одним типом**, але при цьому повертати з неї більше даних. + +Ми хочемо, щоб FastAPI продовжував **фільтрувати** ці дані за допомогою response_model. Тобто навіть якщо функція повертає більше інформації, у відповіді будуть лише ті поля, які вказані у response_model. + +У попередньому прикладі, оскільки класи були різні, нам довелося використовувати параметр `response_model`. Але це означає, що ми не отримуємо підтримки з боку редактора коду та інструментів перевірки типів щодо типу, який повертає функція. + +Проте в більшості випадків, коли нам потрібно зробити щось подібне, ми просто хочемо, щоб модель **відфільтрувала або прибрала** частину даних, як у цьому прикладі. + +У таких випадках ми можемо використати класи та спадкування, щоб скористатися **анотаціями типів** функцій — це дає кращу підтримку з боку редактора та інструментів типу mypy, і при цьому FastAPI продовжує виконувати **фільтрацію даних** у відповіді. + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} + +Завдяки цьому ми отримуємо підтримку інструментів — від редакторів і mypy, оскільки цей код є коректним з точки зору типів, — але ми також отримуємо фільтрацію даних від FastAPI. + +Як це працює? Давайте розберемося. 🤓 + +### Типи та підтримка інструментів + +Спершу подивимось, як це бачать редактори, mypy та інші інструменти. + +`BaseUser` має базові поля. Потім `UserIn` успадковує `BaseUser` і додає поле `password`, отже, він матиме всі поля з обох моделей. + +Ми зазначаємо тип повернення функції як `BaseUser`, але фактично повертаємо екземпляр `UserIn`. + +Редактор, mypy та інші інструменти не скаржитимуться на це, тому що з точки зору типізації `UserIn` є підкласом `BaseUser`, а це означає, що він є `валідним` типом, коли очікується будь-що, що є `BaseUser`. + +### Фільтрація даних у FastAPI + +Тепер для FastAPI він бачить тип повернення і переконується, що те, що Ви повертаєте, містить **тільки** поля, які оголошені у цьому типі. + +FastAPI виконує кілька внутрішніх операцій з Pydantic, щоб гарантувати, що правила наслідування класів не застосовуються для фільтрації повернених даних, інакше Ви могли б повернути значно більше даних, ніж очікували. + +Таким чином, Ви отримуєте найкраще з двох світів: анотації типів **з підтримкою інструментів** і **фільтрацію даних**. + +## Подивитись у документації + +Коли Ви дивитесь автоматичну документацію, Ви можете побачити, що вхідна модель і вихідна модель мають власну JSON-схему: + + + +І обидві моделі використовуються для інтерактивної API-документації: + + + +## Інші анотації типів повернення + +Існують випадки, коли Ви повертаєте щось, що не є допустимим полем Pydantic, але анотуєте це у функції лише для того, щоб отримати підтримку від інструментів (редактора, mypy тощо). + +### Повернення Response напряму + +Найпоширенішим випадком буде [повернення Response напряму, як пояснюється пізніше у розширеній документації](../advanced/response-directly.md){.internal-link target=_blank}. + +{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *} + +Цей простий випадок автоматично обробляється FastAPI, тому що анотація типу повернення — це клас (або підклас) `Response`. + +І інструменти також будуть задоволені, бо і `RedirectResponse`, і `JSONResponse` є підкласами `Response`, отже анотація типу коректна. + +### Анотація підкласу Response + +Також можна використовувати підклас `Response` у анотації типу: + +{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *} + +Це теж працюватиме, бо `RedirectResponse` — підклас `Response`, і FastAPI автоматично обробить цей простий випадок. + +### Некоректні анотації типу повернення + +Але коли Ви повертаєте якийсь інший довільний об’єкт, що не є валідним типом Pydantic (наприклад, об’єкт бази даних), і анотуєте його так у функції, FastAPI спробує створити Pydantic модель відповіді на основі цієї анотації типу, і це завершиться помилкою. + +Те саме станеться, якщо Ви використовуєте union між різними типами, де один або більше не є валідними типами Pydantic, наприклад, це спричинить помилку 💥: + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +...це не працює, тому що тип анотації не є типом Pydantic і не є просто класом `Response` або його підкласом, а є об’єднанням (union) — або `Response`, або `dict`. + +### Відключення Моделі Відповіді + +Продовжуючи приклад вище, можливо, Ви не хочете використовувати стандартну валідацію даних, автоматичну документацію, фільтрацію тощо, які FastAPI виконує за замовчуванням. + +Але ви все одно можете залишити анотацію типу у функції, щоб зберегти підтримку з боку інструментів, таких як редактори коду або статичні перевірки типів (наприклад, mypy). + +У такому випадку ви можете вимкнути генерацію моделі відповіді, встановивши `response_model=None`: + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +Це змусить FastAPI пропустити генерацію моделі відповіді, і таким чином Ви зможете використовувати будь-які анотації типів повернення без впливу на вашу FastAPI аплікацію. 🤓 + +## Параметри кодування моделі відповіді + +Ваша модель відповіді може мати значення за замовчуванням, наприклад: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None` (або `str | None = None` у Python 3.10) має значення за замовчуванням `None`. +* `tax: float = 10.5` має значення за замовчуванням `10.5`. +* `tags: List[str] = []` має значення за замовчуванням порожній список: `[]`. + +Але Ви можете захотіти не включати їх у результат, якщо вони фактично не були збережені. + +Наприклад, якщо у Вас є моделі з багатьма необов’язковими атрибутами у NoSQL базі даних, але Ви не хочете відправляти дуже довгі JSON-відповіді, повні значень за замовчуванням. + +### Використовуйте параметр `response_model_exclude_unset` + +Ви можете встановити параметр декоратора шляху `response_model_exclude_unset=True`: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} + +і ці значення за замовчуванням не будуть включені у відповідь, тільки фактично встановлені значення. + +Отже, якщо Ви надішлете запит до цього оператора шляху для елемента з item_id `foo`, відповідь (без включення значень за замовчуванням) буде: + +```JSON +{ + "name": "Foo", + "price": 50.2 +} +``` + +/// info | Інформація + +У Pydantic версії 1 метод називався `.dict()`, він був застарілий (але ще підтримується) у Pydantic версії 2 і перейменований у `.model_dump()`. + +Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо Ви можете використовувати Pydantic v2. + +/// + +/// info | Інформація + +FastAPI використовує `.dict()` моделі Pydantic з параметром `exclude_unset`, щоб досягти цього. + +/// + +/// info | Інформація + +Ви також можете використовувати: + +* `response_model_exclude_defaults=True` +* `response_model_exclude_none=True` + +як описано в документації Pydantic for `exclude_defaults` та `exclude_none`. + +/// + +#### Дані зі значеннями для полів із типовими значеннями + +Але якщо Ваші дані мають значення для полів моделі з типовими значеннями, як у елемента з item_id `bar`: + +```Python hl_lines="3 5" +{ + "name": "Bar", + "description": "The bartenders", + "price": 62, + "tax": 20.2 +} +``` +вони будуть включені у відповідь. + +#### Дані з тими самими значеннями, що й типові + +Якщо дані мають ті самі значення, що й типові, як у елемента з item_id `baz`: + +```Python hl_lines="3 5-6" +{ + "name": "Baz", + "description": None, + "price": 50.2, + "tax": 10.5, + "tags": [] +} +``` + +FastAPI достатньо розумний (насправді, Pydantic достатньо розумний), щоб зрозуміти, що, хоча `description`, `tax` і `tags` мають ті самі значення, що й типові, вони були встановлені явно (а не взяті як значення за замовчуванням). + +Отже, вони будуть включені у JSON-відповідь. + +/// tip | Порада + +Зверніть увагу, що типові значення можуть бути будь-якими, не лише `None`. + +Це може бути list (`[]`), `float` 10.5 тощо. + +/// + +### `response_model_include` та `response_model_exclude` + +Ви також можете використовувати параметри *декоратора операції шляху* `response_model_include` та `response_model_exclude`. + +Вони приймають `set` (множину) рядків (`str`) з іменами атрибутів, які потрібно включити (пропускаючи інші) або виключити (включаючи інші). + +Це можна використовувати як швидкий спосіб, якщо у Вас є лише одна модель Pydantic і Ви хочете видалити деякі дані з виводу. + +/// tip | Порада + +Але все ж рекомендується використовувати описані вище підходи, із застосуванням кількох класів, замість цих параметрів. + + +Це тому, що JSON Schema, який генерується у вашому OpenAPI додатку (і в документації), все одно буде відповідати повній моделі, навіть якщо Ви використовуєте `response_model_include` або `response_model_exclude` для виключення деяких атрибутів. + +Це також стосується `response_model_by_alias`, який працює подібним чином. + +/// + +{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} + +/// tip | Порада + +Синтаксис `{"name", "description"}` створює `set` з цими двома значеннями. + +Він еквівалентний `set(["name", "description"])`. + +/// + +#### Використання `list` замість `set` + +Якщо Ви забудете використати `set` і натомість застосуєте `list` або `tuple`, FastAPI все одно перетворить це на `set`, і все працюватиме правильно: + +{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} + +## Підсумок + +Використовуйте параметр `response_model` *декоратора операції шляху*, щоб визначати моделі відповіді, особливо щоб гарантувати фільтрацію приватних даних. + +Використовуйте `response_model_exclude_unset`, щоб повертати лише явно встановлені значення. From 3b09dd8e01ecdbdc56829cc7b0f524a882eebdd8 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 24 Jun 2025 19:14:26 +0000 Subject: [PATCH 218/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 52e197cb9..ebf4cfbda 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/response-model.md`. PR [#13792](https://github.com/fastapi/fastapi/pull/13792) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/security/index.md`. PR [#13805](https://github.com/fastapi/fastapi/pull/13805) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). * ✏️ Fix typo in `docs/ja/docs/tutorial/encoder.md`. PR [#13815](https://github.com/fastapi/fastapi/pull/13815) by [@ruzia](https://github.com/ruzia). * ✏️ Fix typo in `docs/ja/docs/tutorial/handling-errors.md`. PR [#13814](https://github.com/fastapi/fastapi/pull/13814) by [@ruzia](https://github.com/ruzia). From 8f64d09ee01daf4773a77e9690e511d928da9b98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:12:53 +0200 Subject: [PATCH 219/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13823)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.13 → v0.12.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.13...v0.12.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7af88b5aa..946d24f35 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.13 + rev: v0.12.0 hooks: - id: ruff args: From df35896a0ebb379d68b7c9bd9fdadd476ef6ac83 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 25 Jun 2025 09:13:15 +0000 Subject: [PATCH 220/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ebf4cfbda..3de9d99ce 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -21,6 +21,10 @@ hide: * ✏️ Fix typo in `docs/ja/docs/tutorial/body-fields.md`. PR [#13802](https://github.com/fastapi/fastapi/pull/13802) by [@ruzia](https://github.com/ruzia). * 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis). +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13823](https://github.com/fastapi/fastapi/pull/13823) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + ## 0.115.13 ### Fixes From 9d0d8828cc6b3f0217581d7e607ba8e4d7e0017b Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Thu, 26 Jun 2025 16:22:53 +0100 Subject: [PATCH 221/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20support=20for=20un?= =?UTF-8?q?ions=20when=20using=20`Form`=20(#13827)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 27 +++++- tests/test_union_forms.py | 156 ++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 tests/test_union_forms.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 84dfa4d03..081b63a8b 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -816,6 +816,25 @@ def request_params_to_args( return values, errors +def is_union_of_base_models(field_type: Any) -> bool: + """Check if field type is a Union where all members are BaseModel subclasses.""" + from fastapi.types import UnionType + + origin = get_origin(field_type) + + # Check if it's a Union type (covers both typing.Union and types.UnionType in Python 3.10+) + if origin is not Union and origin is not UnionType: + return False + + union_args = get_args(field_type) + + for arg in union_args: + if not lenient_issubclass(arg, BaseModel): + return False + + return True + + def _should_embed_body_fields(fields: List[ModelField]) -> bool: if not fields: return False @@ -829,10 +848,12 @@ def _should_embed_body_fields(fields: List[ModelField]) -> bool: # If it explicitly specifies it is embedded, it has to be embedded if getattr(first_field.field_info, "embed", None): return True - # If it's a Form (or File) field, it has to be a BaseModel to be top level + # If it's a Form (or File) field, it has to be a BaseModel (or a union of BaseModels) to be top level # otherwise it has to be embedded, so that the key value pair can be extracted - if isinstance(first_field.field_info, params.Form) and not lenient_issubclass( - first_field.type_, BaseModel + if ( + isinstance(first_field.field_info, params.Form) + and not lenient_issubclass(first_field.type_, BaseModel) + and not is_union_of_base_models(first_field.type_) ): return True return False diff --git a/tests/test_union_forms.py b/tests/test_union_forms.py new file mode 100644 index 000000000..cbe98ea82 --- /dev/null +++ b/tests/test_union_forms.py @@ -0,0 +1,156 @@ +from typing import Union + +from fastapi import FastAPI, Form +from fastapi.testclient import TestClient +from pydantic import BaseModel +from typing_extensions import Annotated + +app = FastAPI() + + +class UserForm(BaseModel): + name: str + email: str + + +class CompanyForm(BaseModel): + company_name: str + industry: str + + +@app.post("/form-union/") +def post_union_form(data: Annotated[Union[UserForm, CompanyForm], Form()]): + return {"received": data} + + +client = TestClient(app) + + +def test_post_user_form(): + response = client.post( + "/form-union/", data={"name": "John Doe", "email": "john@example.com"} + ) + assert response.status_code == 200, response.text + assert response.json() == { + "received": {"name": "John Doe", "email": "john@example.com"} + } + + +def test_post_company_form(): + response = client.post( + "/form-union/", data={"company_name": "Tech Corp", "industry": "Technology"} + ) + assert response.status_code == 200, response.text + assert response.json() == { + "received": {"company_name": "Tech Corp", "industry": "Technology"} + } + + +def test_invalid_form_data(): + response = client.post( + "/form-union/", + data={"name": "John", "company_name": "Tech Corp"}, + ) + assert response.status_code == 422, response.text + + +def test_empty_form(): + response = client.post("/form-union/") + assert response.status_code == 422, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/form-union/": { + "post": { + "summary": "Post Union Form", + "operationId": "post_union_form_form_union__post", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "anyOf": [ + {"$ref": "#/components/schemas/UserForm"}, + {"$ref": "#/components/schemas/CompanyForm"}, + ], + "title": "Data", + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "CompanyForm": { + "properties": { + "company_name": {"type": "string", "title": "Company Name"}, + "industry": {"type": "string", "title": "Industry"}, + }, + "type": "object", + "required": ["company_name", "industry"], + "title": "CompanyForm", + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": {"$ref": "#/components/schemas/ValidationError"}, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "UserForm": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "email": {"type": "string", "title": "Email"}, + }, + "type": "object", + "required": ["name", "email"], + "title": "UserForm", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } From 3ecb4c53895c0a8bf3462983d48379abc54fcaec Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 26 Jun 2025 15:23:20 +0000 Subject: [PATCH 222/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3de9d99ce..963559e12 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Fix support for unions when using `Form`. PR [#13827](https://github.com/fastapi/fastapi/pull/13827) by [@patrick91](https://github.com/patrick91). + ### Docs * Misprint. PR [#13800](https://github.com/fastapi/fastapi/pull/13800) by [@NavesSapnis](https://github.com/NavesSapnis). From 8fa19a6faa3309a150f6e6fafd2c3a5043c09718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 26 Jun 2025 17:24:56 +0200 Subject: [PATCH 223/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 963559e12..fdfe3a49b 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,7 +13,7 @@ hide: ### Docs -* Misprint. PR [#13800](https://github.com/fastapi/fastapi/pull/13800) by [@NavesSapnis](https://github.com/NavesSapnis). +* ✏️ Fix grammar mistake in `docs/en/docs/advanced/response-directly.md`. PR [#13800](https://github.com/fastapi/fastapi/pull/13800) by [@NavesSapnis](https://github.com/NavesSapnis). * 📝 Update Speakeasy URL to Speakeasy Sandbox. PR [#13697](https://github.com/fastapi/fastapi/pull/13697) by [@ndimares](https://github.com/ndimares). ### Translations From ebdeda2de6e17036e3048940b7a9e725ef6a95b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 26 Jun 2025 17:26:32 +0200 Subject: [PATCH 224/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?5.14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fdfe3a49b..77f460fde 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.115.14 + ### Fixes * 🐛 Fix support for unions when using `Form`. PR [#13827](https://github.com/fastapi/fastapi/pull/13827) by [@patrick91](https://github.com/patrick91). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 1768d0204..e672ec9e5 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.115.13" +__version__ = "0.115.14" from starlette import status as status From 6c1432801f34a3b0e1551f69cdd90ab7953f05e0 Mon Sep 17 00:00:00 2001 From: Valentyn Date: Mon, 30 Jun 2025 02:00:04 -0400 Subject: [PATCH 225/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Ukrainian=20transl?= =?UTF-8?q?ation=20for=20`docs/uk/docs/tutorial/body-updates.md`=20(#13804?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Ukrainian translation for docs/uk/docs/tutorial/body-updates.md * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Co-authored-by: Valentyn Druzhynin Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/uk/docs/tutorial/body-updates.md | 116 ++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 docs/uk/docs/tutorial/body-updates.md diff --git a/docs/uk/docs/tutorial/body-updates.md b/docs/uk/docs/tutorial/body-updates.md new file mode 100644 index 000000000..e78b5a5bf --- /dev/null +++ b/docs/uk/docs/tutorial/body-updates.md @@ -0,0 +1,116 @@ +# Тіло – Оновлення + +## Оновлення з використанням `PUT` + +Щоб оновити елемент, Ви можете використати HTTP `PUT` операцію. + +Ви можете використати `jsonable_encoder`, щоб перетворити вхідні дані на такі, які можна зберігати як JSON (наприклад, у NoSQL базі даних). Наприклад, перетворюючи `datetime` у `str`. + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +`PUT` використовується для отримання даних, які мають замінити чинні дані. + +### Попередження про заміну + +Це означає, що якщо Ви хочете оновити елемент `bar`, використовуючи `PUT` з тілом: + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +оскільки він не містить вже збереженого атрибута `"tax": 20.2`, модель введення прийме значення за замовчуванням `"tax": 10.5`. + +І дані будуть збережені з цим "новим" значенням `tax` = `10.5`. + +## Часткові оновлення з `PATCH` + +Ви також можете використовувати операцію HTTP `PATCH` для *часткового* оновлення даних. + +Це означає, що Ви можете надіслати лише ті дані, які хочете оновити, залишаючи інші без змін. + +/// note | Примітка + +`PATCH` менш відомий і рідше використовується, ніж `PUT`. + +І багато команд використовують лише `PUT`, навіть для часткових оновлень. + +Ви **вільні** використовувати їх так, як хочете, **FastAPI** не накладає обмежень. + +Але цей посібник показує Вам більш-менш як їх задумано використовувати. + +/// + +### Використання параметра `exclude_unset` у Pydantic + +Якщо Ви хочете отримати часткові оновлення, дуже зручно використовувати параметр `exclude_unset` у методі `.model_dump()` моделі Pydantic. + +Наприклад: `item.model_dump(exclude_unset=True)`. + +/// info | Інформація + +У Pydantic v1 цей метод називався `.dict()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_dump()`. + +Приклади тут використовують `.dict()` для сумісності з Pydantic v1, але Вам слід використовувати `.model_dump()`, якщо можете використовувати Pydantic v2. + +/// + +Це створить `dict` лише з тими даними, які були явно встановлені під час створення моделі `item`, виключаючи значення за замовчуванням. + +Тоді Ви можете використовувати це, щоб створити `dict` лише з даними, які були встановлені (надіслані у запиті), пропускаючи значення за замовчуванням: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### Використання параметра `update` у Pydantic + +Тепер Ви можете створити копію наявної моделі за допомогою `.model_copy()`, і передати параметр `update` з `dict` , який містить дані для оновлення. + +/// info | Інформація + +У Pydantic v1 метод називався `.copy()`, він був застарілий (але все ще підтримується) у Pydantic v2, і був перейменований у `.model_copy()`. + +Приклади тут використовують `.copy()` для сумісності з Pydantic v1, але якщо Ви можете використовувати Pydantic v2 — Вам слід використовувати `.model_copy()` замість цього. + +/// + +Наприклад: `stored_item_model.model_copy(update=update_data)`: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### Підсумок часткових оновлень + +У підсумку, щоб застосувати часткові оновлення, Ви: + +* (Опціонально) використовуєте `PATCH` замість `PUT`. +* Отримуєте збережені дані. +* Поміщаєте ці дані в модель Pydantic. +* Генеруєте `dict` без значень за замовчуванням з моделі введення (використовуючи `exclude_unset`). + * Таким чином Ви оновите лише ті значення, які були явно задані користувачем, замість того, щоб перезаписувати вже збережені значення значеннями за замовчуванням з вашої моделі. +* Створюєте копію збереженої моделі, оновлюючи її атрибути отриманими частковими оновленнями (використовуючи параметр `update`). +* Перетворюєте скопійовану модель на щось, що можна зберегти у вашу БД (наприклад, використовуючи `jsonable_encoder`). + * Це можна порівняти з повторним використанням методу `.model_dump()` моделі, але це гарантує (і перетворює) значення у типи даних, які можна перетворити на JSON, наприклад, `datetime` на `str`. +* Зберігаєте дані у вашу БД. +* Повертаєте оновлену модель. + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | Порада + +Насправді Ви можете використовувати цю саму техніку і з операцією HTTP `PUT`. + +Але приклад тут використовує `PATCH`, тому що він був створений саме для таких випадків. + +/// + +/// note | Примітка + +Зверніть увагу, що модель запиту все ще проходить валідацію. + +Тож, якщо Ви хочете отримувати часткові оновлення, які можуть не містити жодного атрибута, Вам потрібно мати модель, де всі атрибути позначені як необов’язкові (зі значеннями за замовчуванням або `None`). + +Щоб розрізняти моделі з усіма необов’язковими значеннями для **оновлення** і моделі з обов’язковими значеннями для **створення**, Ви можете скористатись ідеями, описаними у [Додаткові моделі](extra-models.md){.internal-link target=_blank}. + +/// From 5e7c3ee1f3b24e7757ee25328f75cb47e92436d7 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 30 Jun 2025 06:00:29 +0000 Subject: [PATCH 226/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 77f460fde..75f7288f3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-updates.md`. PR [#13804](https://github.com/fastapi/fastapi/pull/13804) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + ## 0.115.14 ### Fixes From c6037fc96fa11d411fd57499f8a42306edee5325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 1 Jul 2025 07:14:26 +0200 Subject: [PATCH 227/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#13845)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/contributors.yml | 23 ++++- docs/en/data/translation_reviewers.yml | 119 ++++++++++++++++--------- docs/en/data/translators.yml | 32 ++++--- 3 files changed, 117 insertions(+), 57 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index f3f7c9133..e06510ac4 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,11 +1,11 @@ tiangolo: login: tiangolo - count: 747 + count: 753 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 102 + count: 104 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: @@ -15,7 +15,7 @@ alejsdev: url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci - count: 30 + count: 33 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci github-actions: @@ -116,7 +116,7 @@ hitrust: ShahriyarR: login: ShahriyarR count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=c9a1691e5ebdc94cbf543086099a6ed705cdb873&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=631b2ae59360ab380c524b32bc3d245aff1165af&v=4 url: https://github.com/ShahriyarR adriangb: login: adriangb @@ -513,6 +513,11 @@ tamird: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1535036?v=4 url: https://github.com/tamird +ndimares: + login: ndimares + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6267663?u=cfb27efde7a7212be8142abb6c058a1aeadb41b1&v=4 + url: https://github.com/ndimares rabinlamadong: login: rabinlamadong count: 2 @@ -538,8 +543,18 @@ DanielYang59: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/80093591?u=63873f701c7c74aac83c906800a1dddc0bc8c92f&v=4 url: https://github.com/DanielYang59 +valentinDruzhinin: + login: valentinDruzhinin + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin blueswen: login: blueswen count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1564148?u=6d6b8cc8f2b5cef715e68d6175154a8a94d518ee&v=4 url: https://github.com/blueswen +YuriiMotov: + login: YuriiMotov + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index aad3e4fac..4f3c95b27 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -10,7 +10,7 @@ Xewus: url: https://github.com/Xewus sodaMelon: login: sodaMelon - count: 125 + count: 126 avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 url: https://github.com/sodaMelon ceb10n: @@ -30,7 +30,7 @@ hasansezertasan: url: https://github.com/hasansezertasan hard-coders: login: hard-coders - count: 92 + count: 93 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders alv2017: @@ -70,7 +70,7 @@ mattwang44: url: https://github.com/mattwang44 tiangolo: login: tiangolo - count: 52 + count: 53 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo Laineyzhang55: @@ -148,6 +148,11 @@ nilslindemann: count: 35 avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 url: https://github.com/nilslindemann +mezgoodle: + login: mezgoodle + count: 35 + avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4 + url: https://github.com/mezgoodle rjNemo: login: rjNemo count: 34 @@ -158,11 +163,6 @@ codingjenny: count: 34 avatarUrl: https://avatars.githubusercontent.com/u/103817302?u=3a042740dc0ff58615da0d8679230966fd7693e8&v=4 url: https://github.com/codingjenny -mezgoodle: - login: mezgoodle - count: 33 - avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4 - url: https://github.com/mezgoodle akarev0: login: akarev0 count: 33 @@ -243,6 +243,11 @@ mycaule: count: 25 avatarUrl: https://avatars.githubusercontent.com/u/6161385?u=e3cec75bd6d938a0d73fae0dc5534d1ab2ed1b0e&v=4 url: https://github.com/mycaule +YuriiMotov: + login: YuriiMotov + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov Aruelius: login: Aruelius count: 24 @@ -268,6 +273,11 @@ axel584: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 url: https://github.com/axel584 +DianaTrufanova: + login: DianaTrufanova + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/119067607?u=1cd55f841b68b4a187fa6d06a7dafa5f070195aa&v=4 + url: https://github.com/DianaTrufanova AGolicyn: login: AGolicyn count: 21 @@ -328,6 +338,11 @@ Limsunoh: count: 18 avatarUrl: https://avatars.githubusercontent.com/u/90311848?u=f456e0c5709fd50c8cd2898b551558eda14e5f21&v=4 url: https://github.com/Limsunoh +SofiiaTrufanova: + login: SofiiaTrufanova + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/63260929?u=483e0b64fabc76343b3be39b7e1dcb930a95e1bb&v=4 + url: https://github.com/SofiiaTrufanova bezaca: login: bezaca count: 17 @@ -373,11 +388,6 @@ JaeHyuckSa: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/104830931?u=6e352201714a05154e5d0ccf91b4715a951c622e&v=4 url: https://github.com/JaeHyuckSa -SofiiaTrufanova: - login: SofiiaTrufanova - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/63260929?u=483e0b64fabc76343b3be39b7e1dcb930a95e1bb&v=4 - url: https://github.com/SofiiaTrufanova Jedore: login: Jedore count: 15 @@ -388,11 +398,6 @@ kim-sangah: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/173775778?v=4 url: https://github.com/kim-sangah -DianaTrufanova: - login: DianaTrufanova - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/119067607?u=1cd55f841b68b4a187fa6d06a7dafa5f070195aa&v=4 - url: https://github.com/DianaTrufanova PandaHun: login: PandaHun count: 14 @@ -533,6 +538,11 @@ Lufa1u: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/112495876?u=087658920ed9e74311597bdd921d8d2de939d276&v=4 url: https://github.com/Lufa1u +waketzheng: + login: waketzheng + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 + url: https://github.com/waketzheng KNChiu: login: KNChiu count: 11 @@ -593,16 +603,21 @@ nick-cjyx9: count: 10 avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=c35aab03f082430be8a1edd80f5625b44819a0d8&v=4 url: https://github.com/nick-cjyx9 -waketzheng: - login: waketzheng - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 - url: https://github.com/waketzheng lucasbalieiro: login: lucasbalieiro count: 10 avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=eabaf4aebbaa88a94a4886273edba689012cee70&v=4 url: https://github.com/lucasbalieiro +maru0123-2004: + login: maru0123-2004 + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 + url: https://github.com/maru0123-2004 +Zhongheng-Cheng: + login: Zhongheng-Cheng + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 + url: https://github.com/Zhongheng-Cheng RunningIkkyu: login: RunningIkkyu count: 9 @@ -646,7 +661,7 @@ riroan: MinLee0210: login: MinLee0210 count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=3c4b6e9d69bff148d09fe022ddf867e564acaa44&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=8ca05a7efbc76048183da00da87d148b755a3ba8&v=4 url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai @@ -663,11 +678,6 @@ JoaoGustavoRogel: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/29525510?u=a0a91251f5e43e132608d55d28ccb8645c5ea405&v=4 url: https://github.com/JoaoGustavoRogel -Zhongheng-Cheng: - login: Zhongheng-Cheng - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 - url: https://github.com/Zhongheng-Cheng Yarous: login: Yarous count: 9 @@ -713,11 +723,6 @@ camigomezdev: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/16061815?u=25b5ebc042fff53fa03dc107ded10e36b1b7a5b9&v=4 url: https://github.com/camigomezdev -maru0123-2004: - login: maru0123-2004 - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 - url: https://github.com/maru0123-2004 minaton-ru: login: minaton-ru count: 8 @@ -748,6 +753,11 @@ anthonycepeda: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4 url: https://github.com/anthonycepeda +Muaytie666: + login: Muaytie666 + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/198508825?v=4 + url: https://github.com/Muaytie666 fabioueno: login: fabioueno count: 7 @@ -773,6 +783,11 @@ d2a-raudenaerde: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 url: https://github.com/d2a-raudenaerde +valentinDruzhinin: + login: valentinDruzhinin + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin Zerohertz: login: Zerohertz count: 7 @@ -781,7 +796,7 @@ Zerohertz: deniscapeto: login: deniscapeto count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/12864353?u=dbc20c5c1171feab5df4db46488b675d53cb5b07&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/12864353?u=20c5b2300b264a585a8381acf3cef44bcfcc1ead&v=4 url: https://github.com/deniscapeto bsab: login: bsab @@ -878,11 +893,11 @@ bankofsardine: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/44944207?u=0368e1b698ffab6bf29e202f9fd2dddd352429f1&v=4 url: https://github.com/bankofsardine -valentinDruzhinin: - login: valentinDruzhinin +Rekl0w: + login: Rekl0w count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin + avatarUrl: https://avatars.githubusercontent.com/u/91488737?u=3b62b04a3e6699eab9b1eea4e88c09a39b753a17&v=4 + url: https://github.com/Rekl0w rsip22: login: rsip22 count: 5 @@ -966,7 +981,7 @@ ChuyuChoyeon: frwl404: login: frwl404 count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/42642656?u=572a5a33762e07eaa6ebd58d9d773abdb1de41c3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/42642656?u=8395a3d991d9fac86901277d76f0f70857b56ec5&v=4 url: https://github.com/frwl404 esrefzeki: login: esrefzeki @@ -1328,6 +1343,11 @@ Sion99: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/82511301?v=4 url: https://github.com/Sion99 +nymous: + login: nymous + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 + url: https://github.com/nymous EpsilonRationes: login: EpsilonRationes count: 3 @@ -1366,7 +1386,7 @@ GDemay: maxscheijen: login: maxscheijen count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/47034840?u=eb98f37882528ea349ca4e5255fa64ac3fef0294&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/47034840?v=4 url: https://github.com/maxscheijen celestywang: login: celestywang @@ -1566,7 +1586,7 @@ raphaelauv: Fahad-Md-Kamal: login: Fahad-Md-Kamal count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=f96c6cbd25b06274e3ff96bc961ca91b3f876481&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=141086368c5557d5a1a533fe291f21f9fc584458&v=4 url: https://github.com/Fahad-Md-Kamal zxcq544: login: zxcq544 @@ -1753,6 +1773,11 @@ kiharito: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/38311245?v=4 url: https://github.com/kiharito +t4f1d: + login: t4f1d + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4054172?u=463d5ce0ec8ad8582f6e9351bb8c9a5105b39bb7&v=4 + url: https://github.com/t4f1d J-Fuji: login: J-Fuji count: 2 @@ -1783,3 +1808,13 @@ Azazul123: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/102759111?u=b48ce6e30a81a23467cc30e0c011bcc57f0326ab&v=4 url: https://github.com/Azazul123 +ykertytsky: + login: ykertytsky + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/83857001?u=1172902656ee604cf37f5e36abe938cd34a97a32&v=4 + url: https://github.com/ykertytsky +NavesSapnis: + login: NavesSapnis + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 51d05003b..3cd6120d0 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -8,16 +8,16 @@ jaystone776: count: 46 avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 url: https://github.com/jaystone776 +valentinDruzhinin: + login: valentinDruzhinin + count: 29 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin ceb10n: login: ceb10n count: 27 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n -valentinDruzhinin: - login: valentinDruzhinin - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin tokusumi: login: tokusumi count: 23 @@ -108,6 +108,11 @@ ptt3199: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=2c3d947a80283e32bf616d4c3af139a6be69680f&v=4 url: https://github.com/ptt3199 +NinaHwang: + login: NinaHwang + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=241f2cb6d38a2d379536608a8ea5a22ed4b1a3ea&v=4 + url: https://github.com/NinaHwang batlopes: login: batlopes count: 6 @@ -138,11 +143,6 @@ Attsun1031: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4 url: https://github.com/Attsun1031 -NinaHwang: - login: NinaHwang - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=241f2cb6d38a2d379536608a8ea5a22ed4b1a3ea&v=4 - url: https://github.com/NinaHwang tiangolo: login: tiangolo count: 5 @@ -296,7 +296,7 @@ pe-brian: maxscheijen: login: maxscheijen count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/47034840?u=eb98f37882528ea349ca4e5255fa64ac3fef0294&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/47034840?v=4 url: https://github.com/maxscheijen ilacftemp: login: ilacftemp @@ -343,6 +343,11 @@ Rishat-F: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 url: https://github.com/Rishat-F +ruzia: + login: ruzia + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/24503?v=4 + url: https://github.com/ruzia izaguerreiro: login: izaguerreiro count: 2 @@ -523,3 +528,8 @@ EgorOnishchuk: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 url: https://github.com/EgorOnishchuk +NavesSapnis: + login: NavesSapnis + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis From a86b9a5b03ff9bd1d6c1cdce9cb54c7f1a78ae4c Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 1 Jul 2025 05:14:52 +0000 Subject: [PATCH 228/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 75f7288f3..7c71fdb2a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-updates.md`. PR [#13804](https://github.com/fastapi/fastapi/pull/13804) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +### Internal + +* 👥 Update FastAPI People - Contributors and Translators. PR [#13845](https://github.com/fastapi/fastapi/pull/13845) by [@tiangolo](https://github.com/tiangolo). + ## 0.115.14 ### Fixes From 21c8a32fa72eaab337c44259307fc20b5225b76d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:18:16 +0200 Subject: [PATCH 229/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13843)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.0 → v0.12.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.0...v0.12.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 946d24f35..673c86127 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.0 + rev: v0.12.1 hooks: - id: ruff args: From 638b4355d89c7cc60002e483936c1d1f841e79af Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 1 Jul 2025 13:18:41 +0000 Subject: [PATCH 230/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7c71fdb2a..3de894190 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13843](https://github.com/fastapi/fastapi/pull/13843) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Contributors and Translators. PR [#13845](https://github.com/fastapi/fastapi/pull/13845) by [@tiangolo](https://github.com/tiangolo). ## 0.115.14 From b0e09640e113d3d5be45f9c573703ffd86d0c9e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:19:03 +0200 Subject: [PATCH 231/455] =?UTF-8?q?=E2=AC=86=20Bump=20mkdocs-material=20fr?= =?UTF-8?q?om=209.6.1=20to=209.6.15=20(#13849)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.1 to 9.6.15. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.1...9.6.15) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.6.15 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 606314926..059203ec1 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,6 +1,6 @@ -e . -r requirements-docs-tests.txt -mkdocs-material==9.6.1 +mkdocs-material==9.6.15 mdx-include >=1.4.1,<2.0.0 mkdocs-redirects>=1.2.1,<1.3.0 typer == 0.16.0 From 943faf237c6c956bf33df1fba2145614195ee1f3 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 1 Jul 2025 13:19:35 +0000 Subject: [PATCH 232/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3de894190..8057c3021 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump mkdocs-material from 9.6.1 to 9.6.15. PR [#13849](https://github.com/fastapi/fastapi/pull/13849) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13843](https://github.com/fastapi/fastapi/pull/13843) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Contributors and Translators. PR [#13845](https://github.com/fastapi/fastapi/pull/13845) by [@tiangolo](https://github.com/tiangolo). From f4bacfe1b5418db6519a47515d95b8079256c514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 1 Jul 2025 15:20:03 +0200 Subject: [PATCH 233/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#13848)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/topic_repos.yml | 426 +++++++++++++++++------------------ 1 file changed, 213 insertions(+), 213 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 1f6ae55bd..ab9f21995 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,495 +1,495 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 33079 + stars: 34156 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 30350 + stars: 30835 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21593 + stars: 21631 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 17229 + stars: 18125 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 16068 + stars: 16249 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: 12689 + stars: 13279 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 11965 + stars: 12334 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 9773 + stars: 9934 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8829 + stars: 8838 owner_login: pydantic owner_html_url: https://github.com/pydantic +- name: XHS-Downloader + html_url: https://github.com/JoeanAmier/XHS-Downloader + stars: 7962 + owner_login: JoeanAmier + owner_html_url: https://github.com/JoeanAmier - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 6779 + stars: 6834 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 6652 + stars: 6783 owner_login: vastsa owner_html_url: https://github.com/vastsa -- name: serge - html_url: https://github.com/serge-chat/serge - stars: 5722 - owner_login: serge-chat - owner_html_url: https://github.com/serge-chat +- name: fastapi_mcp + html_url: https://github.com/tadata-org/fastapi_mcp + stars: 5846 + owner_login: tadata-org + owner_html_url: https://github.com/tadata-org - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 5607 + stars: 5773 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev +- name: serge + html_url: https://github.com/serge-chat/serge + stars: 5728 + owner_login: serge-chat + owner_html_url: https://github.com/serge-chat - name: polar html_url: https://github.com/polarsource/polar - stars: 5327 + stars: 5709 owner_login: polarsource owner_html_url: https://github.com/polarsource - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 5235 + stars: 5336 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users -- name: fastapi_mcp - html_url: https://github.com/tadata-org/fastapi_mcp - stars: 5193 - owner_login: tadata-org - owner_html_url: https://github.com/tadata-org -- name: SurfSense - html_url: https://github.com/MODSetter/SurfSense - stars: 4833 - owner_login: MODSetter - owner_html_url: https://github.com/MODSetter -- name: chatgpt-web-share - html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4307 - owner_login: chatpire - owner_html_url: https://github.com/chatpire - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4281 + stars: 4317 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: 4301 + owner_login: chatpire + owner_html_url: https://github.com/chatpire - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4110 + stars: 4106 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4008 + stars: 4045 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: poem html_url: https://github.com/poem-web/poem - stars: 3977 + stars: 4037 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3317 + stars: 3348 owner_login: rashadphz owner_html_url: https://github.com/rashadphz +- name: LitServe + html_url: https://github.com/Lightning-AI/LitServe + stars: 3347 + 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: 3253 + stars: 3309 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: 3228 + stars: 3291 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: LitServe - html_url: https://github.com/Lightning-AI/LitServe - stars: 3175 - owner_login: Lightning-AI - owner_html_url: https://github.com/Lightning-AI - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3172 + stars: 3288 owner_login: pydantic owner_html_url: https://github.com/pydantic -- name: opyrator - html_url: https://github.com/ml-tooling/opyrator - stars: 3122 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3110 + stars: 3201 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor +- name: opyrator + html_url: https://github.com/ml-tooling/opyrator + stars: 3132 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 3099 + owner_login: remsky + owner_html_url: https://github.com/remsky - name: docarray html_url: https://github.com/docarray/docarray - stars: 3068 + stars: 3075 owner_login: docarray owner_html_url: https://github.com/docarray - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2892 + stars: 2902 owner_login: nsidnev owner_html_url: https://github.com/nsidnev -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 2883 - owner_login: remsky - owner_html_url: https://github.com/remsky -- name: uvicorn-gunicorn-fastapi-docker - html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker - stars: 2770 - owner_login: tiangolo - owner_html_url: https://github.com/tiangolo - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 2740 + stars: 2888 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ +- name: uvicorn-gunicorn-fastapi-docker + html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker + stars: 2775 + owner_login: tiangolo + owner_html_url: https://github.com/tiangolo - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2517 + stars: 2537 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2423 + stars: 2427 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2376 + stars: 2397 owner_login: Buuntu owner_html_url: https://github.com/Buuntu - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2301 + stars: 2334 owner_login: s3rius owner_html_url: https://github.com/s3rius - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2289 + stars: 2295 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2196 + stars: 2235 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2179 + stars: 2181 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2098 + stars: 2119 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2077 + stars: 2100 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 2047 + stars: 2084 owner_login: supabase owner_html_url: https://github.com/supabase - name: solara html_url: https://github.com/widgetti/solara - stars: 2044 + stars: 2056 owner_login: widgetti owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1905 + stars: 1923 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1823 + stars: 1821 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno -- name: manage-fastapi - html_url: https://github.com/ycd/manage-fastapi - stars: 1754 - owner_login: ycd - owner_html_url: https://github.com/ycd - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1746 + stars: 1765 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: 1756 + owner_login: ycd + owner_html_url: https://github.com/ycd - name: ormar html_url: https://github.com/collerek/ormar - stars: 1742 + stars: 1755 owner_login: collerek owner_html_url: https://github.com/collerek - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1630 + stars: 1631 owner_login: jina-ai owner_html_url: https://github.com/jina-ai -- name: termpair - html_url: https://github.com/cs01/termpair - stars: 1611 - owner_login: cs01 - owner_html_url: https://github.com/cs01 - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1609 + stars: 1629 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm -- name: coronavirus-tracker-api - html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1587 - owner_login: ExpDev07 - owner_html_url: https://github.com/ExpDev07 -- name: fastapi-cache - html_url: https://github.com/long2ice/fastapi-cache - stars: 1575 - owner_login: long2ice - owner_html_url: https://github.com/long2ice +- name: termpair + html_url: https://github.com/cs01/termpair + stars: 1616 + owner_login: cs01 + owner_html_url: https://github.com/cs01 - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1568 + stars: 1603 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators -- name: fastapi-crudrouter - html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1508 - owner_login: awtkns - owner_html_url: https://github.com/awtkns +- name: fastapi-cache + html_url: https://github.com/long2ice/fastapi-cache + stars: 1589 + owner_login: long2ice + owner_html_url: https://github.com/long2ice +- name: coronavirus-tracker-api + html_url: https://github.com/ExpDev07/coronavirus-tracker-api + stars: 1580 + owner_login: ExpDev07 + owner_html_url: https://github.com/ExpDev07 - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1501 + stars: 1533 owner_login: laurentS owner_html_url: https://github.com/laurentS +- name: fastapi-crudrouter + html_url: https://github.com/awtkns/fastapi-crudrouter + stars: 1518 + owner_login: awtkns + owner_html_url: https://github.com/awtkns - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1453 + stars: 1461 owner_login: Kludex owner_html_url: https://github.com/Kludex +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 1409 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1390 + stars: 1393 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1353 + stars: 1378 owner_login: uriyyo owner_html_url: https://github.com/uriyyo -- name: budgetml - html_url: https://github.com/ebhy/budgetml - stars: 1342 - owner_login: ebhy - owner_html_url: https://github.com/ebhy - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1325 + stars: 1348 owner_login: teamhide owner_html_url: https://github.com/teamhide -- name: vue-fastapi-admin - html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1306 - owner_login: mizhexiaoxiao - owner_html_url: https://github.com/mizhexiaoxiao +- name: budgetml + html_url: https://github.com/ebhy/budgetml + stars: 1344 + owner_login: ebhy + owner_html_url: https://github.com/ebhy - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1256 + stars: 1284 owner_login: amisadmin owner_html_url: https://github.com/amisadmin +- name: bracket + html_url: https://github.com/evroon/bracket + stars: 1274 + owner_login: evroon + owner_html_url: https://github.com/evroon - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1245 + stars: 1265 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1201 + stars: 1216 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: bracket - html_url: https://github.com/evroon/bracket - stars: 1201 - owner_login: evroon - owner_html_url: https://github.com/evroon - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1179 + stars: 1190 owner_login: slackapi owner_html_url: https://github.com/slackapi -- name: fastapi_production_template - html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1147 - owner_login: zhanymkanov - owner_html_url: https://github.com/zhanymkanov +- name: fastcrud + html_url: https://github.com/benavlabs/fastcrud + stars: 1169 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1145 + stars: 1167 owner_login: trallnag owner_html_url: https://github.com/trallnag +- name: fastapi_production_template + html_url: https://github.com/zhanymkanov/fastapi_production_template + stars: 1165 + owner_login: zhanymkanov + owner_html_url: https://github.com/zhanymkanov - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1143 + stars: 1163 owner_login: aws-samples owner_html_url: https://github.com/aws-samples - name: langchain-extract html_url: https://github.com/langchain-ai/langchain-extract - stars: 1134 + stars: 1142 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: odmantic html_url: https://github.com/art049/odmantic - stars: 1118 + stars: 1121 owner_login: art049 owner_html_url: https://github.com/art049 +- name: fastapi_best_architecture + html_url: https://github.com/fastapi-practices/fastapi_best_architecture + stars: 1118 + owner_login: fastapi-practices + owner_html_url: https://github.com/fastapi-practices - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1110 + stars: 1116 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 -- name: fastcrud - html_url: https://github.com/benavlabs/fastcrud - stars: 1080 +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1070 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: restish html_url: https://github.com/rest-sh/restish - stars: 1056 + stars: 1069 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: fastapi_best_architecture - html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 1050 - owner_login: fastapi-practices - owner_html_url: https://github.com/fastapi-practices - name: runhouse html_url: https://github.com/run-house/runhouse - stars: 1034 + stars: 1037 owner_login: run-house owner_html_url: https://github.com/run-house - name: autollm html_url: https://github.com/viddexa/autollm - stars: 992 + stars: 994 owner_login: viddexa owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 990 + stars: 992 owner_login: ajndkr owner_html_url: https://github.com/ajndkr -- name: FastAPI-boilerplate - html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 985 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs - name: authx html_url: https://github.com/yezz123/authx - stars: 938 + stars: 953 owner_login: yezz123 owner_html_url: https://github.com/yezz123 - name: secure html_url: https://github.com/TypeError/secure - stars: 935 + stars: 941 owner_login: TypeError owner_html_url: https://github.com/TypeError -- name: langcorn - html_url: https://github.com/msoedov/langcorn - stars: 925 - owner_login: msoedov - owner_html_url: https://github.com/msoedov - name: energy-forecasting html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 913 + stars: 928 owner_login: iusztinpaul owner_html_url: https://github.com/iusztinpaul +- name: langcorn + html_url: https://github.com/msoedov/langcorn + stars: 927 + owner_login: msoedov + owner_html_url: https://github.com/msoedov - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 886 + stars: 901 owner_login: developmentseed owner_html_url: https://github.com/developmentseed - name: flock html_url: https://github.com/Onelevenvy/flock - stars: 866 + stars: 896 owner_login: Onelevenvy owner_html_url: https://github.com/Onelevenvy -- name: httpdbg - html_url: https://github.com/cle-b/httpdbg - stars: 863 - owner_login: cle-b - owner_html_url: https://github.com/cle-b -- name: marker-api - html_url: https://github.com/adithya-s-k/marker-api - stars: 859 - owner_login: adithya-s-k - owner_html_url: https://github.com/adithya-s-k -- name: ludic - html_url: https://github.com/getludic/ludic - stars: 845 - owner_login: getludic - owner_html_url: https://github.com/getludic -- name: fastapi-do-zero - html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 827 - owner_login: dunossauro - owner_html_url: https://github.com/dunossauro -- name: fastapi-observability - html_url: https://github.com/blueswen/fastapi-observability - stars: 823 - owner_login: blueswen - owner_html_url: https://github.com/blueswen - name: fastapi-langgraph-agent-production-ready-template html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 803 + stars: 896 owner_login: wassim249 owner_html_url: https://github.com/wassim249 -- name: fastapi-mail - html_url: https://github.com/sabuhish/fastapi-mail - stars: 798 - owner_login: sabuhish - owner_html_url: https://github.com/sabuhish +- name: marker-api + html_url: https://github.com/adithya-s-k/marker-api + stars: 875 + owner_login: adithya-s-k + owner_html_url: https://github.com/adithya-s-k +- name: httpdbg + html_url: https://github.com/cle-b/httpdbg + stars: 870 + owner_login: cle-b + owner_html_url: https://github.com/cle-b +- name: fastapi-do-zero + html_url: https://github.com/dunossauro/fastapi-do-zero + stars: 855 + owner_login: dunossauro + owner_html_url: https://github.com/dunossauro +- name: ludic + html_url: https://github.com/getludic/ludic + stars: 849 + owner_login: getludic + owner_html_url: https://github.com/getludic +- name: fastapi-observability + html_url: https://github.com/blueswen/fastapi-observability + stars: 837 + owner_login: blueswen + owner_html_url: https://github.com/blueswen +- name: fastapi-scaf + html_url: https://github.com/atpuxiner/fastapi-scaf + stars: 821 + owner_login: atpuxiner + owner_html_url: https://github.com/atpuxiner - name: starlette-admin html_url: https://github.com/jowilf/starlette-admin - stars: 785 + stars: 808 owner_login: jowilf owner_html_url: https://github.com/jowilf -- name: lccn_predictor - html_url: https://github.com/baoliay2008/lccn_predictor - stars: 767 - owner_login: baoliay2008 - owner_html_url: https://github.com/baoliay2008 +- name: fastapi-mail + html_url: https://github.com/sabuhish/fastapi-mail + stars: 807 + owner_login: sabuhish + owner_html_url: https://github.com/sabuhish - name: aktools html_url: https://github.com/akfamily/aktools - stars: 759 + stars: 796 owner_login: akfamily owner_html_url: https://github.com/akfamily -- name: KonomiTV - html_url: https://github.com/tsukumijima/KonomiTV - stars: 748 - owner_login: tsukumijima - owner_html_url: https://github.com/tsukumijima +- name: RuoYi-Vue3-FastAPI + html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI + stars: 782 + owner_login: insistence + owner_html_url: https://github.com/insistence From be91d0c1bde305c441d9aeda5c00f21094656de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 1 Jul 2025 15:20:19 +0200 Subject: [PATCH 234/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Sponsors=20(#13846)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 109 +++++++++++++++---------------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index efc5cbfcc..0cb200185 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -1,10 +1,10 @@ sponsors: +- - login: classmethod + avatarUrl: https://avatars.githubusercontent.com/u/1532151?v=4 + url: https://github.com/classmethod - - login: renderinc avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 url: https://github.com/renderinc - - login: Nixtla - avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 - url: https://github.com/Nixtla - login: andrew-propelauth avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4 url: https://github.com/andrew-propelauth @@ -17,12 +17,15 @@ sponsors: - login: coderabbitai avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 url: https://github.com/coderabbitai + - login: madisonredtfeldt + avatarUrl: https://avatars.githubusercontent.com/u/152656511?v=4 + url: https://github.com/madisonredtfeldt - login: subtotal avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 url: https://github.com/subtotal - - login: porter-dev - avatarUrl: https://avatars.githubusercontent.com/u/62078005?v=4 - url: https://github.com/porter-dev + - login: Nixtla + avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 + url: https://github.com/Nixtla - login: scalar avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 url: https://github.com/scalar @@ -41,27 +44,27 @@ sponsors: - login: speakeasy-api avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4 url: https://github.com/speakeasy-api - - login: snapit-cypher - avatarUrl: https://avatars.githubusercontent.com/u/115662654?v=4 - url: https://github.com/snapit-cypher - login: databento avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4 url: https://github.com/databento - login: permitio avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 url: https://github.com/permitio -- - login: mercedes-benz - avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 - url: https://github.com/mercedes-benz - - login: xoflare +- - login: xoflare avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 url: https://github.com/xoflare - login: marvin-robot avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4 url: https://github.com/marvin-robot + - login: mercedes-benz + avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 + url: https://github.com/mercedes-benz - login: Ponte-Energy-Partners avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4 url: https://github.com/Ponte-Energy-Partners + - login: snapit-cypher + avatarUrl: https://avatars.githubusercontent.com/u/115662654?v=4 + url: https://github.com/snapit-cypher - login: LambdaTest-Inc avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 url: https://github.com/LambdaTest-Inc @@ -98,15 +101,21 @@ sponsors: - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin + - login: CoodingPenguin + avatarUrl: https://avatars.githubusercontent.com/u/37505775?u=6a9e1f6647fbf95f99afeee82a3682e15fc6e959&v=4 + url: https://github.com/CoodingPenguin + - login: deight93 + avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 + url: https://github.com/deight93 - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky - login: ramonalmeidam avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 url: https://github.com/ramonalmeidam - - login: ashi-agrawal - avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 - url: https://github.com/ashi-agrawal + - login: kaoru0310 + avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 + url: https://github.com/kaoru0310 - login: RaamEEIL avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 url: https://github.com/RaamEEIL @@ -125,9 +134,6 @@ sponsors: - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure - - login: kaoru0310 - avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 - url: https://github.com/kaoru0310 - login: DelfinaCare avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 url: https://github.com/DelfinaCare @@ -191,9 +197,6 @@ sponsors: - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 url: https://github.com/gorhack - - login: Ryandaydev - avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 - url: https://github.com/Ryandaydev - login: vincentkoc avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 url: https://github.com/vincentkoc @@ -227,15 +230,9 @@ sponsors: - login: mintuhouse avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 url: https://github.com/mintuhouse - - login: TrevorBenson - avatarUrl: https://avatars.githubusercontent.com/u/9167887?u=dccbea3327a57750923333d8ebf1a0b3f1948949&v=4 - url: https://github.com/TrevorBenson - login: wdwinslow - avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4 url: https://github.com/wdwinslow - - login: catherinenelson1 - avatarUrl: https://avatars.githubusercontent.com/u/11951946?u=fe11bc35d36b6038cd46a946e4e46ef8aa5688ab&v=4 - url: https://github.com/catherinenelson1 - login: jsoques avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4 url: https://github.com/jsoques @@ -251,6 +248,12 @@ sponsors: - login: mjohnsey avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 url: https://github.com/mjohnsey + - login: ashi-agrawal + avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 + url: https://github.com/ashi-agrawal + - login: Ryandaydev + avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 + url: https://github.com/Ryandaydev - login: jaredtrog avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 url: https://github.com/jaredtrog @@ -278,9 +281,6 @@ sponsors: - - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy - - login: bnkc - avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4 - url: https://github.com/bnkc - login: petercool avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=81c525232bb35780945a68e88afd96bb2cdad9c4&v=4 url: https://github.com/petercool @@ -296,12 +296,6 @@ sponsors: - login: caviri avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 url: https://github.com/caviri - - login: hgalytoby - avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 - url: https://github.com/hgalytoby - - login: browniebroke - avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 - url: https://github.com/browniebroke - login: joshuatz avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 url: https://github.com/joshuatz @@ -323,21 +317,24 @@ sponsors: - login: engineerjoe440 avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 url: https://github.com/engineerjoe440 + - login: bnkc + avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4 + url: https://github.com/bnkc - login: lukzmu - avatarUrl: https://avatars.githubusercontent.com/u/175964415?u=83ea9b0b7b7b0f15bcb5747d93f303447a19a00b&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/175964415?u=75348f25bb99a5f92ddb40c0b9b1ff7acb39c150&v=4 url: https://github.com/lukzmu - - login: conservative-dude - avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4 - url: https://github.com/conservative-dude - - login: CR1337 - avatarUrl: https://avatars.githubusercontent.com/u/62649536?u=57a6aab10d2421a497306da8bcded01b826c54ae&v=4 - url: https://github.com/CR1337 + - login: hgalytoby + avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 + url: https://github.com/hgalytoby - login: PunRabbit avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4 url: https://github.com/PunRabbit - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ + - login: browniebroke + avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 + url: https://github.com/browniebroke - login: miguelgr avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 url: https://github.com/miguelgr @@ -347,9 +344,6 @@ sponsors: - login: my3 avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 url: https://github.com/my3 - - login: leobiscassi - avatarUrl: https://avatars.githubusercontent.com/u/1977418?u=f9f82445a847ab479bd7223debd677fcac6c49a0&v=4 - url: https://github.com/leobiscassi - login: Alisa-lisa avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 url: https://github.com/Alisa-lisa @@ -425,9 +419,6 @@ sponsors: - login: harsh183 avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 url: https://github.com/harsh183 - - login: hcristea - avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=19092923a4ea5b338567961c8270b9206a6d81bb&v=4 - url: https://github.com/hcristea - - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba @@ -446,15 +437,21 @@ sponsors: - login: larsyngvelundin avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 url: https://github.com/larsyngvelundin - - login: one-st-one + - login: 0ne-stone avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 - url: https://github.com/one-st-one - - login: federicsp - avatarUrl: https://avatars.githubusercontent.com/u/62903636?u=05004f4a2c590f1d18c200e17978bf2e17acb632&v=4 - url: https://github.com/federicsp + url: https://github.com/0ne-stone + - login: darixsamani + avatarUrl: https://avatars.githubusercontent.com/u/67915678?u=cfa82128692eeeec4bf0e7a0faaa9a614695c0f9&v=4 + url: https://github.com/darixsamani + - login: nayasinghania + avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=af853245a21fe052b6a27e41a8de8cf4cdf76e85&v=4 + url: https://github.com/nayasinghania - login: Toothwitch avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 url: https://github.com/Toothwitch + - login: roboman-tech + avatarUrl: https://avatars.githubusercontent.com/u/8183070?u=fdeaa2ed29f598eb7901693884c0ad32b16982e3&v=4 + url: https://github.com/roboman-tech - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi From 3e666dfdd7f74f6ec3779db84955aa7be43b12a9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 1 Jul 2025 13:20:35 +0000 Subject: [PATCH 235/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8057c3021..0c2338b9a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#13848](https://github.com/fastapi/fastapi/pull/13848) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.1 to 9.6.15. PR [#13849](https://github.com/fastapi/fastapi/pull/13849) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13843](https://github.com/fastapi/fastapi/pull/13843) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 👥 Update FastAPI People - Contributors and Translators. PR [#13845](https://github.com/fastapi/fastapi/pull/13845) by [@tiangolo](https://github.com/tiangolo). From 8f336c5fd3be2089dfdd82bc7e5d79b4da7bf108 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 1 Jul 2025 13:20:56 +0000 Subject: [PATCH 236/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0c2338b9a..f135ab134 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Sponsors. PR [#13846](https://github.com/fastapi/fastapi/pull/13846) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#13848](https://github.com/fastapi/fastapi/pull/13848) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.1 to 9.6.15. PR [#13849](https://github.com/fastapi/fastapi/pull/13849) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13843](https://github.com/fastapi/fastapi/pull/13843) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 4f4d47baf497bb36d0e5d3b838f760550cf18a05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:07:09 +0200 Subject: [PATCH 237/455] =?UTF-8?q?=E2=AC=86=20Bump=20pillow=20from=2011.1?= =?UTF-8?q?.0=20to=2011.3.0=20(#13852)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pillow](https://github.com/python-pillow/Pillow) from 11.1.0 to 11.3.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/11.1.0...11.3.0) --- updated-dependencies: - dependency-name: pillow dependency-version: 11.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 059203ec1..5c5701f73 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -8,7 +8,7 @@ pyyaml >=5.3.1,<7.0.0 # For Material for MkDocs, Chinese search jieba==0.42.1 # For image processing by Material for MkDocs -pillow==11.1.0 +pillow==11.3.0 # For image processing by Material for MkDocs cairosvg==2.7.1 mkdocstrings[python]==0.26.1 From 2915e31dab7057a24a24a91797195a9e28aacb96 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 2 Jul 2025 19:07:32 +0000 Subject: [PATCH 238/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f135ab134..e9b15bf62 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ Bump pillow from 11.1.0 to 11.3.0. PR [#13852](https://github.com/fastapi/fastapi/pull/13852) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Sponsors. PR [#13846](https://github.com/fastapi/fastapi/pull/13846) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI GitHub topic repositories. PR [#13848](https://github.com/fastapi/fastapi/pull/13848) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.1 to 9.6.15. PR [#13849](https://github.com/fastapi/fastapi/pull/13849) by [@dependabot[bot]](https://github.com/apps/dependabot). From 6682295c73c1c1ba22bad9efff86682adfca9035 Mon Sep 17 00:00:00 2001 From: Naves <79222417+NavesSapnis@users.noreply.github.com> Date: Fri, 4 Jul 2025 08:17:17 +0300 Subject: [PATCH 239/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translat?= =?UTF-8?q?ion=20for=20`docs/ru/docs/advanced/additional-status-codes.md`?= =?UTF-8?q?=20(#13799)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Russian translation for `docs/ru/docs/advanced/additional-status-codes.md` * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks * Update additional-status-codes.md fixed `Response-классов` --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../docs/advanced/additional-status-codes.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/ru/docs/advanced/additional-status-codes.md diff --git a/docs/ru/docs/advanced/additional-status-codes.md b/docs/ru/docs/advanced/additional-status-codes.md new file mode 100644 index 000000000..aab1f8ee3 --- /dev/null +++ b/docs/ru/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# Дополнительные статус коды + +По умолчанию **FastAPI** возвращает ответы, используя `JSONResponse`, помещая содержимое, которое вы возвращаете из вашей *операции пути*, внутрь этого `JSONResponse`. + +Он будет использовать код статуса по умолчанию или тот, который вы укажете в вашей *операции пути*. + +## Дополнительные статус коды + +Если вы хотите возвращать дополнительный статус код помимо основного, вы можете сделать это, возвращая объект `Response` напрямую, как `JSONResponse`, и устанавливая нужный статус код напрямую. + +Например, скажем, вы хотите создать *операцию пути*, которая позволяет обновлять элементы и возвращает HTTP-код 200 "OK" при успешном выполнении. + +Но вы также хотите, чтобы она принимала новые элементы. И если элемент ранее не существовал, он создаётся, и возвращался HTTP-код 201 "Created". + +Чтобы реализовать это, импортируйте `JSONResponse` и возвращайте ваш контент напрямую, устанавливая нужный `status_code`: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning | Внимание + +Когда вы возвращаете объект `Response` напрямую, как в примере выше, он будет возвращён как есть. + +Он не будет сериализован при помощи модели и т.д. + +Убедитесь, что в нём содержатся именно те данные, которые вы хотите, и что значения являются валидным JSON (если вы используете `JSONResponse`). + +/// + +/// note | Технические детали + +Вы также можете использовать `from starlette.responses import JSONResponse`. + +**FastAPI** предоставляет тот же `starlette.responses` через `fastapi.responses` просто для вашего удобства, как разработчика. Но большинство доступных Response-классов поступают напрямую из Starlette. То же самое касается и `status`. + +/// + +## OpenAPI и документация API + +Если вы возвращаете дополнительные коды статусов и ответы напрямую, они не будут включены в схему OpenAPI (документацию API), потому что FastAPI не может заранее знать, что вы собираетесь вернуть. + +Но вы можете задокументировать это в вашем коде, используя: [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. From 8068a404c7597d5bdbf4afdce37dffbccb44111d Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 4 Jul 2025 05:17:43 +0000 Subject: [PATCH 240/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e9b15bf62..2dd3526b7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Add Russian translation for `docs/ru/docs/advanced/additional-status-codes.md`. PR [#13799](https://github.com/fastapi/fastapi/pull/13799) by [@NavesSapnis](https://github.com/NavesSapnis). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-updates.md`. PR [#13804](https://github.com/fastapi/fastapi/pull/13804) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). ### Internal From 0d5dc7ee7bdcd747fd15cfa5d562d2b6411a2fa5 Mon Sep 17 00:00:00 2001 From: Naves <79222417+NavesSapnis@users.noreply.github.com> Date: Fri, 4 Jul 2025 08:21:55 +0300 Subject: [PATCH 241/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Russian=20translat?= =?UTF-8?q?ion=20for=20`docs/ru/docs/advanced/response-directly.md`=20(#13?= =?UTF-8?q?801)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Russian translation for `docs/ru/docs/advanced/response-directly.md` * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks * Update response-directly.md fixed `Response-классов` --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/ru/docs/advanced/response-directly.md | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 docs/ru/docs/advanced/response-directly.md diff --git a/docs/ru/docs/advanced/response-directly.md b/docs/ru/docs/advanced/response-directly.md new file mode 100644 index 000000000..ee83d22b1 --- /dev/null +++ b/docs/ru/docs/advanced/response-directly.md @@ -0,0 +1,65 @@ +# Возврат ответа напрямую + +Когда вы создаёте **FastAPI** *операцию пути*, вы можете возвращать из неё любые данные: `dict`, `list`, Pydantic-модель, модель базы данных и т.д. + +По умолчанию **FastAPI** автоматически преобразует возвращаемое значение в JSON с помощью `jsonable_encoder`, как описано в [JSON кодировщик](../tutorial/encoder.md){.internal-link target=_blank}. + +Затем "под капотом" эти данные, совместимые с JSON (например `dict`), помещаются в `JSONResponse`, который используется для отправки ответа клиенту. + +Но вы можете возвращать `JSONResponse` напрямую из ваших *операций пути*. + +Это может быть полезно, например, если нужно вернуть пользовательские заголовки или куки. + +## Возврат `Response` + +На самом деле, вы можете возвращать любой объект `Response` или его подкласс. + +/// tip | Подсказка + +`JSONResponse` сам по себе является подклассом `Response`. + +/// + +И когда вы возвращаете `Response`, **FastAPI** передаст его напрямую. + +Это не приведет к преобразованию данных с помощью Pydantic-моделей, содержимое не будет преобразовано в какой-либо тип и т.д. + +Это даёт вам большую гибкость. Вы можете возвращать любые типы данных, переопределять любые объявления или валидацию данных и т.д. + +## Использование `jsonable_encoder` в `Response` + +Поскольку **FastAPI** не изменяет объект `Response`, который вы возвращаете, вы должны убедиться, что его содержимое готово к отправке. + +Например, вы не можете поместить Pydantic-модель в `JSONResponse`, не преобразовав её сначала в `dict` с помощью преобразования всех типов данных (таких как `datetime`, `UUID` и т.д.) в совместимые с JSON типы. + +В таких случаях вы можете использовать `jsonable_encoder` для преобразования данных перед передачей их в ответ: + +{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *} + +/// note | Технические детали + +Вы также можете использовать `from starlette.responses import JSONResponse`. + +**FastAPI** предоставляет `starlette.responses` через `fastapi.responses` просто для вашего удобства, как разработчика. Но большинство доступных Response-классов поступают напрямую из Starlette. + +/// + +## Возврат пользовательского `Response` + +Пример выше показывает все необходимые части, но он пока не очень полезен, так как вы могли бы просто вернуть `item` напрямую, и **FastAPI** поместил бы его в `JSONResponse`, преобразовав в `dict` и т.д. Всё это происходит по умолчанию. + +Теперь давайте посмотрим, как можно использовать это для возврата пользовательского ответа. + +Допустим, вы хотите вернуть ответ в формате XML. + +Вы можете поместить ваш XML-контент в строку, поместить её в `Response` и вернуть: + +{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} + +## Примечания + +Когда вы возвращаете объект `Response` напрямую, его данные не валидируются, не преобразуются (не сериализуются) и не документируются автоматически. + +Но вы всё равно можете задокументировать это, как описано в [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}. + +В следующих разделах вы увидите, как использовать/объявлять такие кастомные `Response`, при этом сохраняя автоматическое преобразование данных, документацию и т.д. From af64e9d196fc124a7f8051406234301c3b4024ed Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 4 Jul 2025 05:22:22 +0000 Subject: [PATCH 242/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2dd3526b7..e176d9402 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Add Russian translation for `docs/ru/docs/advanced/response-directly.md`. PR [#13801](https://github.com/fastapi/fastapi/pull/13801) by [@NavesSapnis](https://github.com/NavesSapnis). * 🌐 Add Russian translation for `docs/ru/docs/advanced/additional-status-codes.md`. PR [#13799](https://github.com/fastapi/fastapi/pull/13799) by [@NavesSapnis](https://github.com/NavesSapnis). * 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-updates.md`. PR [#13804](https://github.com/fastapi/fastapi/pull/13804) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). From b083ccd250e8fd22c3f9f8b3fd34765c6d625917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 7 Jul 2025 17:00:35 +0200 Subject: [PATCH 243/455] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20deplo?= =?UTF-8?q?ying=20to=20FastAPI=20Cloud=20with=20`fastapi=20deploy`=20(#138?= =?UTF-8?q?70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 +++++++-- docs/en/docs/index.md | 9 +++++++-- docs/en/docs/tutorial/index.md | 4 +++- pyproject.toml | 23 +++++++++++++++++++++-- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ab5143084..25a1d9179 100644 --- a/README.md +++ b/README.md @@ -470,15 +470,20 @@ Used by Starlette: * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. -Used by FastAPI / Starlette: +Used by FastAPI: * uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. -* `fastapi-cli` - to provide the `fastapi` command. +* `fastapi-cli[standard]` - to provide the `fastapi` command. + * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. ### Without `standard` Dependencies If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. +### Without `fastapi-cloud-cli` + +If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + ### Additional Optional Dependencies There are some additional dependencies you might want to install. diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 0f3623ed5..938882d7d 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -468,15 +468,20 @@ Used by Starlette: * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. -Used by FastAPI / Starlette: +Used by FastAPI: * uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. -* `fastapi-cli` - to provide the `fastapi` command. +* `fastapi-cli[standard]` - to provide the `fastapi` command. + * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. ### Without `standard` Dependencies If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. +### Without `fastapi-cloud-cli` + +If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + ### Additional Optional Dependencies There are some additional dependencies you might want to install. diff --git a/docs/en/docs/tutorial/index.md b/docs/en/docs/tutorial/index.md index 4fe38256c..17f6fb685 100644 --- a/docs/en/docs/tutorial/index.md +++ b/docs/en/docs/tutorial/index.md @@ -76,10 +76,12 @@ $ pip install "fastapi[standard]" /// note -When you install with `pip install "fastapi[standard]"` it comes with some default optional standard dependencies. +When you install with `pip install "fastapi[standard]"` it comes with some default optional standard dependencies, including `fastapi-cloud-cli`, which allows you to deploy to FastAPI Cloud. If you don't want to have those optional dependencies, you can instead install `pip install fastapi`. +If you want to install the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + /// ## Advanced User Guide diff --git a/pyproject.toml b/pyproject.toml index 1c540e2f6..a3fc54e3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,26 @@ Changelog = "https://fastapi.tiangolo.com/release-notes/" [project.optional-dependencies] standard = [ - "fastapi-cli[standard] >=0.0.5", + "fastapi-cli[standard] >=0.0.8", + # For the test client + "httpx >=0.23.0", + # For templates + "jinja2 >=3.1.5", + # For forms and file uploads + "python-multipart >=0.0.18", + # To validate email fields + "email-validator >=2.0.0", + # Uvicorn with uvloop + "uvicorn[standard] >=0.12.0", + # TODO: this should be part of some pydantic optional extra dependencies + # # Settings management + # "pydantic-settings >=2.0.0", + # # Extra Pydantic data types + # "pydantic-extra-types >=2.0.0", +] + +standard-no-fastapi-cloud-cli = [ + "fastapi-cli[standard-no-fastapi-cloud-cli] >=0.0.8", # For the test client "httpx >=0.23.0", # For templates @@ -77,7 +96,7 @@ standard = [ ] all = [ - "fastapi-cli[standard] >=0.0.5", + "fastapi-cli[standard] >=0.0.8", # # For the test client "httpx >=0.23.0", # For templates From dd906a998ee2aa41cba98edf13364b34fdc9b1c1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 7 Jul 2025 15:00:58 +0000 Subject: [PATCH 244/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e176d9402..b22e8dd54 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* ✨ Add support for deploying to FastAPI Cloud with `fastapi deploy`. PR [#13870](https://github.com/fastapi/fastapi/pull/13870) by [@tiangolo](https://github.com/tiangolo). + ### Translations * 🌐 Add Russian translation for `docs/ru/docs/advanced/response-directly.md`. PR [#13801](https://github.com/fastapi/fastapi/pull/13801) by [@NavesSapnis](https://github.com/NavesSapnis). From 18eb7a708096ab7a19f31a59918bc010aba0ddba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 7 Jul 2025 17:05:38 +0200 Subject: [PATCH 245/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b22e8dd54..e8e7d9cdb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,12 @@ hide: * ✨ Add support for deploying to FastAPI Cloud with `fastapi deploy`. PR [#13870](https://github.com/fastapi/fastapi/pull/13870) by [@tiangolo](https://github.com/tiangolo). +Installing `fastapi[standard]` now includes `fastapi-cloud-cli`. + +This will allow you to deploy to [FastAPI Cloud](https://fastapicloud.com) with the `fastapi deploy` command. + +If you want to install `fastapi` with the standard dependencies but without `fastapi-cloud-cli`, you can install instead `fastapi[standard-no-fastapi-cloud-cli]`. + ### Translations * 🌐 Add Russian translation for `docs/ru/docs/advanced/response-directly.md`. PR [#13801](https://github.com/fastapi/fastapi/pull/13801) by [@NavesSapnis](https://github.com/NavesSapnis). From bd8f358fd93416835b06486566b9d9ab991577b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 7 Jul 2025 17:07:03 +0200 Subject: [PATCH 246/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?6.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e8e7d9cdb..d085081e2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.116.0 + ### Features * ✨ Add support for deploying to FastAPI Cloud with `fastapi deploy`. PR [#13870](https://github.com/fastapi/fastapi/pull/13870) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index e672ec9e5..873ae18e0 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.115.14" +__version__ = "0.116.0" from starlette import status as status From 07bcb18a5a2ddab8282f4a9d50f63f3c9f46ca8c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 08:49:17 +0200 Subject: [PATCH 247/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13871)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.1 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.1...v0.12.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 673c86127..680cafce9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.1 + rev: v0.12.2 hooks: - id: ruff args: From 7179d48fd774bcbc5f5013bb8f4df61b8c36795f Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 11 Jul 2025 06:49:39 +0000 Subject: [PATCH 248/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d085081e2..592e88ea3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13871](https://github.com/fastapi/fastapi/pull/13871) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + ## 0.116.0 ### Features From 2c13b1ba4bce313d68f2ebd562b9b0c3267f5158 Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Fri, 11 Jul 2025 18:14:15 +0200 Subject: [PATCH 249/455] =?UTF-8?q?=F0=9F=93=9D=20Add=20notification=20abo?= =?UTF-8?q?ut=20impending=20changes=20in=20Translations=20to=20`docs/en/do?= =?UTF-8?q?cs/contributing.md`=20(#13886)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/contributing.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 1b70a0ea9..91c39c927 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -181,6 +181,28 @@ as Uvicorn by default will use the port `8000`, the documentation on port `8008` ### Translations +/// warning | Attention + +**Update on Translations** + +We're updating the way we handle documentation translations. + +Until now, we invited community members to translate pages via pull requests, which were then reviewed by at least two native speakers. While this has helped bring FastAPI to many more users, we’ve also run into several challenges - some languages have only a few translated pages, others are outdated and hard to maintain over time. +To improve this, we’re working on automation tools 🤖 to manage translations more efficiently. Once ready, documentation will be machine-translated and still reviewed by at least two native speakers ✅ before publishing. This will allow us to keep translations up-to-date while reducing the review burden on maintainers. + +What’s changing now: + +* 🚫 We’re no longer accepting new community-submitted translation PRs. + +* ⏳ Existing open PRs will be reviewed and can still be merged if completed within the next 3 weeks (since July 11 2025). + +* 🌐 In the future, we will only support languages where at least three active native speakers are available to review and maintain translations. + +This transition will help us keep translations more consistent and timely while better supporting our contributors 🙌. Thank you to everyone who has contributed so far — your help has been invaluable! 💖 + +/// + + Help with translations is VERY MUCH appreciated! And it can't be done without the help from the community. 🌎 🚀 Here are the steps to help with translations. From a6e79e68a438c3e1f2ff628254d433832f73df53 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 11 Jul 2025 16:14:42 +0000 Subject: [PATCH 250/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 592e88ea3..d6527de83 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Add notification about impending changes in Translations to `docs/en/docs/contributing.md`. PR [#13886](https://github.com/fastapi/fastapi/pull/13886) by [@YuriiMotov](https://github.com/YuriiMotov). + ### Internal * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13871](https://github.com/fastapi/fastapi/pull/13871) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From cad6880fd97d6f25d3f05025c88230285386e7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 11 Jul 2025 18:15:27 +0200 Subject: [PATCH 251/455] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20Starlett?= =?UTF-8?q?e=20supported=20version=20range=20to=20`>=3D0.40.0,<0.48.0`=20(?= =?UTF-8?q?#13884)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/routing.py | 3 ++- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fastapi/routing.py b/fastapi/routing.py index bf61a65c1..54c75a027 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -9,6 +9,7 @@ from typing import ( Any, AsyncIterator, Callable, + Collection, Coroutine, Dict, List, @@ -862,7 +863,7 @@ class APIRouter(routing.Router): def route( self, path: str, - methods: Optional[List[str]] = None, + methods: Optional[Collection[str]] = None, name: Optional[str] = None, include_in_schema: bool = True, ) -> Callable[[DecoratedCallable], DecoratedCallable]: diff --git a/pyproject.toml b/pyproject.toml index a3fc54e3d..7709451ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette>=0.40.0,<0.47.0", + "starlette>=0.40.0,<0.48.0", "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0", "typing-extensions>=4.8.0", ] From 095dab00c7d7bb3fc5d02da159207d56ac5bc1ea Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 11 Jul 2025 16:16:48 +0000 Subject: [PATCH 252/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d6527de83..31787330e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Upgrades + +* ⬆️ Upgrade Starlette supported version range to `>=0.40.0,<0.48.0`. PR [#13884](https://github.com/fastapi/fastapi/pull/13884) by [@tiangolo](https://github.com/tiangolo). + ### Docs * 📝 Add notification about impending changes in Translations to `docs/en/docs/contributing.md`. PR [#13886](https://github.com/fastapi/fastapi/pull/13886) by [@YuriiMotov](https://github.com/YuriiMotov). From 313723494be79d4b24ccaa60e4f6d1f96c150fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 11 Jul 2025 18:17:01 +0200 Subject: [PATCH 253/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?6.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 31787330e..0a20ab9af 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.116.1 + ### Upgrades * ⬆️ Upgrade Starlette supported version range to `>=0.40.0,<0.48.0`. PR [#13884](https://github.com/fastapi/fastapi/pull/13884) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 873ae18e0..b02bf8b4f 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.116.0" +__version__ = "0.116.1" from starlette import status as status From ce26b8e1caa3d375dba527612717c3279a290b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 12 Jul 2025 21:09:49 +0200 Subject: [PATCH 254/455] =?UTF-8?q?=F0=9F=94=A8=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20sleep=20interval,=20use=20external=20settings=20(#13888)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/people.yml | 1 + scripts/people.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index 11931a05a..c1df3455e 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -51,3 +51,4 @@ jobs: run: python ./scripts/people.py env: GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} + SLEEP_INTERVAL: ${{ vars.PEOPLE_SLEEP_INTERVAL }} diff --git a/scripts/people.py b/scripts/people.py index f61fd31c9..7418b4595 100644 --- a/scripts/people.py +++ b/scripts/people.py @@ -119,6 +119,7 @@ class Settings(BaseSettings): github_token: SecretStr github_repository: str httpx_timeout: int = 30 + sleep_interval: int = 5 def get_graphql_response( @@ -184,7 +185,7 @@ def get_discussion_nodes(settings: Settings) -> list[DiscussionsNode]: discussion_nodes.append(discussion_edge.node) last_edge = discussion_edges[-1] # Handle GitHub secondary rate limits, requests per minute - time.sleep(5) + time.sleep(settings.sleep_interval) discussion_edges = get_graphql_question_discussion_edges( settings=settings, after=last_edge.cursor ) From 3063c7c57d75e982838964ce126392d1ea8bfc32 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 12 Jul 2025 19:10:12 +0000 Subject: [PATCH 255/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0a20ab9af..0b20fc04d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Internal + +* 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo). + ## 0.116.1 ### Upgrades From 6726bf8559c5a0744f64e4534e475a42a8c0b6a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 12 Jul 2025 21:32:26 +0200 Subject: [PATCH 256/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#13889)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/people.yml | 732 ++++++++++++++++++++-------------------- 1 file changed, 364 insertions(+), 368 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index a94c7c63c..e3eab5d01 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -8,22 +8,22 @@ experts: count: 1898 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: YuriiMotov + count: 941 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov - login: github-actions - count: 770 + count: 769 avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 url: https://github.com/apps/github-actions - login: Kludex - count: 655 + count: 654 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: jgould22 count: 263 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: YuriiMotov - count: 247 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov - login: dmontagu count: 240 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 @@ -33,11 +33,11 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4 url: https://github.com/Mause - login: ycd - count: 217 + count: 216 avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 url: https://github.com/ycd - login: JarroVGIT - count: 192 + count: 190 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: euri10 @@ -53,65 +53,65 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 91 + count: 93 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: luzzodev + count: 84 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: raphaelauv count: 83 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv -- login: ghandic - count: 71 - avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 - url: https://github.com/ghandic - login: ArcLightSlavik count: 71 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik +- login: ghandic + count: 71 + avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 + url: https://github.com/ghandic - login: n8sty count: 67 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty -- login: luzzodev - count: 61 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev - login: falkben count: 59 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben -- login: acidjunk - count: 50 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk - login: yinziyan1206 - count: 49 + count: 50 avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 url: https://github.com/yinziyan1206 - login: sm-Fifteen count: 49 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen +- login: acidjunk + count: 49 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk - login: adriangb count: 46 avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 url: https://github.com/adriangb -- login: insomnes - count: 45 - avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 - url: https://github.com/insomnes - login: Dustyposa count: 45 avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 url: https://github.com/Dustyposa -- login: odiseo0 - count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 - url: https://github.com/odiseo0 +- login: insomnes + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 + url: https://github.com/insomnes - login: frankie567 count: 43 avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4 url: https://github.com/frankie567 +- login: odiseo0 + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 + url: https://github.com/odiseo0 - login: sinisaos count: 41 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 @@ -120,14 +120,14 @@ experts: count: 40 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 url: https://github.com/includeamin -- login: chbndrhnns - count: 37 - avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 - url: https://github.com/chbndrhnns - login: STeveShary count: 37 avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 url: https://github.com/STeveShary +- login: chbndrhnns + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 + url: https://github.com/chbndrhnns - login: krishnardt count: 35 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 @@ -144,14 +144,14 @@ experts: count: 27 avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 url: https://github.com/hasansezertasan +- login: alv2017 + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: dbanty count: 26 avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9d726785d08e50b1e1cd96505800c8ea8405bce2&v=4 url: https://github.com/dbanty -- login: alv2017 - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 - login: wshayes count: 25 avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 @@ -176,10 +176,6 @@ experts: count: 21 avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=5fe59a56e1f2f9ccd8005d71752a8276f133ae1a&v=4 url: https://github.com/rafsaf -- login: ebottos94 - count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=8b91053b3abe4a9209375e3651e1c1ef192d884b&v=4 - url: https://github.com/ebottos94 - login: nsidnev count: 20 avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4 @@ -188,10 +184,18 @@ experts: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 url: https://github.com/chris-allnutt +- login: ebottos94 + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=8b91053b3abe4a9209375e3651e1c1ef192d884b&v=4 + url: https://github.com/ebottos94 - login: estebanx64 count: 19 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 +- login: retnikt + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 + url: https://github.com/retnikt - login: zoliknemet count: 18 avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 @@ -200,14 +204,6 @@ experts: count: 18 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz -- login: retnikt - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 - url: https://github.com/retnikt -- login: caeser1996 - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 - url: https://github.com/caeser1996 - login: Hultner count: 17 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 @@ -216,197 +212,249 @@ experts: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4 url: https://github.com/harunyasar +- login: caeser1996 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 + url: https://github.com/caeser1996 - login: nkhitrov count: 17 avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=e19427d8dc296d6950e9c424adacc92d37496fe9&v=4 url: https://github.com/nkhitrov -- login: jonatasoli - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 - url: https://github.com/jonatasoli - login: dstlny count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 url: https://github.com/dstlny -- login: abhint +- login: jonatasoli + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 + url: https://github.com/jonatasoli +- login: ghost count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 - url: https://github.com/abhint -- login: ceb10n - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n + avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4 + url: https://github.com/ghost - login: jorgerpo count: 15 avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 url: https://github.com/jorgerpo -- login: simondale00 +- login: pythonweb2 count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/33907262?u=2721fb37014d50daf473267c808aa678ecaefe09&v=4 - url: https://github.com/simondale00 + avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 + url: https://github.com/pythonweb2 +- login: abhint + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 + url: https://github.com/abhint last_month_experts: - login: YuriiMotov - count: 9 + count: 289 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 8 + count: 12 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev -- login: alv2017 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 +- login: raceychan + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 + url: https://github.com/raceychan +- login: valentinDruzhinin + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: DoctorJohn + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + url: https://github.com/DoctorJohn +- login: eqsdxr + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr - login: sachinh35 - count: 2 + count: 4 avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 url: https://github.com/sachinh35 -- login: KianAnbarestani - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani - login: tiangolo count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: Brikas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 + url: https://github.com/Brikas +- login: TaigoFr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr three_months_experts: -- login: luzzodev - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev - login: YuriiMotov - count: 24 + count: 732 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov +- login: luzzodev + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: valentinDruzhinin + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: sachinh35 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: raceychan + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 + url: https://github.com/raceychan +- login: DoctorJohn + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + url: https://github.com/DoctorJohn +- login: eqsdxr + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +- login: tiangolo + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: JavierSanchezCastro + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: henrymcl + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: jymchng + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng +- login: Brikas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 + url: https://github.com/Brikas +- login: TaigoFr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: davidhuser + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 + url: https://github.com/davidhuser +- login: KianAnbarestani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 + url: https://github.com/KianAnbarestani +- login: Kludex + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +six_months_experts: +- login: YuriiMotov + count: 749 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + url: https://github.com/YuriiMotov +- login: luzzodev + count: 51 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: alv2017 - count: 22 + count: 26 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 +- login: Kludex + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: valentinDruzhinin + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin - login: jgould22 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: Kludex +- login: JavierSanchezCastro count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: sachinh35 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: yauhen-sobaleu count: 9 avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu -- login: JavierSanchezCastro - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro - login: tiangolo - count: 6 + count: 8 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: sachinh35 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 +- login: raceychan + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 + url: https://github.com/raceychan +- login: DoctorJohn + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + url: https://github.com/DoctorJohn +- login: sehraramiz + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz +- login: eqsdxr + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe -- login: KianAnbarestani - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani -- login: sinisaos - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos -- login: Ale-Cas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: adsouza - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 - url: https://github.com/adsouza -- login: marsboy02 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 - url: https://github.com/marsboy02 - login: EverStarck count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 url: https://github.com/EverStarck -- login: vtgn +- login: henrymcl count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 - url: https://github.com/vtgn -six_months_experts: -- login: luzzodev - count: 57 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev -- login: YuriiMotov - count: 56 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov -- login: Kludex - count: 34 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: alv2017 - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: jgould22 - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: sehraramiz - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz -- login: JavierSanchezCastro - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: yauhen-sobaleu - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 - url: https://github.com/yauhen-sobaleu -- login: estebanx64 - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 -- login: yvallois - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois -- login: tiangolo - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: yokwejuste - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 - url: https://github.com/yokwejuste -- login: sachinh35 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 -- login: viniciusCalcantara - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 - url: https://github.com/viniciusCalcantara -- login: SobikXexe - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 - url: https://github.com/SobikXexe -- login: chaitanyarahalkar + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: jymchng count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/24942959?u=d3fbbc622540cb50b956585d5aec5037e01e4b1f&v=4 - url: https://github.com/chaitanyarahalkar + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng +- login: adsouza + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 + url: https://github.com/adsouza +- login: Brikas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 + url: https://github.com/Brikas +- login: JacobHayes + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 + url: https://github.com/JacobHayes +- login: TaigoFr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: davidhuser + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 + url: https://github.com/davidhuser +- login: PidgeyBE + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 + url: https://github.com/PidgeyBE - login: KianAnbarestani count: 2 avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 url: https://github.com/KianAnbarestani +- login: Ykaiqx + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 + url: https://github.com/Ykaiqx - login: sinisaos count: 2 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 @@ -415,30 +463,14 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 url: https://github.com/Ale-Cas -- login: adsouza - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 - url: https://github.com/adsouza -- login: Synrom - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 - url: https://github.com/Synrom -- login: PREPONDERANCE - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE - login: nbx3 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 url: https://github.com/nbx3 - login: marsboy02 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=efe3aa9e4b22689df7633a96328fb35bf4a23905&v=4 url: https://github.com/marsboy02 -- login: EverStarck - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 - url: https://github.com/EverStarck - login: vtgn count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 @@ -447,159 +479,131 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 url: https://github.com/Trinkes -- login: XiaoXinYo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/XiaoXinYo -- login: iloveitaly - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly -- login: LincolnPuzey - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18750802?v=4 - url: https://github.com/LincolnPuzey -- login: Knighthawk-Leo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72437494?u=27c68db94a3107b605e603cc136f4ba83f0106d5&v=4 - url: https://github.com/Knighthawk-Leo -- login: gelezo43 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 - url: https://github.com/gelezo43 -- login: AliYmn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=98c1fca46c7e4dabe8c39d17b5e55d1511d41cf9&v=4 - url: https://github.com/AliYmn -- login: RichieB2B - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 - url: https://github.com/RichieB2B -- login: iiotsrc - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 - url: https://github.com/iiotsrc -- login: Kfir-G - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 - url: https://github.com/Kfir-G one_year_experts: - login: YuriiMotov - count: 172 + count: 831 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 url: https://github.com/YuriiMotov -- login: Kludex - count: 63 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex - login: luzzodev - count: 61 + count: 84 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev +- login: Kludex + count: 55 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: sinisaos count: 41 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos -- login: JavierSanchezCastro - count: 33 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: jgould22 - count: 27 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 - login: alv2017 - count: 25 + count: 26 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 +- login: JavierSanchezCastro + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro - login: tiangolo - count: 24 + count: 22 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: ceb10n - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n -- login: estebanx64 - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 -- login: n8sty - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty +- login: jgould22 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 +- login: valentinDruzhinin + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin - login: Kfir-G count: 13 avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 url: https://github.com/Kfir-G +- login: estebanx64 + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 + url: https://github.com/estebanx64 - login: sehraramiz count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz -- login: PhysicallyActive - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 - url: https://github.com/PhysicallyActive -- login: mattmess1221 - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 - url: https://github.com/mattmess1221 +- login: ceb10n + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +- login: sachinh35 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: yauhen-sobaleu count: 9 avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu -- login: AIdjis +- login: n8sty count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 - url: https://github.com/AIdjis + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty - login: yvallois count: 7 avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 url: https://github.com/yvallois -- login: hasansezertasan +- login: raceychan + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 + url: https://github.com/raceychan +- login: DoctorJohn count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 - url: https://github.com/hasansezertasan -- login: gustavosett + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + url: https://github.com/DoctorJohn +- login: AIdjis count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/99373133?u=1382fe27034a0179f07cf989f63c4f23017f043c&v=4 - url: https://github.com/gustavosett -- login: chyok - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/32629225?u=3b7c30e8a09426a1b9284f6e8a0ae53a525596bf&v=4 - url: https://github.com/chyok -- login: PREPONDERANCE + avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 + url: https://github.com/AIdjis +- login: eqsdxr count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE -- login: svlandeg - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr - login: TomFaulkner count: 4 avatarUrl: https://avatars.githubusercontent.com/u/14956620?v=4 url: https://github.com/TomFaulkner - login: yokwejuste count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=4ba43bd63c169b5c015137d8916752a44001445a&v=4 url: https://github.com/yokwejuste -- login: binbjz +- login: PhysicallyActive count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/8213913?u=40b777c625cf53dcdc6afc4aa127de67c48bf610&v=4 - url: https://github.com/binbjz -- login: dbfreem + avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 + url: https://github.com/PhysicallyActive +- login: svlandeg + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: mattmess1221 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 - url: https://github.com/dbfreem -- login: sachinh35 + avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 + url: https://github.com/mattmess1221 +- login: pythonweb2 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 + avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 + url: https://github.com/pythonweb2 - login: viniciusCalcantara count: 3 avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 url: https://github.com/viniciusCalcantara +- login: davidhuser + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 + url: https://github.com/davidhuser +- login: bertomaniac + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 + url: https://github.com/bertomaniac +- login: dbfreem + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 + url: https://github.com/dbfreem - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 @@ -616,46 +620,38 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 url: https://github.com/Isuxiz -- login: bertomaniac - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 - url: https://github.com/bertomaniac -- login: deight93 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 - url: https://github.com/deight93 - login: Minibrams count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 url: https://github.com/Minibrams -- login: alexandercronin - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8014288?u=69580504c51a0cdd756fc47b23bb7f404bd694e7&v=4 - url: https://github.com/alexandercronin - login: yanggeorge count: 2 avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 url: https://github.com/yanggeorge -- login: chaitanyarahalkar +- login: mmzeynalli count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/24942959?u=d3fbbc622540cb50b956585d5aec5037e01e4b1f&v=4 - url: https://github.com/chaitanyarahalkar -- login: KianAnbarestani + avatarUrl: https://avatars.githubusercontent.com/u/33568903?u=19efd0c0722730b83a70b7c86c36e5b7d83e07d2&v=4 + url: https://github.com/mmzeynalli +- login: jd-solanki count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani -- login: rustonaut + avatarUrl: https://avatars.githubusercontent.com/u/47495003?u=6e225cb42c688d0cd70e65c6baedb9f5922b1178&v=4 + url: https://github.com/jd-solanki +- login: EverStarck count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/7632017?u=652bb86c1399727082c929fd4666fd7fa65923b1&v=4 - url: https://github.com/rustonaut -- login: Ale-Cas + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: slafs count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 - url: https://github.com/Ale-Cas -- login: CharlesPerrotMinotHCHB + avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 + url: https://github.com/slafs +- login: henrymcl count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112571330?u=a9628848d6096b491135727435a2a253152995a1&v=4 - url: https://github.com/CharlesPerrotMinotHCHB + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: jymchng + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng - login: adsouza count: 2 avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 @@ -668,59 +664,59 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/835733?u=8c72dec16fa560bdc81113354f2ffd79ad062bde&v=4 url: https://github.com/gaby -- login: nbx3 +- login: christiansicari count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: marsboy02 + avatarUrl: https://avatars.githubusercontent.com/u/29756552?v=4 + url: https://github.com/christiansicari +- login: Brikas count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=fa4a6b91eea3a11ae93c162616ca5edf51c68572&v=4 - url: https://github.com/marsboy02 -- login: EverStarck + avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 + url: https://github.com/Brikas +- login: JacobHayes count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 - url: https://github.com/EverStarck -- login: Trolldemorted + avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 + url: https://github.com/JacobHayes +- login: TaigoFr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/10261186?v=4 - url: https://github.com/Trolldemorted -- login: anantgupta129 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: rlimberger count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/66518357?u=6e25dcd84638f17d2c6df5dc26f07fd7c6dc118e&v=4 - url: https://github.com/anantgupta129 -- login: slafs + avatarUrl: https://avatars.githubusercontent.com/u/4841242?u=6a13252caf3cedceb07b6e2775b6592445d13b70&v=4 + url: https://github.com/rlimberger +- login: iloveitaly count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs -- login: ddahan + avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 + url: https://github.com/iloveitaly +- login: iiotsrc count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 - url: https://github.com/ddahan -- login: vtgn + avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 + url: https://github.com/iiotsrc +- login: AmirHmZz count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 - url: https://github.com/vtgn -- login: redb0 + avatarUrl: https://avatars.githubusercontent.com/u/38752106?u=07f80e451bda00a9492bbc764e49d24ad3ada8cc&v=4 + url: https://github.com/AmirHmZz +- login: PidgeyBE count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30475117?v=4 - url: https://github.com/redb0 -- login: pedroconceicao + avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 + url: https://github.com/PidgeyBE +- login: KianAnbarestani count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/32837064?u=5a0e6559bc391442629a28b6923790b54deb4464&v=4 - url: https://github.com/pedroconceicao -- login: msukmanowsky + avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 + url: https://github.com/KianAnbarestani +- login: Ykaiqx count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/362755?u=782e6bf5b9f0356c3f74b4d894fda9f179252086&v=4 - url: https://github.com/msukmanowsky -- login: rishabhc32 + avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 + url: https://github.com/Ykaiqx +- login: AliYmn count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/15983714?u=147776509107af8bdf099223e1840d3f40f944da&v=4 - url: https://github.com/rishabhc32 -- login: meower1 + avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=a77e2605e3ce6aaf6fef8ad4a7b0d32954fba47a&v=4 + url: https://github.com/AliYmn +- login: dolfinus count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/109747197?u=0a5cc2a6ae74e558f0afc2874da85132e5953d8b&v=4 - url: https://github.com/meower1 -- login: Trinkes + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus +- login: gelezo43 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 - url: https://github.com/Trinkes + avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 + url: https://github.com/gelezo43 From e6d09027e59cee9e83c97c3bb59b0d5b6544c618 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 12 Jul 2025 19:32:45 +0000 Subject: [PATCH 257/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0b20fc04d..65ca03a7d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo). ## 0.116.1 From 679a97603ac6edb754fdc3ca61c6f7291a03d1c2 Mon Sep 17 00:00:00 2001 From: sajjad rahman <67529599+sajjadrahman56@users.noreply.github.com> Date: Mon, 14 Jul 2025 18:58:49 +0600 Subject: [PATCH 258/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Bangali=20translat?= =?UTF-8?q?ion=20for=20`docs/bn/about/index.md`=20(#13882)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add translation for docs/about/index.md * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/bn/docs/about/index.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/bn/docs/about/index.md diff --git a/docs/bn/docs/about/index.md b/docs/bn/docs/about/index.md new file mode 100644 index 000000000..b6d611ae9 --- /dev/null +++ b/docs/bn/docs/about/index.md @@ -0,0 +1,3 @@ +# সম্পর্কে + +**FastAPI** সম্পর্কে বিস্তারিত — এর ডিজাইন, অনুপ্রেরণা ও আরও অনেক কিছু। 🤓 From 27f4240750eb5598aea4bc792c425efcd74a7393 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 14 Jul 2025 12:59:10 +0000 Subject: [PATCH 259/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 65ca03a7d..d33e76fce 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Translations + +* 🌐 Add Bangali translation for `docs/bn/about/index.md`. PR [#13882](https://github.com/fastapi/fastapi/pull/13882) by [@sajjadrahman56](https://github.com/sajjadrahman56). + ### Internal * 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). From 5c74eeba5bd82af096d3d7febec0034cc5f2580d Mon Sep 17 00:00:00 2001 From: Mohammad <116789737+Mohammad222PR@users.noreply.github.com> Date: Mon, 21 Jul 2025 13:12:59 +0330 Subject: [PATCH 260/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Persian=20translat?= =?UTF-8?q?ion=20for=20`docs/fa/docs/async.md`=20(#13541)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Persian translation for docs/fa/docs/async.md * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/fa/docs/async.md | 444 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 444 insertions(+) create mode 100644 docs/fa/docs/async.md diff --git a/docs/fa/docs/async.md b/docs/fa/docs/async.md new file mode 100644 index 000000000..e07374862 --- /dev/null +++ b/docs/fa/docs/async.md @@ -0,0 +1,444 @@ +# هم‌زمانی و async / await + +جزئیات در مورد سینتکس `async def` برای *توابع عملیات مسیر* و یه کم پیش‌زمینه در مورد کد ناهم‌زمان، هم‌زمانی و موازی‌سازی. + +## عجله داری؟ + +TL;DR: + +اگه از کتابخونه‌های سوم‌شخصی استفاده می‌کنی که بهت می‌گن با `await` صداشون کنی، مثل: + +```Python +results = await some_library() +``` + +اون وقت، *توابع عملیات مسیرت* رو با `async def` تعریف کن، اینجوری: + +```Python hl_lines="2" +@app.get('/') +async def read_results(): + results = await some_library() + return results +``` + +/// note + +فقط توی توابعی که با `async def` ساخته شدن می‌تونی از `await` استفاده کنی. + +/// + +--- + +اگه از یه کتابخونه سوم‌شخص استفاده می‌کنی که با یه چیزی (مثل دیتابیس، API، سیستم فایل و غیره) ارتباط داره و از `await` پشتیبانی نمی‌کنه (که الان برای بیشتر کتابخونه‌های دیتابیس اینجوریه)، اون وقت *توابع عملیات مسیرت* رو عادی، فقط با `def` تعریف کن، اینجوری: + +```Python hl_lines="2" +@app.get('/') +def results(): + results = some_library() + return results +``` + +--- + +اگه برنامه‌ات (به هر دلیلی) لازم نیست با چیز دیگه‌ای ارتباط برقرار کنه و منتظر جوابش بمونه، از `async def` استفاده کن. + +--- + +اگه نمی‌دونی چیکار کنی، از `def` معمولی استفاده کن. + +--- + +**توجه**: می‌تونی توی *توابع عملیات مسیرت* هر چقدر که لازم داری `def` و `async def` رو قاطی کنی و هر کدوم رو با بهترین گزینه برات تعریف کنی. FastAPI خودش کار درست رو باهاشون انجام می‌ده. + +به هر حال، توی هر کدوم از موقعیت‌های بالا، FastAPI هنوز ناهم‌زمان کار می‌کنه و خیلی خیلی سریع هست. + +ولی با دنبال کردن مراحل بالا، می‌تونه یه سری بهینه‌سازی عملکرد هم بکنه. + +## جزئیات فنی + +نسخه‌های مدرن پایتون از **"کد ناهم‌زمان"** با چیزی که بهش **"کروتین"** می‌گن پشتیبانی می‌کنن، با سینتکس **`async` و `await`**. + +بیاید این جمله رو تکه‌تکه توی بخش‌های زیر ببینیم: + +* **کد ناهم‌زمان** +* **`async` و `await`** +* **کروتین‌ها** + +## کد ناهم‌زمان + +کد ناهم‌زمان یعنی زبون 💬 یه راهی داره که به کامپیوتر / برنامه 🤖 بگه توی یه جای کد، باید منتظر بمونه تا *یه چیز دیگه* یه جای دیگه تموم بشه. فرض کن اون *یه چیز دیگه* اسمش "فایل-آروم" 📝 باشه. + +پس، توی اون مدت، کامپیوتر می‌تونه بره یه کار دیگه بکنه، تا وقتی "فایل-آروم" 📝 تموم بشه. + +بعدش کامپیوتر / برنامه 🤖 هر وقت فرصتی داشته باشه برمی‌گرده، چون دوباره منتظره، یا هر وقت همه کاری که اون لحظه داشته تموم کرده. و می‌بینه آیا کارایی که منتظرشون بوده تموم شدن یا نه، و هر کاری که باید بکنه رو انجام می‌ده. + +بعد، اون 🤖 اولین کاری که تموم شده (مثلاً "فایل-آروم" 📝 ما) رو برمی‌داره و هر کاری که باید باهاش بکنه رو ادامه می‌ده. + +این "منتظر یه چیز دیگه بودن" معمولاً به عملیات I/O اشاره داره که نسبتاً "آروم" هستن (نسبت به سرعت پردازنده و حافظه RAM)، مثل منتظر موندن برای: + +* داده‌هایی که از کلاینت از طریق شبکه فرستاده می‌شن +* داده‌هایی که برنامه‌ات فرستاده تا از طریق شبکه به کلاینت برسه +* محتوای یه فایل توی دیسک که سیستم بخوندش و به برنامه‌ات بده +* محتوایی که برنامه‌ات به سیستم داده تا توی دیسک بنویسه +* یه عملیات API از راه دور +* یه عملیات دیتابیس که تموم بشه +* یه کوئری دیتابیس که نتایجش برگرده +* و غیره. + +چون زمان اجرا بیشتر صرف انتظار برای عملیات I/O می‌شه، بهشون می‌گن عملیات "I/O bound". + +بهش "ناهم‌زمان" می‌گن چون کامپیوتر / برنامه لازم نیست با کار آروم "هم‌زمان" باشه، منتظر لحظه دقیق تموم شدن کار بمونه، در حالی که هیچ کاری نمی‌کنه، تا نتیجه رو بگیره و کارش رو ادامه بده. + +به جاش، چون یه سیستم "ناهم‌زمان" هست، وقتی کار تموم شد، می‌تونه یه کم توی صف منتظر بمونه (چند میکروثانیه) تا کامپیوتر / برنامه هر کاری که رفته بکنه رو تموم کنه، و بعد برگرده نتیجه رو بگیره و باهاش کار کنه. + +برای "هم‌زمان" (برخلاف "ناهم‌زمان") معمولاً از اصطلاح "ترتیبی" هم استفاده می‌کنن، چون کامپیوتر / برنامه همه مراحل رو به ترتیب دنبال می‌کنه قبل از اینکه بره سراغ یه کار دیگه، حتی اگه اون مراحل شامل انتظار باشن. + +### هم‌زمانی و برگرها + +این ایده **ناهم‌زمان** که بالا توضیح دادم گاهی بهش **"هم‌زمانی"** هم می‌گن. با **"موازی‌سازی"** فرق داره. + +**هم‌زمانی** و **موازی‌سازی** هر دو به "اتفاق افتادن چیزای مختلف کم‌وبیش همزمان" ربط دارن. + +ولی جزئیات بین *هم‌زمانی* و *موازی‌سازی* خیلی متفاوته. + +برای دیدن فرقش، این داستان در مورد برگرها رو تصور کن: + +### برگرهای هم‌زمان + +با عشقت می‌ری فست‌فود بگیرین، توی صف وایمیستی در حالی که صندوقدار سفارش آدمای جلوی تو رو می‌گیره. 😍 + + + +بعد نوبت تو می‌شه، سفارش دو تا برگر خیلی شیک برای خودت و عشقت می‌دی. 🍔🍔 + + + +صندوقدار یه چیزی به آشپز توی آشپزخونه می‌گه تا بدونن باید برگرهای تو رو آماده کنن (گرچه الان دارن برگرهای مشتریای قبلی رو درست می‌کنن). + + + +پول رو می‌دی. 💸 + +صندوقدار شماره نوبتت رو بهت می‌ده. + + + +وقتی منتظری، با عشقت می‌ری یه میز انتخاب می‌کنی، می‌شینی و کلی با عشقت حرف می‌زنی (چون برگرهات خیلی شیکن و آماده کردنشون یه کم طول می‌کشه). + +وقتی پشت میز با عشقت نشستی، در حالی که منتظر برگرهایی، می‌تونی اون زمان رو صرف تحسین این کنی که عشقت چقدر باحال، ناز و باهوشه ✨😍✨. + + + +وقتی منتظری و با عشقت حرف می‌زنی، هر از گاهی شماره‌ای که رو پیشخون نشون داده می‌شه رو چک می‌کنی که ببینی نوبتت شده یا نه. + +بعد یه جایی بالاخره نوبتت می‌شه. می‌ری پیشخون، برگرهات رو می‌گیری و برمی‌گردی سر میز. + + + +تو و عشقت برگرها رو می‌خورین و یه وقت خوب باهم دارین. ✨ + + + +/// info + +تصاویر قشنگ از کترینا تامپسون. 🎨 + +/// + +--- + +تصور کن تو توی این داستان کامپیوتر / برنامه 🤖 هستی. + +وقتی توی صف هستی، فقط بیکاری 😴، منتظر نوبتت هستی، کار خیلی "مفیدی" نمی‌کنی. ولی صف سریع پیش می‌ره چون صندوقدار فقط سفارش می‌گیره (آمادشون نمی‌کنه)، پس این خوبه. + +بعد، وقتی نوبتت می‌شه، کار "مفید" واقعی می‌کنی، منو رو پردازش می‌کنی، تصمیم می‌گیری چی می‌خوای، انتخاب عشقت رو می‌گیری، پول می‌دی، چک می‌کنی اسکناس یا کارت درست رو دادی، چک می‌کنی درست حساب شده، چک می‌کنی سفارش آیتمای درست رو داره و غیره. + +ولی بعد، گرچه هنوز برگرهات رو نداری، کارت با صندوقدار "موقتاً متوقف" ⏸ می‌شه، چون باید منتظر بمونی 🕙 تا برگرهات آماده بشن. + +ولی وقتی از پیشخون دور می‌شی و با شماره نوبتت سر میز می‌شینی، می‌تونی توجهت رو 🔀 به عشقت بدی و "کار" ⏯ 🤓 رو اون بکنی. بعدش دوباره داری یه چیز خیلی "مفید" انجام می‌دی، مثل لاس زدن با عشقت 😍. + +بعد صندوقدار 💁 با گذاشتن شماره‌ات رو نمایشگر پیشخون می‌گه "من با درست کردن برگرها تموم کردم"، ولی تو مثل دیوونه‌ها وقتی شماره‌ات رو نمایشگر میاد فوری نمی‌پری. می‌دونی کسی برگرهات رو نمی‌دزده چون شماره نوبتت رو داری، و اونا هم مال خودشون رو دارن. + +پس منتظر می‌مونی تا عشقت داستانش رو تموم کنه (کار فعلی ⏯ / وظیفه‌ای که داره پردازش می‌شه 🤓)، آروم لبخند می‌زنی و می‌گی که می‌ری برگرها رو بیاری ⏸. + +بعد می‌ری پیشخون 🔀، به کار اولیه که حالا تموم شده ⏯، برگرها رو می‌گیری، تشکر می‌کنی و می‌برشون سر میز. این مرحله / وظیفه تعامل با پیشخون رو تموم می‌کنه ⏹. این به نوبه خودش یه وظیفه جدید، "خوردن برگرها" 🔀 ⏯، می‌سازه، ولی اون قبلی که "گرفتن برگرها" بود تموم شده ⏹. + +### برگرهای موازی + +حالا فرض کن اینا "برگرهای هم‌زمان" نیستن، بلکه "برگرهای موازی" هستن. + +با عشقت می‌ری فست‌فود موازی بگیری. + +توی صف وایمیستی در حالی که چند تا (مثلاً 8 تا) صندوقدار که همزمان آشپز هم هستن سفارش آدمای جلوی تو رو می‌گیرن. + +همه قبل تو منتظرن برگرهاشون آماده بشه قبل از اینکه پیشخون رو ترک کنن، چون هر کدوم از 8 تا صندوقدار می‌ره و برگر رو همون موقع درست می‌کنه قبل از اینکه سفارش بعدی رو بگیره. + + + +بالاخره نوبت تو می‌شه، سفارش دو تا برگر خیلی شیک برای خودت و عشقت می‌دی. + +پول رو می‌دی 💸. + + + +صندوقدار می‌ره آشپزخونه. + +منتظر می‌مونی، جلوی پیشخون وایستادی 🕙، که کسی قبل از تو برگرهات رو نگیره، چون شماره نوبت نیست. + + + +چون تو و عشقت مشغول این هستین که نذارین کسی جلوتون بیاد و هر وقت برگرها رسیدن اونا رو بگیره، نمی‌تونی به عشقت توجه کنی. 😞 + +این کار "هم‌زمان" هست، تو با صندوقدار/آشپز 👨‍🍳 "هم‌زمان" هستی. باید منتظر بمونی 🕙 و درست همون لحظه که صندوقدار/آشپز 👨‍🍳 برگرها رو تموم می‌کنه و بهت می‌ده اونجا باشی، وگرنه ممکنه یکی دیگه اونا رو بگیره. + + + +بعد صندوقدار/آشپزت 👨‍🍳 بالاخره بعد از یه مدت طولانی انتظار 🕙 جلوی پیشخون با برگرهات برمی‌گرده. + + + +برگرهات رو می‌گیری و با عشقت می‌ری سر میز. + +فقط می‌خورینشون، و تمومه. ⏹ + + + +حرف زدن یا لاس زدن زیاد نبود چون بیشتر وقت صرف انتظار 🕙 جلوی پیشخون شد. 😞 + +/// info + +تصاویر قشنگ از کترینا تامپسون. 🎨 + +/// + +--- + +توی این سناریوی برگرهای موازی، تو یه کامپیوتر / برنامه 🤖 با دو تا پردازنده (تو و عشقت) هستی، هر دو منتظر 🕙 و توجهشون ⏯ رو برای مدت طولانی "انتظار جلوی پیشخون" 🕙 گذاشتن. + +فست‌فود 8 تا پردازنده (صندوقدار/آشپز) داره. در حالی که فست‌فود برگرهای هم‌زمان شاید فقط 2 تا داشته (یه صندوقدار و یه آشپز). + +ولی با این حال، تجربه نهایی بهترین نیست. 😞 + +--- + +این معادل موازی داستان برگرها بود. 🍔 + +برای یه مثال "واقعی‌تر" از زندگی، یه بانک رو تصور کن. + +تا همین چند وقت پیش، بیشتر بانک‌ها چند تا صندوقدار 👨‍💼👨‍💼👨‍💼👨‍💼 داشتن و یه صف بزرگ 🕙🕙🕙🕙🕙🕙🕙🕙. + +همه صندوقدارها کار رو با یه مشتری بعد از اون یکی 👨‍💼⏯ انجام می‌دادن. + +و باید توی صف 🕙 مدت زیادی منتظر بمونی وگرنه نوبتت رو از دست می‌دی. + +احتمالاً نمی‌خوای عشقت 😍 رو با خودت ببری بانک 🏦 برای کارای روزمره. + +### نتیجه‌گیری برگرها + +توی این سناریوی "برگرهای فست‌فود با عشقت"، چون کلی انتظار 🕙 هست، خیلی منطقی‌تره که یه سیستم هم‌زمان ⏸🔀⏯ داشته باشی. + +این برای بیشتر برنامه‌های وب هم صدق می‌کنه. + +خیلی خیلی کاربر، ولی سرورت منتظر 🕙 اتصال نه‌چندان خوبشون هست تا درخواست‌هاشون رو بفرستن. + +و بعد دوباره منتظر 🕙 که جواب‌ها برگردن. + +این "انتظار" 🕙 توی میکروثانیه‌ها اندازه‌گیری می‌شه، ولی با این حال، جمعش که بکنی آخرش کلی انتظار می‌شه. + +برای همین استفاده از کد ناهم‌زمان ⏸🔀⏯ برای APIهای وب خیلی منطقیه. + +این نوع ناهم‌زمانی چیزیه که NodeJS رو محبوب کرد (گرچه NodeJS موازی نیست) و نقطه قوت Go به‌عنوان یه زبون برنامه‌نویسیه. + +و همون سطح عملکردی هست که با **FastAPI** می‌گیری. + +و چون می‌تونی هم‌زمانی و موازی‌سازی رو همزمان داشته باشی، عملکرد بالاتری از بیشتر فریم‌ورک‌های تست‌شده NodeJS می‌گیری و هم‌تراز با Go، که یه زبون کامپایل‌شده نزدیک به C هست (همه اینا به لطف Starlette). + +### آیا هم‌زمانی از موازی‌سازی بهتره؟ + +نه! این نتیجه داستان نیست. + +هم‌زمانی با موازی‌سازی فرق داره. و توی **سناریوهای خاص** که کلی انتظار دارن بهتره. به همین خاطر، معمولاً برای توسعه برنامه‌های وب خیلی از موازی‌سازی بهتره. ولی نه برای همه‌چیز. + +برای اینکه یه تعادل بذاریم، این داستان کوتاه رو تصور کن: + +> باید یه خونه بزرگ و کثیف رو تمیز کنی. + +*آره، کل داستان همینه*. + +--- + +هیچ انتظاری 🕙 اونجا نیست، فقط کلی کار برای انجام دادن توی جاهای مختلف خونه. + +می‌تونی مثل مثال برگرها نوبت بذاری، اول پذیرایی، بعد آشپزخونه، ولی چون منتظر چیزی نیستی 🕙، فقط داری تمیز می‌کنی و تمیز می‌کنی، نوبت‌ها هیچ تأثیری نداره. + +با نوبت یا بدون نوبت (هم‌زمانی) همون قدر طول می‌کشه تا تمومش کنی و همون مقدار کار رو کردی. + +ولی توی این موقعیت، اگه بتونی اون 8 تا صندوقدار/آشپز/حالا-تمیزکار رو بیاری، و هر کدومشون (به‌علاوه خودت) یه قسمت از خونه رو تمیز کنن، می‌تونی همه کار رو **موازی** انجام بدی، با کمک اضافی، و خیلی زودتر تمومش کنی. + +توی این سناریو، هر کدوم از تمیزکارها (از جمله خودت) یه پردازنده‌ست که کار خودش رو می‌کنه. + +و چون بیشتر زمان اجرا صرف کار واقعی می‌شه (به جای انتظار)، و کار توی کامپیوتر با CPU انجام می‌شه، به این مشکلات می‌گن "CPU bound". + +--- + +مثال‌های رایج عملیات CPU bound چیزایی هستن که نیاز به پردازش ریاضی پیچیده دارن. + +مثلاً: + +* پردازش **صدا** یا **تصویر**. +* **بینایی کامپیوتری**: یه تصویر از میلیون‌ها پیکسل تشکیل شده، هر پیکسل 3 تا مقدار / رنگ داره، پردازشش معمولاً نیاز داره چیزی رو رو اون پیکسل‌ها همزمان حساب کنی. +* **یادگیری ماشین**: معمولاً کلی ضرب "ماتریس" و "بردار" لازم داره. یه جدول بزرگ پر از عدد رو تصور کن که همه‌شون رو همزمان ضرب می‌کنی. +* **یادگیری عمیق**: این یه زیرشاخه از یادگیری ماشینه، پس همون قضیه صدق می‌کنه. فقط این که یه جدول عدد برای ضرب کردن نیست، بلکه یه مجموعه بزرگ از اونا هست، و توی خیلی موارد از یه پردازنده خاص برای ساخت و / یا استفاده از این مدل‌ها استفاده می‌کنی. + +### هم‌زمانی + موازی‌سازی: وب + یادگیری ماشین + +با **FastAPI** می‌تونی از هم‌زمانی که برای توسعه وب خیلی رایجه (همون جذابیت اصلی NodeJS) استفاده کنی. + +ولی می‌تونی از فواید موازی‌سازی و چندپردازشی (اجرای چند پروسه به‌صورت موازی) برای کارای **CPU bound** مثل سیستم‌های یادگیری ماشین هم بهره ببری. + +این، به‌علاوه این واقعیت ساده که پایتون زبون اصلی برای **علم داده**، یادگیری ماشین و به‌خصوص یادگیری عمیقه، باعث می‌شه FastAPI یه انتخاب خیلی خوب برای APIها و برنامه‌های وب علم داده / یادگیری ماشین باشه (بین خیلی چیزای دیگه). + +برای دیدن اینکه چطور توی محیط واقعی به این موازی‌سازی برسی، بخش [استقرار](deployment/index.md){.internal-link target=_blank} رو ببین. + +## `async` و `await` + +نسخه‌های مدرن پایتون یه راه خیلی ساده و قابل‌فهم برای تعریف کد ناهم‌زمان دارن. این باعث می‌شه مثل کد "ترتیبی" معمولی به نظر بیاد و توی لحظه‌های درست "انتظار" رو برات انجام بده. + +وقتی یه عملیاتی هست که قبل از دادن نتیجه‌ها نیاز به انتظار داره و از این قابلیت‌های جدید پایتون پشتیبانی می‌کنه، می‌تونی اینجوری کدنویسیش کنی: + +```Python +burgers = await get_burgers(2) +``` + +نکته کلیدی اینجا `await` هست. به پایتون می‌گه که باید ⏸ منتظر بمونه تا `get_burgers(2)` کارش 🕙 تموم بشه قبل از اینکه نتیجه‌ها رو توی `burgers` ذخیره کنه. با این، پایتون می‌دونه که می‌تونه بره یه کار دیگه 🔀 ⏯ توی این مدت بکنه (مثل گرفتن یه درخواست دیگه). + +برای اینکه `await` کار کنه، باید توی یه تابع باشه که از این ناهم‌زمانی پشتیبانی کنه. برای این کار، فقط با `async def` تعریفش می‌کنی: + +```Python hl_lines="1" +async def get_burgers(number: int): + # یه سری کار ناهم‌زمان برای ساختن برگرها انجام بده + return burgers +``` + +...به جای `def`: + +```Python hl_lines="2" +# این ناهم‌زمان نیست +def get_sequential_burgers(number: int): + # یه سری کار ترتیبی برای ساختن برگرها انجام بده + return burgers +``` + +با `async def`، پایتون می‌دونه که توی اون تابع باید حواسش به عبارت‌های `await` باشه، و می‌تونه اجرای اون تابع رو "موقتاً متوقف" ⏸ کنه و بره یه کار دیگه 🔀 قبل از برگشتن بکنه. + +وقتی می‌خوای یه تابع `async def` رو صدا کنی، باید "منتظرش" بمونی. پس این کار نمی‌کنه: + +```Python +# این کار نمی‌کنه، چون get_burgers با async def تعریف شده +burgers = get_burgers(2) +``` + +--- + +پس، اگه از یه کتابخونه استفاده می‌کنی که بهت می‌گه می‌تونی با `await` صداش کنی، باید *توابع عملیات مسیرت* که ازش استفاده می‌کنن رو با `async def` بسازی، مثل: + +```Python hl_lines="2-3" +@app.get('/burgers') +async def read_burgers(): + burgers = await get_burgers(2) + return burgers +``` + +### جزئیات فنی‌تر + +شاید متوجه شده باشی که `await` فقط توی توابعی که با `async def` تعریف شدن می‌تونه استفاده بشه. + +ولی در عین حال، توابعی که با `async def` تعریف شدن باید "منتظر"شون بمونی. پس توابع با `async def` فقط توی توابعی که با `async def` تعریف شدن می‌تونن صدا زده بشن. + +حالا، قضیه مرغ و تخم‌مرغ چیه، چطور اولین تابع `async` رو صدا می‌کنی؟ + +اگه با **FastAPI** کار می‌کنی، لازم نیست نگران این باشی، چون اون "اولین" تابع، *تابع عملیات مسیرت* هست، و FastAPI می‌دونه چطور کار درست رو بکنه. + +ولی اگه بخوای بدون FastAPI از `async` / `await` استفاده کنی، اینم ممکنه. + +### کد ناهم‌زمان خودت رو بنویس + +Starlette (و **FastAPI**) بر پایه AnyIO هستن، که باعث می‌شه با کتابخونه استاندارد پایتون asyncio و Trio سازگار باشه. + +به‌خصوص، می‌تونی مستقیماً از AnyIO برای موارد استفاده پیشرفته هم‌زمانی که نیاز به الگوهای پیچیده‌تر توی کد خودت دارن استفاده کنی. + +و حتی اگه از FastAPI استفاده نکنی، می‌تونی برنامه‌های ناهم‌زمان خودت رو با AnyIO بنویسی تا خیلی سازگار باشه و فوایدش رو بگیری (مثل *هم‌زمانی ساختاریافته*). + +من یه کتابخونه دیگه روی AnyIO ساختم، یه لایه نازک روش، تا یه کم annotationهای نوع رو بهتر کنم و **تکمیل خودکار** بهتر، **خطاهای درون‌خطی** و غیره بگیرم. یه مقدمه و آموزش ساده هم داره که بهت کمک می‌کنه **بفهمی** و **کد ناهم‌زمان خودت رو بنویسی**: Asyncer. اگه بخوای **کد ناهم‌زمان رو با کد معمولی** (بلاک‌کننده/هم‌زمان) ترکیب کنی خیلی به‌دردت می‌خوره. + +### شکل‌های دیگه کد ناهم‌زمان + +این سبک استفاده از `async` و `await` توی زبون نسبتاً جدیده. + +ولی کار با کد ناهم‌زمان رو خیلی ساده‌تر می‌کنه. + +همین سینتکس (یا تقریباً یکسان) اخیراً توی نسخه‌های مدرن جاوااسکریپت (توی مرورگر و NodeJS) هم اضافه شده. + +ولی قبل از اون، مدیریت کد ناهم‌زمان خیلی پیچیده‌تر و سخت‌تر بود. + +توی نسخه‌های قبلی پایتون، می‌تونستی از نخ‌ها یا Gevent استفاده کنی. ولی کد خیلی پیچیده‌تر می‌شه برای فهمیدن، دیباگ کردن و فکر کردن بهش. + +توی نسخه‌های قبلی NodeJS / جاوااسکریپت مرورگر، از "کال‌بک‌ها" استفاده می‌کردی. که می‌رسید به جهان کال‌بک‌ها. + +## کروتین‌ها + +**کروتین** فقط یه اصطلاح خیلی شیک برای چیزیه که یه تابع `async def` برمی‌گردونه. پایتون می‌دونه که این یه چیزی مثل تابع هست، می‌تونه شروع بشه و یه جایی تموم بشه، ولی ممکنه داخلش هم موقف ⏸ بشه، هر وقت یه `await` توش باشه. + +ولی همه این قابلیت استفاده از کد ناهم‌زمان با `async` و `await` خیلی وقتا خلاصه می‌شه به استفاده از "کروتین‌ها". این قابل مقایسه با ویژگی اصلی Go، یعنی "Goroutineها" هست. + +## نتیجه‌گیری + +بیاید همون جمله از بالا رو ببینیم: + +> نسخه‌های مدرن پایتون از **"کد ناهم‌زمان"** با چیزی که بهش **"کروتین"** می‌گن پشتیبانی می‌کنن، با سینتکس **`async` و `await`**. + +حالا باید بیشتر برات معنی بده. ✨ + +همه اینا چیزیه که به FastAPI (از طریق Starlette) قدرت می‌ده و باعث می‌شه عملکرد چشمگیری داشته باشه. + +## جزئیات خیلی فنی + +/// warning + +احتمالاً می‌تونی اینو رد کنی. + +اینا جزئیات خیلی فنی از نحوه کار **FastAPI** زیر پوسته‌ست. + +اگه یه کم دانش فنی (کروتین‌ها، نخ‌ها، بلاک کردن و غیره) داری و کنجکاوی که FastAPI چطور `async def` رو در مقابل `def` معمولی مدیریت می‌کنه، ادامه بده. + +/// + +### توابع عملیات مسیر + +وقتی یه *تابع عملیات مسیر* رو با `def` معمولی به جای `async def` تعریف می‌کنی، توی یه استخر نخ خارجی اجرا می‌شه که بعدش منتظرش می‌مونن، به جای اینکه مستقیم صداش کنن (چون سرور رو بلاک می‌کنه). + +اگه از یه فریم‌ورک ناهم‌زمان دیگه میای که به روش بالا کار نمی‌کنه و عادت داری *توابع عملیات مسیر* ساده فقط محاسباتی رو با `def` معمولی برای یه سود کوچیک عملکرد (حدود 100 نانوثانیه) تعریف کنی، توجه کن که توی **FastAPI** اثرش کاملاً برعکسه. توی این موارد، بهتره از `async def` استفاده کنی مگه اینکه *توابع عملیات مسیرت* کدی داشته باشن که عملیات I/O بلاک‌کننده انجام بده. + +با این حال، توی هر دو موقعیت، احتمالش زیاده که **FastAPI** هنوز [سریع‌تر](index.md#performance){.internal-link target=_blank} از فریم‌ورک قبلی‌ات باشه (یا حداقل قابل مقایسه باهاش). + +### وابستگی‌ها + +همین برای [وابستگی‌ها](tutorial/dependencies/index.md){.internal-link target=_blank} هم صدق می‌کنه. اگه یه وابستگی یه تابع `def` معمولی به جای `async def` باشه، توی استخر نخ خارجی اجرا می‌شه. + +### زیروابستگی‌ها + +می‌تونی چند تا وابستگی و [زیروابستگی](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} داشته باشی که همدیگه رو نیاز دارن (به‌عنوان پارامترهای تعریف تابع)، بعضی‌هاشون ممکنه با `async def` ساخته بشن و بعضی‌ها با `def` معمولی. بازم کار می‌کنه، و اونایی که با `def` معمولی ساخته شدن توی یه نخ خارجی (از استخر نخ) صدا زده می‌شن به جای اینکه "منتظرشون" بمونن. + +### توابع کاربردی دیگه + +هر تابع کاربردی دیگه‌ای که مستقیم خودت صداش می‌کنی می‌تونه با `def` معمولی یا `async def` ساخته بشه و FastAPI رو نحوه صدازدنش تأثیر نمی‌ذاره. + +این برخلاف توابعی هست که FastAPI برات صداشون می‌کنه: *توابع عملیات مسیر* و وابستگی‌ها. + +اگه تابع کاربردیت یه تابع معمولی با `def` باشه، مستقیم صداش می‌کنن (همون‌طور که توی کدت نوشتی)، نه توی استخر نخ، اگه تابع با `async def` ساخته شده باشه، باید وقتی توی کدت صداش می‌کنی `await`ش کنی. + +--- + +دوباره، اینا جزئیات خیلی فنی هستن که احتمالاً اگه دنبالشون اومده باشی برات مفید باشن. + +وگرنه، با راهنمایی‌های بخش بالا باید خوب باشی: عجله داری؟. From 4ec2c0bb5b17e23916c37d891f22f71715cc284a Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 21 Jul 2025 09:43:19 +0000 Subject: [PATCH 261/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d33e76fce..bc15e23d4 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Bangali translation for `docs/bn/about/index.md`. PR [#13882](https://github.com/fastapi/fastapi/pull/13882) by [@sajjadrahman56](https://github.com/sajjadrahman56). ### Internal From cf0c3cf2c43ef415698f3e5a083ce94386915668 Mon Sep 17 00:00:00 2001 From: Edmilson Monteiro Rodrigues Neto Date: Mon, 21 Jul 2025 10:57:31 +0100 Subject: [PATCH 262/455] =?UTF-8?q?=F0=9F=8C=90=20Update=20Portuguese=20Tr?= =?UTF-8?q?anslation=20for=20`docs/pt/docs/project-generation.md`=20(#1387?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: update pt-docs project_generation.md * fix: fix typo --- docs/pt/docs/project-generation.md | 102 +++++++---------------------- 1 file changed, 23 insertions(+), 79 deletions(-) diff --git a/docs/pt/docs/project-generation.md b/docs/pt/docs/project-generation.md index e5c935fd2..e337ad762 100644 --- a/docs/pt/docs/project-generation.md +++ b/docs/pt/docs/project-generation.md @@ -1,84 +1,28 @@ -# Geração de Projetos - Modelo +# Full Stack FastAPI Template -Você pode usar um gerador de projetos para começar, por já incluir configurações iniciais, segurança, banco de dados e os primeiros _endpoints_ API já feitos para você. +_Templates_, embora tipicamente venham com alguma configuração específica, são desenhados para serem flexíveis e customizáveis. Isso permite que você os modifique e adapte para as especificações do seu projeto, fazendo-os um excelente ponto de partida. 🏁 -Um gerador de projetos sempre terá uma pré-configuração que você pode atualizar e adaptar para suas próprias necessidades, mas pode ser um bom ponto de partida para seu projeto. +Você pode usar esse _template_ para começar, já que ele inclui várias configurações iniciais, segurança, banco de dados, e alguns _endpoints_ de API já feitos para você. -## Full Stack FastAPI PostgreSQL +Repositório GitHub: Full Stack FastAPI Template -GitHub: https://github.com/tiangolo/full-stack-fastapi-postgresql +## Full Stack FastAPI Template - Pilha de Tecnologias e Recursos -### Full Stack FastAPI PostgreSQL - Recursos - -* Integração completa **Docker**. -* Modo de implantação Docker Swarm. -* Integração e otimização **Docker Compose** para desenvolvimento local. -* **Pronto para Produção** com servidor _web_ usando Uvicorn e Gunicorn. -* _Backend_ **FastAPI** Python: - * **Rápido**: Alta performance, no nível de **NodeJS** e **Go** (graças ao Starlette e Pydantic). - * **Intuitivo**: Ótimo suporte de editor. _Auto-Complete_ em todo lugar. Menos tempo _debugando_. - * **Fácil**: Projetado para ser fácil de usar e aprender. Menos tempo lendo documentações. - * **Curto**: Minimize duplicação de código. Múltiplos recursos para cada declaração de parâmetro. - * **Robusto**: Tenha código pronto para produção. Com documentação interativa automática. - * **Baseado em Padrões**: Baseado em (e completamente compatível com) padrões abertos para APIs: OpenAPI e JSON Schema. - * **Muitos outros recursos** incluindo validação automática, serialização, documentação interativa, autenticação com _tokens_ OAuth2 JWT etc. -* **Senha segura** _hashing_ por padrão. -* Autenticação **Token JWT**. -* Modelos **SQLAlchemy** (independente de extensões Flask, para que eles possam ser usados com _workers_ Celery diretamente). -* Modelos básicos para usuários (modifique e remova conforme suas necessidades). -* Migrações **Alembic**. -* **CORS** (_Cross Origin Resource Sharing_ - Compartilhamento de Recursos Entre Origens). -* _Worker_ **Celery** que pode importar e usar modelos e códigos do resto do _backend_ seletivamente. -* Testes _backend_ _REST_ baseados no **Pytest**, integrados com Docker, então você pode testar a interação completa da API, independente do banco de dados. Como roda no Docker, ele pode construir um novo repositório de dados do zero toda vez (assim você pode usar ElasticSearch, MongoDB, CouchDB, ou o que quiser, e apenas testar que a API esteja funcionando). -* Fácil integração com Python através dos **Kernels Jupyter** para desenvolvimento remoto ou no Docker com extensões como Atom Hydrogen ou Visual Studio Code Jupyter. -* _Frontend_ **Vue**: - * Gerado com Vue CLI. - * Controle de **Autenticação JWT**. - * Visualização de _login_. - * Após o _login_, visualização do painel de controle principal. - * Painel de controle principal com criação e edição de usuário. - * Edição do próprio usuário. - * **Vuex**. - * **Vue-router**. - * **Vuetify** para belos componentes _material design_. - * **TypeScript**. - * Servidor Docker baseado em **Nginx** (configurado para rodar "lindamente" com Vue-router). - * Construção multi-estágio Docker, então você não precisa salvar ou _commitar_ código compilado. - * Testes _frontend_ rodados na hora da construção (pode ser desabilitado também). - * Feito tão modular quanto possível, então ele funciona fora da caixa, mas você pode gerar novamente com Vue CLI ou criar conforme você queira, e reutilizar o que quiser. -* **PGAdmin** para banco de dados PostgreSQL, você pode modificar para usar PHPMyAdmin e MySQL facilmente. -* **Flower** para monitoração de tarefas Celery. -* Balanceamento de carga entre _frontend_ e _backend_ com **Traefik**, então você pode ter ambos sob o mesmo domínio, separados por rota, mas servidos por diferentes containers. -* Integração Traefik, incluindo geração automática de certificados **HTTPS** Let's Encrypt. -* GitLab **CI** (integração contínua), incluindo testes _frontend_ e _backend_. - -## Full Stack FastAPI Couchbase - -GitHub: https://github.com/tiangolo/full-stack-fastapi-couchbase - -⚠️ **WARNING** ⚠️ - -Se você está iniciando um novo projeto do zero, verifique as alternativas aqui. - -Por exemplo, o gerador de projetos Full Stack FastAPI PostgreSQL pode ser uma alternativa melhor, como ele é ativamente mantido e utilizado. E ele inclui todos os novos recursos e melhorias. - -Você ainda é livre para utilizar o gerador baseado em Couchbase se quiser, ele provavelmente ainda funciona bem, e você já tem um projeto gerado com ele que roda bem também (e você provavelmente já atualizou ele para encaixar nas suas necessidades). - -Você pode ler mais sobre nas documentaçãoes do repositório. - -## Full Stack FastAPI MongoDB - -...pode demorar, dependendo do meu tempo disponível e outros fatores. 😅 🎉 - -## Modelos de Aprendizado de Máquina com spaCy e FastAPI - -GitHub: https://github.com/microsoft/cookiecutter-spacy-fastapi - -### Modelos de Aprendizado de Máquina com spaCy e FastAPI - Recursos - -* Integração com modelo NER **spaCy**. -* Formato de requisição **Busca Cognitiva Azure** acoplado. -* Servidor Python _web_ **Pronto para Produção** usando Uvicorn e Gunicorn. -* Implantação **Azure DevOps** Kubernetes (AKS) CI/CD acoplada. -* **Multilingual** facilmente escolhido como uma das linguagens spaCy acopladas durante a configuração do projeto. -* **Facilmente extensível** para outros modelos de _frameworks_ (Pytorch, Tensorflow), não apenas spaCy. +- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) para a API do backend em Python. + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para as interações do Python com bancos de dados SQL (ORM). + - 🔍 [Pydantic](https://docs.pydantic.dev), usado pelo FastAPI, para validação de dados e gerenciamento de configurações. + - 💾 [PostgreSQL](https://www.postgresql.org) como banco de dados SQL. +- 🚀 [React](https://react.dev) para o frontend. + - 💃 Usando TypeScript, hooks, [Vite](https://vitejs.dev), e outras partes de uma _stack_ frontend moderna. + - 🎨 [Chakra UI](https://chakra-ui.com) para os componentes de frontend. + - 🤖 Um cliente frontend automaticamente gerado. + - 🧪 [Playwright](https://playwright.dev) para testes Ponta-a-Ponta. + - 🦇 Suporte para modo escuro. +- 🐋 [Docker Compose](https://www.docker.com) para desenvolvimento e produção. +- 🔒 _Hash_ seguro de senhas por padrão. +- 🔑 Autenticação por token JWT. +- 📫 Recuperação de senhas baseada em email. +- ✅ Testes com [Pytest](https://pytest.org). +- 📞 [Traefik](https://traefik.io) como proxy reverso / balanceador de carga. +- 🚢 Instruções de _deployment_ usando Docker Compose, incluindo como configurar um proxy frontend com Traefik para gerenciar automaticamente certificados HTTPS. +- 🏭 CI (Integração Contínua) e CD (_Deploy_ Contínuo) baseado em GitHub Actions. From d9e2aa8678c02e30613e246dc74e667cc0c27207 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 21 Jul 2025 09:57:51 +0000 Subject: [PATCH 263/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bc15e23d4..f3a88b4f3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). * 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Bangali translation for `docs/bn/about/index.md`. PR [#13882](https://github.com/fastapi/fastapi/pull/13882) by [@sajjadrahman56](https://github.com/sajjadrahman56). From c8f330314ee6632edf13d103d7f3f9ae2f8d42ce Mon Sep 17 00:00:00 2001 From: Mohammad <116789737+Mohammad222PR@users.noreply.github.com> Date: Mon, 21 Jul 2025 15:50:57 +0330 Subject: [PATCH 264/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Persian=20translat?= =?UTF-8?q?ion=20for=20`docs/fa/docs/python-types.md`=20(#13524)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🌐 Add Persian translation for docs/fa/docs/python-types.md * 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/fa/docs/python-types.md | 578 +++++++++++++++++++++++++++++++++++ 1 file changed, 578 insertions(+) create mode 100644 docs/fa/docs/python-types.md diff --git a/docs/fa/docs/python-types.md b/docs/fa/docs/python-types.md new file mode 100644 index 000000000..c428acbf7 --- /dev/null +++ b/docs/fa/docs/python-types.md @@ -0,0 +1,578 @@ +# مقدمه‌ای بر انواع نوع در پایتون + +پایتون از "نوع‌نما"های اختیاری (که بهشون "type hints" یا "type annotations" هم می‌گن) پشتیبانی می‌کنه. + +این **"نوع‌نماها"** یا annotationها یه سینتکس خاص هستن که بهت اجازه می‌دن نوع یه متغیر رو مشخص کنی. + +با مشخص کردن نوع متغیرها، ویرایشگرها و ابزارها می‌تونن پشتیبانی بهتری بهت بدن. + +این فقط یه **آموزش سریع / یادآوری** در مورد نوع‌نماهای پایتونه. فقط حداقل چیزایی که برای استفاده ازشون با **FastAPI** لازمه رو پوشش می‌ده... که در واقع خیلی کمه. + +**FastAPI** کاملاً بر پایه این نوع‌نماهاست و این بهش کلی مزیت و فایده می‌ده. + +ولی حتی اگه هیچ‌وقت از **FastAPI** استفاده نکنی، بازم یادگیری یه کم در موردشون به نفعته. + +/// note + +اگه حرفه‌ای پایتونی و همه‌چیز رو در مورد نوع‌نماها می‌دونی، برو سراغ فصل بعدی. + +/// + +## انگیزه + +بیاید با یه مثال ساده شروع کنیم: + +{* ../../docs_src/python_types/tutorial001.py *} + +وقتی این برنامه رو اجرا کنی، خروجی اینه: + +``` +John Doe +``` + +این تابع این کارا رو می‌کنه: + +* یه `first_name` و `last_name` می‌گیره. +* حرف اول هر کدوم رو با `title()` بزرگ می‌کنه. +* ترکیبشون می‌کنه با یه فاصله وسطشون. + +{* ../../docs_src/python_types/tutorial001.py hl[2] *} + +### ویرایشش کن + +این یه برنامه خیلی ساده‌ست. + +ولی حالا تصور کن داری از صفر می‌نویسیش. + +یه جایی شروع کردی به تعریف تابع، پارامترهات آماده‌ست... + +ولی بعد باید "اون متدی که حرف اول رو بزرگ می‌کنه" رو صدا کنی. + +آیا اسمش `upper` بود؟ یا `uppercase`؟ شاید `first_uppercase`؟ یا `capitalize`؟ + +بعد، با دوست قدیمی برنامه‌نویسا، تکمیل خودکار ویرایشگر، امتحان می‌کنی. + +پارامتر اول تابع، `first_name` رو تایپ می‌کنی، بعد یه نقطه (`.`) می‌ذاری و `Ctrl+Space` رو می‌زنی تا تکمیل خودکار بیاد. + +ولی متأسفانه، چیز مفیدی نمی‌گیری: + + + +### نوع اضافه کن + +بیا فقط یه خط از نسخه قبلی رو تغییر بدیم. + +دقیقاً این بخش، پارامترهای تابع رو، از: + +```Python + first_name, last_name +``` + +به: + +```Python + first_name: str, last_name: str +``` + +عوض می‌کنیم. + +همینه. + +اینا همون "نوع‌نماها" هستن: + +{* ../../docs_src/python_types/tutorial002.py hl[1] *} + +این با تعریف مقدار پیش‌فرض فرق داره، مثل: + +```Python + first_name="john", last_name="doe" +``` + +یه چیز متفاوته. + +ما از دونقطه (`:`) استفاده می‌کنیم، نه علامت مساوی (`=`)‌. + +و اضافه کردن نوع‌نماها معمولاً چیزی که اتفاق می‌افته رو از چیزی که بدون اونا می‌افتاد تغییر نمی‌ده. + +ولی حالا، دوباره تصور کن وسط ساختن اون تابع هستی، ولی این بار با نوع‌نماها. + +توی همون نقطه، سعی می‌کنی تکمیل خودکار رو با `Ctrl+Space` فعال کنی و اینو می‌بینی: + + + +با این، می‌تونی اسکرول کنی، گزینه‌ها رو ببینی، تا وقتی که اون چیزی که "به نظرت آشنا میاد" رو پیدا کنی: + + + +## انگیزه بیشتر + +این تابع رو چک کن، الان نوع‌نما داره: + +{* ../../docs_src/python_types/tutorial003.py hl[1] *} + +چون ویرایشگر نوع متغیرها رو می‌دونه، فقط تکمیل خودکار نمی‌گیری، بلکه چک خطاها هم داری: + + + +حالا می‌دونی که باید درستش کنی، `age` رو با `str(age)` به یه رشته تبدیل کنی: + +{* ../../docs_src/python_types/tutorial004.py hl[2] *} + +## تعریف نوع‌ها + +تازه اصلی‌ترین جا برای تعریف نوع‌نماها رو دیدی. به‌عنوان پارامترهای تابع. + +این هم اصلی‌ترین جاییه که با **FastAPI** ازشون استفاده می‌کنی. + +### نوع‌های ساده + +می‌تونی همه نوع‌های استاندارد پایتون رو تعریف کنی، نه فقط `str`. + +مثلاً می‌تونی از اینا استفاده کنی: + +* `int` +* `float` +* `bool` +* `bytes` + +{* ../../docs_src/python_types/tutorial005.py hl[1] *} + +### نوع‌های عمومی با پارامترهای نوع + +یه سری ساختار داده هستن که می‌تونن مقدارهای دیگه رو نگه دارن، مثل `dict`، `list`، `set` و `tuple`. و مقدارهای داخلیشون هم می‌تونن نوع خودشون رو داشته باشن. + +به این نوع‌ها که نوع‌های داخلی دارن می‌گن "**عمومی**" یا "generic". و می‌شه اونا رو تعریف کرد، حتی با نوع‌های داخلیشون. + +برای تعریف این نوع‌ها و نوع‌های داخلیشون، می‌تونی از ماژول استاندارد پایتون `typing` استفاده کنی. این ماژول مخصوص پشتیبانی از نوع‌نماهاست. + +#### نسخه‌های جدیدتر پایتون + +سینتکس با استفاده از `typing` با همه نسخه‌ها، از پایتون 3.6 تا جدیدترین‌ها، از جمله پایتون 3.9، 3.10 و غیره **سازگاره**. + +با پیشرفت پایتون، **نسخه‌های جدیدتر** پشتیبانی بهتری برای این نوع‌نماها دارن و توی خیلی موارد حتی لازم نیست ماژول `typing` رو وارد کنی و ازش برای تعریف نوع‌نماها استفاده کنی. + +اگه بتونی برای پروژه‌ات از یه نسخه جدیدتر پایتون استفاده کنی، می‌تونی از این سادگی اضافه بهره ببری. + +توی همه مستندات، مثال‌هایی هستن که با هر نسخه پایتون سازگارن (وقتی تفاوتی هست). + +مثلاً "**Python 3.6+**" یعنی با پایتون 3.6 یا بالاتر (مثل 3.7، 3.8، 3.9، 3.10 و غیره) سازگاره. و "**Python 3.9+**" یعنی با پایتون 3.9 یا بالاتر (مثل 3.10 و غیره) سازگاره. + +اگه بتونی از **جدیدترین نسخه‌های پایتون** استفاده کنی، از مثال‌های نسخه آخر استفاده کن، چون اونا **بهترین و ساده‌ترین سینتکس** رو دارن، مثلاً "**Python 3.10+**". + +#### لیست + +مثلاً، بیایم یه متغیر تعریف کنیم که یه `list` از `str` باشه. + +//// tab | Python 3.9+ + +متغیر رو با همون سینتکس دونقطه (`:`) تعریف کن. + +به‌عنوان نوع، `list` رو بذار. + +چون لیست یه نوعه که نوع‌های داخلی داره، اونا رو توی کروشه‌ها می‌ذاری: + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial006_py39.py!} +``` + +//// + +//// tab | Python 3.8+ + +از `typing`، `List` رو (با `L` بزرگ) وارد کن: + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial006.py!} +``` + +متغیر رو با همون سینتکس دونقطه (`:`) تعریف کن. + +به‌عنوان نوع، `List` رو که از `typing` وارد کردی بذار. + +چون لیست یه نوعه که نوع‌های داخلی داره، اونا رو توی کروشه‌ها می‌ذاری: + +```Python hl_lines="4" +{!> ../../docs_src/python_types/tutorial006.py!} +``` + +//// + +/// info + +اون نوع‌های داخلی توی کروشه‌ها بهشون "پارامترهای نوع" می‌گن. + +توی این مورد، `str` پارامتر نوعیه که به `List` (یا `list` توی پایتون 3.9 و بالاتر) پاس داده شده. + +/// + +یعنی: "متغیر `items` یه `list` هست، و هر کدوم از آیتم‌های این لیست یه `str` هستن". + +/// tip + +اگه از پایتون 3.9 یا بالاتر استفاده می‌کنی، لازم نیست `List` رو از `typing` وارد کنی، می‌تونی همون نوع معمولی `list` رو به جاش استفاده کنی. + +/// + +با این کار، ویرایشگرت حتی وقتی داری آیتم‌های لیست رو پردازش می‌کنی بهت کمک می‌کنه: + + + +بدون نوع‌ها، رسیدن به این تقریباً غیرممکنه. + +توجه کن که متغیر `item` یکی از عناصر توی لیست `items` هست. + +و با این حال، ویرایشگر می‌دونه که یه `str` هست و براش پشتیبانی می‌ده. + +#### تاپل و ست + +برای تعریف `tuple`ها و `set`ها هم همین کار رو می‌کنی: + +//// tab | Python 3.9+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial007_py39.py!} +``` + +//// + +//// tab | Python 3.8+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial007.py!} +``` + +//// + +یعنی: + +* متغیر `items_t` یه `tuple` با 3 تا آیتمه، یه `int`، یه `int` دیگه، و یه `str`. +* متغیر `items_s` یه `set` هست، و هر کدوم از آیتم‌هاش از نوع `bytes` هستن. + +#### دیکشنری + +برای تعریف یه `dict`، 2 تا پارامتر نوع می‌دی، که با کاما از هم جدا شدن. + +پارامتر نوع اول برای کلیدهای `dict` هست. + +پارامتر نوع دوم برای مقدارهای `dict` هست: + +//// tab | Python 3.9+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008_py39.py!} +``` + +//// + +//// tab | Python 3.8+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial008.py!} +``` + +//// + +یعنی: + +* متغیر `prices` یه `dict` هست: + * کلیدهای این `dict` از نوع `str` هستن (مثلاً اسم هر آیتم). + * مقدارهای این `dict` از نوع `float` هستن (مثلاً قیمت هر آیتم). + +#### اتحادیه + +می‌تونی تعریف کنی که یه متغیر می‌تونه هر کدوم از **چند تا نوع** باشه، مثلاً یه `int` یا یه `str`. + +توی پایتون 3.6 و بالاتر (از جمله پایتون 3.10) می‌تونی از نوع `Union` توی `typing` استفاده کنی و نوع‌های ممکن رو توی کروشه‌ها بذاری. + +توی پایتون 3.10 یه **سینتکس جدید** هم هست که می‌تونی نوع‌های ممکن رو با یه خط عمودی (`|`) جدا کنی. + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` + +//// + +//// tab | Python 3.8+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial008b.py!} +``` + +//// + +توی هر دو حالت یعنی `item` می‌تونه یه `int` یا یه `str` باشه. + +#### شاید `None` + +می‌تونی تعریف کنی که یه مقدار می‌تونه یه نوع باشه، مثلاً `str`، ولی می‌تونه `None` هم باشه. + +توی پایتون 3.6 و بالاتر (از جمله پایتون 3.10) می‌تونی با وارد کردن و استفاده از `Optional` از ماژول `typing` اینو تعریف کنی. + +```Python hl_lines="1 4" +{!../../docs_src/python_types/tutorial009.py!} +``` + +استفاده از `Optional[str]` به جای فقط `str` به ویرایشگر کمک می‌کنه خطاهایی که ممکنه فکر کنی یه مقدار همیشه `str` هست رو پیدا کنه، در حالی که می‌تونه `None` هم باشه. + +`Optional[Something]` در واقع میان‌بر برای `Union[Something, None]` هست، این دو تا معادلن. + +یعنی توی پایتون 3.10، می‌تونی از `Something | None` استفاده کنی: + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +//// tab | Python 3.8+ + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009.py!} +``` + +//// + +//// tab | Python 3.8+ جایگزین + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial009b.py!} +``` + +//// + +#### استفاده از `Union` یا `Optional` + +اگه از نسخه پایتون زیر 3.10 استفاده می‌کنی، یه نکته از دید خیلی **شخصی** خودم: + +* 🚨 از `Optional[SomeType]` استفاده نکن +* به جاش ✨ **از `Union[SomeType, None]` استفاده کن** ✨. + +هر دو معادلن و زیر پوسته یکی‌ان، ولی من `Union` رو به `Optional` ترجیح می‌دم چون کلمه "**اختیاری**" انگار暗示 می‌کنه که مقدار اختیاریه، در حالی که در واقع یعنی "می‌تونه `None` باشه"، حتی اگه اختیاری نباشه و هنوز لازم باشه. + +فکر می‌کنم `Union[SomeType, None]` واضح‌تر نشون می‌ده چی معنی می‌ده. + +فقط بحث کلمات و اسم‌هاست. ولی این کلمات می‌تونن رو طرز فکر تو و تیمت نسبت به کد تأثیر بذارن. + +به‌عنوان مثال، این تابع رو ببین: + +{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *} + +پارامتر `name` به‌عنوان `Optional[str]` تعریف شده، ولی **اختیاری نیست**، نمی‌تونی تابع رو بدون پارامتر صدا کنی: + +```Python +say_hi() # اوه نه، این خطا می‌ده! 😱 +``` + +پارامتر `name` **هنوز لازمه** (نه *اختیاری*) چون مقدار پیش‌فرض نداره. با این حال، `name` مقدار `None` رو قبول می‌کنه: + +```Python +say_hi(name=None) # این کار می‌کنه، None معتبره 🎉 +``` + +خبر خوب اینه که وقتی رو پایتون 3.10 باشی، لازم نیست نگران این باشی، چون می‌تونی به‌سادگی از `|` برای تعریف اتحادیه نوع‌ها استفاده کنی: + +{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} + +اون موقع دیگه لازم نیست نگران اسم‌هایی مثل `Optional` و `Union` باشی. 😎 + +#### نوع‌های عمومی + +این نوع‌هایی که پارامترهای نوع رو توی کروشه‌ها می‌گیرن بهشون **نوع‌های عمومی** یا **Generics** می‌گن، مثلاً: + +//// tab | Python 3.10+ + +می‌تونی از همون نوع‌های داخلی به‌عنوان نوع‌های عمومی استفاده کنی (با کروشه‌ها و نوع‌ها داخلشون): + +* `list` +* `tuple` +* `set` +* `dict` + +و همون‌طور که توی پایتون 3.8 بود، از ماژول `typing`: + +* `Union` +* `Optional` (همون‌طور که توی پایتون 3.8 بود) +* ...و بقیه. + +توی پایتون 3.10، به‌عنوان جایگزین برای استفاده از نوع‌های عمومی `Union` و `Optional`، می‌تونی از خط عمودی (`|`) برای تعریف اتحادیه نوع‌ها استفاده کنی، که خیلی بهتر و ساده‌تره. + +//// + +//// tab | Python 3.9+ + +می‌تونی از همون نوع‌های داخلی به‌عنوان نوع‌های عمومی استفاده کنی (با کروشه‌ها و نوع‌ها داخلشون): + +* `list` +* `tuple` +* `set` +* `dict` + +و همون‌طور که توی پایتون 3.8 بود، از ماژول `typing`: + +* `Union` +* `Optional` +* ...و بقیه. + +//// + +//// tab | Python 3.8+ + +* `List` +* `Tuple` +* `Set` +* `Dict` +* `Union` +* `Optional` +* ...و بقیه. + +//// + +### کلاس‌ها به‌عنوان نوع + +می‌تونی یه کلاس رو هم به‌عنوان نوع یه متغیر تعریف کنی. + +فرض کن یه کلاس `Person` داری، با یه نام: + +{* ../../docs_src/python_types/tutorial010.py hl[1:3] *} + +بعد می‌تونی یه متغیر رو از نوع `Person` تعریف کنی: + +{* ../../docs_src/python_types/tutorial010.py hl[6] *} + +و بعد، دوباره، همه پشتیبانی ویرایشگر رو داری: + + + +توجه کن که این یعنی "`one_person` یه **نمونه** از کلاس `Person` هست". + +یعنی "`one_person` خود **کلاس** به اسم `Person` نیست". + +## مدل‌های Pydantic + +Pydantic یه کتابخونه پایتونه برای اعتبارسنجی داده‌ها. + +"شکل" داده‌ها رو به‌عنوان کلاس‌هایی با ویژگی‌ها تعریف می‌کنی. + +و هر ویژگی یه نوع داره. + +بعد یه نمونه از اون کلاس رو با یه سری مقدار می‌سازی و اون مقدارها رو اعتبارسنجی می‌کنه، به نوع مناسب تبدیلشون می‌کنه (اگه لازم باشه) و یه شیء با همه داده‌ها بهت می‌ده. + +و با اون شیء نهایی همه پشتیبانی ویرایشگر رو می‌گیری. + +یه مثال از مستندات رسمی Pydantic: + +//// tab | Python 3.10+ + +```Python +{!> ../../docs_src/python_types/tutorial011_py310.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python +{!> ../../docs_src/python_types/tutorial011_py39.py!} +``` + +//// + +//// tab | Python 3.8+ + +```Python +{!> ../../docs_src/python_types/tutorial011.py!} +``` + +//// + +/// info + +برای اطلاعات بیشتر در مورد Pydantic، مستنداتش رو چک کن. + +/// + +**FastAPI** کاملاً بر پایه Pydantic هست. + +توی [آموزش - راهنمای کاربر](tutorial/index.md){.internal-link target=_blank} خیلی بیشتر از اینا رو توی عمل می‌بینی. + +/// tip + +Pydantic یه رفتار خاص داره وقتی از `Optional` یا `Union[Something, None]` بدون مقدار پیش‌فرض استفاده می‌کنی، می‌تونی توی مستندات Pydantic در مورد فیلدهای اختیاری لازم بیشتر بخونی. + +/// + +## نوع‌نماها با Annotationهای متادیتا + +پایتون یه قابلیت هم داره که بهت اجازه می‌ده **متادیتا اضافی** رو توی این نوع‌نماها بذاری با استفاده از `Annotated`. + +//// tab | Python 3.9+ + +توی پایتون 3.9، `Annotated` بخشی از کتابخونه استاندارده، پس می‌تونی از `typing` واردش کنی. + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial013_py39.py!} +``` + +//// + +//// tab | Python 3.8+ + +توی نسخه‌های زیر پایتون 3.9، `Annotated` رو از `typing_extensions` وارد می‌کنی. + +با **FastAPI** از قبل نصب شده. + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial013.py!} +``` + +//// + +خود پایتون با این `Annotated` کاری نمی‌کنه. و برای ویرایشگرها و ابزارهای دیگه، نوع هنوز `str` هست. + +ولی می‌تونی از این فضا توی `Annotated` استفاده کنی تا به **FastAPI** متادیتای اضافی در مورد اینکه چطور می‌خوای برنامه‌ات رفتار کنه بدی. + +نکته مهم اینه که **اولین *پارامتر نوع*** که به `Annotated` می‌دی، **نوع واقعی** هست. بقیش فقط متادیتا برای ابزارهای دیگه‌ست. + +الان فقط باید بدونی که `Annotated` وجود داره، و اینکه پایتون استاندارده. 😎 + +بعداً می‌بینی که چقدر **قوی** می‌تونه باشه. + +/// tip + +اینکه این **پایتون استاندارده** یعنی هنوز **بهترین تجربه توسعه‌دهنده** رو توی ویرایشگرت، با ابزارهایی که برای تحلیل و بازسازی کدت استفاده می‌کنی و غیره می‌گیری. ✨ + +و همین‌طور کدت با خیلی از ابزارها و کتابخونه‌های دیگه پایتون خیلی سازگار می‌مونه. 🚀 + +/// + +## نوع‌نماها توی **FastAPI** + +**FastAPI** از این نوع‌نماها استفاده می‌کنه تا چند تا کار بکنه. + +با **FastAPI** پارامترها رو با نوع‌نماها تعریف می‌کنی و اینا رو می‌گیری: + +* **پشتیبانی ویرایشگر**. +* **چک نوع‌ها**. + +...و **FastAPI** از همون تعریف‌ها برای اینا استفاده می‌کنه: + +* **تعریف نیازها**: از پارامترهای مسیر درخواست، پارامترهای کوئری، هدرها، بدنه‌ها، وابستگی‌ها و غیره. +* **تبدیل داده**: از درخواست به نوع مورد نیاز. +* **اعتبارسنجی داده**: که از هر درخواست میاد: + * تولید **خطاهای خودکار** که به کلاینت برمی‌گرده وقتی داده نامعتبره. +* **مستندسازی** API با استفاده از OpenAPI: + * که بعدش توسط رابط‌های کاربری مستندات تعاملی خودکار استفاده می‌شه. + +اینا شاید همه‌ش انتزاعی به نظر بیاد. نگران نباش. همه اینا رو توی عمل توی [آموزش - راهنمای کاربر](tutorial/index.md){.internal-link target=_blank} می‌بینی. + +نکته مهم اینه که با استفاده از نوع‌های استاندارد پایتون، توی یه جا (به جای اضافه کردن کلاس‌های بیشتر، دکوراتورها و غیره)، **FastAPI** کلی از کار رو برات انجام می‌ده. + +/// info + +اگه همه آموزش رو گذروندی و برگشتی که بیشتر در مورد نوع‌ها ببینی، یه منبع خوب "تقلب‌نامه" از `mypy` هست. + +/// From 6bc29cc5ba2662cff6662a0642784530f78103f9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 21 Jul 2025 12:21:22 +0000 Subject: [PATCH 265/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f3a88b4f3..83c06c013 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). * 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Bangali translation for `docs/bn/about/index.md`. PR [#13882](https://github.com/fastapi/fastapi/pull/13882) by [@sajjadrahman56](https://github.com/sajjadrahman56). From a5a4daa705fe4ee10d5c0eacdd3df84eb6973e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Wed, 23 Jul 2025 15:02:20 +0200 Subject: [PATCH 266/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20Add?= =?UTF-8?q?=20Mobb=20(#13916)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/en/data/sponsors.yml | 3 +++ docs/en/data/sponsors_badge.yml | 1 + docs/en/docs/img/sponsors/mobbai-banner.png | Bin 0 -> 3704 bytes docs/en/docs/img/sponsors/mobbai.png | Bin 0 -> 4137 bytes docs/en/overrides/main.html | 6 ++++++ 6 files changed, 11 insertions(+) create mode 100644 docs/en/docs/img/sponsors/mobbai-banner.png create mode 100644 docs/en/docs/img/sponsors/mobbai.png diff --git a/README.md b/README.md index 25a1d9179..b3eaa6b35 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index f712b6179..784fd6692 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -26,6 +26,9 @@ gold: - url: https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source title: The Gold Standard in Retail Account Linking img: https://fastapi.tiangolo.com/img/sponsors/subtotal.svg + - url: https://vibe.mobb.ai/?utm_source=Fast+APi&utm_medium=Image&utm_campaign=MVS + title: Secure Your AI-Generated Code to Unlock Dev Productivity + img: https://fastapi.tiangolo.com/img/sponsors/mobbai.png silver: - url: https://databento.com/ title: Pay as you go for market data diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index d145e7372..a8895c8ed 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -43,3 +43,4 @@ logins: - permitio - LambdaTest-Inc - dribia + - madisonredtfeldt diff --git a/docs/en/docs/img/sponsors/mobbai-banner.png b/docs/en/docs/img/sponsors/mobbai-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..1f59294abe86bc44f3b7535b50886191343bf4ac GIT binary patch literal 3704 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
+ {% endblock %} From ed48cc457f36ea1f999bdf68668966935cd9e47f Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 23 Jul 2025 13:02:50 +0000 Subject: [PATCH 267/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 83c06c013..42f9c5c2c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -16,6 +16,7 @@ hide: ### Internal +* 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo). From da508e9dce85874d654eb10472b090f573de97fe Mon Sep 17 00:00:00 2001 From: Mohammad <116789737+Mohammad222PR@users.noreply.github.com> Date: Fri, 25 Jul 2025 12:57:03 +0330 Subject: [PATCH 268/455] =?UTF-8?q?=F0=9F=8C=90=20Add=20Persian=20translat?= =?UTF-8?q?ion=20for=20`docs/fa/docs/environment-variables.md`=20(#13923)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🌐 Add Persian translation for docs/fa/docs/environment-variables.md --- docs/fa/docs/environment-variables.md | 298 ++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 docs/fa/docs/environment-variables.md diff --git a/docs/fa/docs/environment-variables.md b/docs/fa/docs/environment-variables.md new file mode 100644 index 000000000..75309ce1f --- /dev/null +++ b/docs/fa/docs/environment-variables.md @@ -0,0 +1,298 @@ +# متغیرهای محیطی + +/// tip + +اگه از قبل می‌دونی متغیرهای محیطی چی هستن و چطور ازشون استفاده می‌شه، می‌تونی این بخش رو رد کنی. + +/// + +یه متغیر محیطی (که بهش "**env var**" هم می‌گن) یه متغیریه که **خارج** از کد پایتون، توی **سیستم‌عامل** زندگی می‌کنه و می‌تونه توسط کد پایتونت (یا برنامه‌های دیگه) خونده بشه. + +متغیرهای محیطی می‌تونن برای مدیریت **تنظیمات** برنامه، به‌عنوان بخشی از **نصب** پایتون و غیره مفید باشن. + +## ساخت و استفاده از متغیرهای محیطی + +می‌تونی متغیرهای محیطی رو توی **شل (ترمینال)** **بسازی** و ازشون استفاده کنی، بدون اینکه به پایتون نیاز داشته باشی: + +//// tab | لینوکس، مک‌اواس، ویندوز بش + +
+ +```console +// می‌تونی یه متغیر محیطی به اسم MY_NAME بسازی با +$ export MY_NAME="Wade Wilson" + +// بعد می‌تونی با برنامه‌های دیگه ازش استفاده کنی، مثل +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | ویندوز پاورشل + +
+ +```console +// یه متغیر محیطی به اسم MY_NAME بساز +$ $Env:MY_NAME = "Wade Wilson" + +// با برنامه‌های دیگه ازش استفاده کن، مثل +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## خوندن متغیرهای محیطی توی پایتون + +می‌تونی متغیرهای محیطی رو **خارج** از پایتون، توی ترمینال (یا با هر روش دیگه) بسازی، و بعد توی **پایتون** اونا رو بخونی. + +مثلاً می‌تونی یه فایل `main.py` داشته باشی با: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +آرگومان دوم `os.getenv()` مقدار پیش‌فرضیه که برمی‌گردونه. + +اگه ندی، به‌صورت پیش‌فرض `None` هست، اینجا ما `"World"` رو به‌عنوان مقدار پیش‌فرض گذاشتیم. + +/// + +بعد می‌تونی اون برنامه پایتون رو صدا کنی: + +//// tab | لینوکس، مک‌اواس، ویندوز بش + +
+ +```console +// اینجا هنوز متغیر محیطی رو تنظیم نکردیم +$ python main.py + +// چون متغیر محیطی رو تنظیم نکردیم، مقدار پیش‌فرض رو می‌گیریم + +Hello World from Python + +// ولی اگه اول یه متغیر محیطی بسازیم +$ export MY_NAME="Wade Wilson" + +// و بعد دوباره برنامه رو صدا کنیم +$ python main.py + +// حالا می‌تونه متغیر محیطی رو بخونه + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | ویندوز پاورشل + +
+ +```console +// اینجا هنوز متغیر محیطی رو تنظیم نکردیم +$ python main.py + +// چون متغیر محیطی رو تنظیم نکردیم، مقدار پیش‌فرض رو می‌گیریم + +Hello World from Python + +// ولی اگه اول یه متغیر محیطی بسازیم +$ $Env:MY_NAME = "Wade Wilson" + +// و بعد دوباره برنامه رو صدا کنیم +$ python main.py + +// حالا می‌تونه متغیر محیطی رو بخونه + +Hello Wade Wilson from Python +``` + +
+ +//// + +چون متغیرهای محیطی می‌تونن خارج از کد تنظیم بشن، ولی کد می‌تونه اونا رو بخونه، و لازم نیست با بقیه فایل‌ها ذخیره (کمیتی به `git`) بشن، معمولاً برای پیکربندی یا **تنظیمات** استفاده می‌شن. + +همچنین می‌تونی یه متغیر محیطی رو فقط برای **یه اجرای خاص برنامه** بسازی، که فقط برای اون برنامه و فقط برای مدت زمان اجراش در دسترسه. + +برای این کار، درست قبل از خود برنامه، توی همون خط بسازش: + +
+ +```console +// یه متغیر محیطی MY_NAME رو توی خط برای این اجرای برنامه بساز +$ MY_NAME="Wade Wilson" python main.py + +// حالا می‌تونه متغیر محیطی رو بخونه + +Hello Wade Wilson from Python + +// متغیر محیطی بعدش دیگه وجود نداره +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +می‌تونی بیشتر در موردش توی برنامه دوازده‌فاکتوری: پیکربندی بخونی. + +/// + +## نوع‌ها و اعتبارسنجی + +این متغیرهای محیطی فقط می‌تونن **رشته‌های متنی** رو نگه دارن، چون خارج از پایتون هستن و باید با برنامه‌های دیگه و بقیه سیستم (و حتی سیستم‌عامل‌های مختلف مثل لینوکس، ویندوز، مک‌اواس) سازگار باشن. + +یعنی **هر مقداری** که توی پایتون از یه متغیر محیطی خونده می‌شه یه `str` هست، و هر تبدیل به نوع دیگه یا هر اعتبارسنجی باید توی کد انجام بشه. + +توی [راهنمای کاربر پیشرفته - تنظیمات و متغیرهای محیطی](./advanced/settings.md){.internal-link target=_blank} بیشتر در مورد استفاده از متغیرهای محیطی برای مدیریت **تنظیمات برنامه** یاد می‌گیری. + +## متغیر محیطی `PATH` + +یه متغیر محیطی **خاص** به اسم **`PATH`** وجود داره که سیستم‌عامل‌ها (لینوکس، مک‌اواس، ویندوز) ازش برای پیدا کردن برنامه‌هایی که قراره اجرا بشن استفاده می‌کنن. + +مقدار متغیر `PATH` یه رشته طولانی از پوشه‌هاست که توی لینوکس و مک‌اواس با دونقطه `:` و توی ویندوز با نقطه‌ویرگول `;` از هم جدا شدن. + +مثلاً، متغیر محیطی `PATH` می‌تونه اینجوری باشه: + +//// tab | لینوکس، مک‌اواس + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +یعنی سیستم باید دنبال برنامه‌ها توی این پوشه‌ها بگرده: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | ویندوز + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +یعنی سیستم باید دنبال برنامه‌ها توی این پوشه‌ها بگرده: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +وقتی یه **دستور** توی ترمینال تایپ می‌کنی، سیستم‌عامل **دنبال** برنامه توی **هر کدوم از این پوشه‌ها** که توی متغیر محیطی `PATH` لیست شدن می‌گرده. + +مثلاً، وقتی توی ترمینال `python` تایپ می‌کنی، سیستم‌عامل دنبال یه برنامه به اسم `python` توی **اولین پوشه** توی اون لیست می‌گرده. + +اگه پیداش کنه، **استفاده‌ش می‌کنه**. وگرنه توی **پوشه‌های بعدی** دنبالش می‌گرده. + +### نصب پایتون و به‌روزرسانی `PATH` + +وقتی پایتون رو نصب می‌کنی، ممکنه ازت بپرسن آیا می‌خوای متغیر محیطی `PATH` رو به‌روزرسانی کنی. + +//// tab | لینوکس، مک‌اواس + +فرض کن پایتون رو نصب کردی و توی یه پوشه `/opt/custompython/bin` قرار گرفته. + +اگه بگی بله برای به‌روزرسانی متغیر محیطی `PATH`، نصاب `/opt/custompython/bin` رو به متغیر محیطی `PATH` اضافه می‌کنه. + +ممکنه اینجوری بشه: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +این‌جوری، وقتی توی ترمینال `python` تایپ می‌کنی، سیستم برنامه پایتون رو توی `/opt/custompython/bin` (آخرین پوشه) پیدا می‌کنه و از اون استفاده می‌کنه. + +//// + +//// tab | ویندوز + +فرض کن پایتون رو نصب کردی و توی یه پوشه `C:\opt\custompython\bin` قرار گرفته. + +اگه بگی بله برای به‌روزرسانی متغیر محیطی `PATH`، نصاب `C:\opt\custompython\bin` رو به متغیر محیطی `PATH` اضافه می‌کنه. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +این‌جوری، وقتی توی ترمینال `python` تایپ می‌کنی، سیستم برنامه پایتون رو توی `C:\opt\custompython\bin` (آخرین پوشه) پیدا می‌کنه و از اون استفاده می‌کنه. + +//// + +پس، اگه تایپ کنی: + +
+ +```console +$ python +``` + +
+ +//// tab | لینوکس، مک‌اواس + +سیستم برنامه `python` رو توی `/opt/custompython/bin` **پیدا** می‌کنه و اجراش می‌کنه. + +تقریباً معادل اینه که تایپ کنی: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | ویندوز + +سیستم برنامه `python` رو توی `C:\opt\custompython\bin\python` **پیدا** می‌کنه و اجراش می‌کنه. + +تقریباً معادل اینه که تایپ کنی: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +این اطلاعات وقتی در مورد [محیط‌های مجازی](virtual-environments.md){.internal-link target=_blank} یاد می‌گیری به‌دردت می‌خوره. + +## نتیجه‌گیری + +با این باید یه درک پایه‌ای از **متغیرهای محیطی** و نحوه استفاده‌شون توی پایتون داشته باشی. + +می‌تونی بیشتر در موردشون توی ویکی‌پدیا برای متغیر محیطی بخونی. + +توی خیلی موارد مشخص نیست که متغیرهای محیطی چطور می‌تونن فوری مفید و کاربردی باشن. ولی توی موقعیت‌های مختلف توسعه مدام پیداشون می‌شه، پس خوبه که در موردشون بدونی. + +مثلاً، توی بخش بعدی در مورد [محیط‌های مجازی](virtual-environments.md) به این اطلاعات نیاز داری. From 4ca93aea04bf289cedb4dc0d922c97f2e99399d9 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 25 Jul 2025 09:27:24 +0000 Subject: [PATCH 269/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 42f9c5c2c..e198e9437 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). * 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR). From e4453a850d794fd211eb3741c85cf3bec320c871 Mon Sep 17 00:00:00 2001 From: Koyo Miyazaki <82708304+KoyoMiyazaki@users.noreply.github.com> Date: Sat, 26 Jul 2025 19:48:11 +0900 Subject: [PATCH 270/455] =?UTF-8?q?=F0=9F=93=9D=20Fix=20highlight=20line?= =?UTF-8?q?=20in=20`docs/ja/docs/tutorial/body.md`=20(#13927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix highlight line in docs/ja/docs/tutorial/body.md --- docs/ja/docs/tutorial/body.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index 8376959d5..1298eec7e 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -22,7 +22,7 @@ GET リクエストでボディを送信することは、仕様では未定義 ます初めに、 `pydantic` から `BaseModel` をインポートする必要があります: -{* ../../docs_src/body/tutorial001.py hl[2] *} +{* ../../docs_src/body/tutorial001.py hl[4] *} ## データモデルの作成 @@ -30,7 +30,7 @@ GET リクエストでボディを送信することは、仕様では未定義 すべての属性にpython標準の型を使用します: -{* ../../docs_src/body/tutorial001.py hl[5:9] *} +{* ../../docs_src/body/tutorial001.py hl[7:11] *} クエリパラメータの宣言と同様に、モデル属性がデフォルト値をもつとき、必須な属性ではなくなります。それ以外は必須になります。オプショナルな属性にしたい場合は `None` を使用してください。 @@ -58,7 +58,7 @@ GET リクエストでボディを送信することは、仕様では未定義 *パスオペレーション* に加えるために、パスパラメータやクエリパラメータと同じ様に宣言します: -{* ../../docs_src/body/tutorial001.py hl[16] *} +{* ../../docs_src/body/tutorial001.py hl[18] *} ...そして、作成したモデル `Item` で型を宣言します。 @@ -125,7 +125,7 @@ GET リクエストでボディを送信することは、仕様では未定義 関数内部で、モデルの全ての属性に直接アクセスできます: -{* ../../docs_src/body/tutorial002.py hl[19] *} +{* ../../docs_src/body/tutorial002.py hl[21] *} ## リクエストボディ + パスパラメータ @@ -133,7 +133,7 @@ GET リクエストでボディを送信することは、仕様では未定義 **FastAPI** はパスパラメータである関数パラメータは**パスから受け取り**、Pydanticモデルによって宣言された関数パラメータは**リクエストボディから受け取る**ということを認識します。 -{* ../../docs_src/body/tutorial003.py hl[15:16] *} +{* ../../docs_src/body/tutorial003.py hl[17:18] *} ## リクエストボディ + パスパラメータ + クエリパラメータ @@ -141,7 +141,7 @@ GET リクエストでボディを送信することは、仕様では未定義 **FastAPI** はそれぞれを認識し、適切な場所からデータを取得します。 -{* ../../docs_src/body/tutorial004.py hl[16] *} +{* ../../docs_src/body/tutorial004.py hl[18] *} 関数パラメータは以下の様に認識されます: From 106a4338db8d546f3a6bf817e237331297e7f797 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 10:48:36 +0000 Subject: [PATCH 271/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e198e9437..d5186aad3 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki). * 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). From 54c7c34b25e9c71d218f4a01095520bc2b582b24 Mon Sep 17 00:00:00 2001 From: Chih-Hsuan Yen <1937689+yan12125@users.noreply.github.com> Date: Sat, 26 Jul 2025 18:49:23 +0800 Subject: [PATCH 272/455] =?UTF-8?q?=E2=AC=86=20Update=20httpx=20requiremen?= =?UTF-8?q?t=20to=20>=3D0.23.0,<0.29.0=20(#13114)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- requirements-docs-tests.txt | 2 +- requirements-github-actions.txt | 2 +- .../test_custom_request_and_route/test_tutorial002.py | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index 71f4a7ab9..e7684a2e3 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests -httpx >=0.23.0,<0.28.0 +httpx >=0.23.0,<0.29.0 # For linting and generating docs versions ruff ==0.11.2 diff --git a/requirements-github-actions.txt b/requirements-github-actions.txt index 920aefea6..f807d06a8 100644 --- a/requirements-github-actions.txt +++ b/requirements-github-actions.txt @@ -1,6 +1,6 @@ PyGithub>=2.3.0,<3.0.0 pydantic>=2.5.3,<3.0.0 pydantic-settings>=2.1.0,<3.0.0 -httpx>=0.27.0,<0.28.0 +httpx>=0.27.0,<0.29.0 pyyaml >=5.3.1,<7.0.0 smokeshow diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py index 6f7355aaa..647f1c5dd 100644 --- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py +++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.custom_request_and_route.tutorial002 import app @@ -24,14 +24,16 @@ def test_exception_handler_body_access(): "input": {"numbers": [1, 2, 3]}, } ], - "body": '{"numbers": [1, 2, 3]}', + # httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363 + "body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'), } } ) | IsDict( # TODO: remove when deprecating Pydantic v1 { "detail": { - "body": '{"numbers": [1, 2, 3]}', + # httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363 + "body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'), "errors": [ { "loc": ["body"], From bfbed308699d6f8204411e5bbaaa084b6e779c30 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 10:49:51 +0000 Subject: [PATCH 273/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d5186aad3..c75a8b574 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Internal +* ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). * 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo). From fcdd5031e1b150952bd70ea8d1ea805d5f1014c6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 26 Jul 2025 12:51:31 +0200 Subject: [PATCH 274/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13894)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.2 → v0.12.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.2...v0.12.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 680cafce9..e461b0133 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.2 + rev: v0.12.4 hooks: - id: ruff args: From 8bfc783194bdfc2142ac716ae208c735e1862c81 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 10:51:53 +0000 Subject: [PATCH 275/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c75a8b574..d5730e247 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). * 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). From 2013336d65e1b7ac25aa3a4b130d41b6b2ac31f4 Mon Sep 17 00:00:00 2001 From: Edmilson Monteiro Rodrigues Neto Date: Sat, 26 Jul 2025 12:16:39 +0100 Subject: [PATCH 276/455] =?UTF-8?q?=20=F0=9F=8C=90=20Update=20Portuguese?= =?UTF-8?q?=20Translation=20for=20`docs/pt/docs/async.md`=20(#13863)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/pt/docs/async.md | 207 ++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 99 deletions(-) diff --git a/docs/pt/docs/async.md b/docs/pt/docs/async.md index 0d6bdbf0e..4425eba77 100644 --- a/docs/pt/docs/async.md +++ b/docs/pt/docs/async.md @@ -40,7 +40,7 @@ def results(): --- -Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e tem que esperar que o respondam, use `async def`. +Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e esperar que o respondam, use `async def`. --- @@ -52,7 +52,7 @@ Se você simplesmente não sabe, use apenas `def`. De qualquer forma, em ambos os casos acima, FastAPI irá trabalhar assincronamente e ser extremamente rápido. -Seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance. +Mas, seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance. ## Detalhes Técnicos @@ -66,36 +66,36 @@ Vamos ver aquela frase por partes na seção abaixo: ## Código assíncrono -Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto, ele 🤖 terá que esperar por *algo* para finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝. +Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto do código, ele 🤖 terá que esperar *algo* finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝. -Então, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termine. +Então, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termina. -Então o computador / programa 🤖 irá voltar toda hora que tiver uma chance porquê ele ainda está esperando o "arquivo lento", ou ele 🤖 nunca irá terminar todo o trabalho que tem até esse ponto. E ele 🤖 irá ver se alguma das tarefas que estava esperando já terminaram, fazendo o que quer que tinham que fazer. +Então o computador / programa 🤖 irá voltar sempre que tiver uma chance, seja porque ele está esperando novamente, ou quando ele 🤖 terminar todo o trabalho que tem até esse ponto. E ele 🤖 irá ver se alguma das tarefas que estava esperando já terminaram de fazer o que quer que tinham que fazer. -Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que ele tem que fazer com isso. +Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que tem que fazer com ela. -Esse "esperar por algo" normalmente se refere a operações I/O que são relativamente "lentas" (comparadas a velocidade do processador e da memória RAM), como esperar por: +Esse "esperar por algo" normalmente se refere a operações I/O que são relativamente "lentas" (comparadas à velocidade do processador e da memória RAM), como esperar por: * dados do cliente para serem enviados através da rede -* dados enviados pelo seu programa para serem recebidos pelo clente através da rede -* conteúdo de um arquivo no disco pra ser lido pelo sistema e entregar ao seu programa +* dados enviados pelo seu programa serem recebidos pelo clente através da rede +* conteúdo de um arquivo no disco ser lido pelo sistema e entregue ao seu programa * conteúdo que seu programa deu ao sistema para ser escrito no disco -* uma operação remota API -* uma operação no banco de dados para finalizar -* uma solicitação no banco de dados esperando o retorno do resultado +* uma operação em uma API remota +* uma operação no banco de dados finalizar +* uma solicitação no banco de dados retornar o resultado * etc. -Enquanto o tempo de execução é consumido mais pela espera das operações I/O, essas operações são chamadas de operações "limitadas por I/O". +Quanto o tempo de execução é consumido majoritariamente pela espera de operações I/O, essas operações são chamadas operações "limitadas por I/O". -Isso é chamado de "assíncrono" porquê o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo exato momento que a tarefa finalize, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho. +Isso é chamado de "assíncrono" porque o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo momento exato em que a tarefa finaliza, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho. -Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo,e então volte para pegar o resultado e continue trabalhando com ele. +Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar na fila um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo, e então volte para pegar o resultado e continue trabalhando com ele. -Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, na sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar. +Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, em sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar. ### Concorrência e hambúrgueres -Essa idéia de código **assíncrono** descrito acima é algo às vezes chamado de **"concorrência"**. E é diferente de **"paralelismo"**. +Essa idéia de código **assíncrono** descrita acima é às vezes chamado de **"concorrência"**. Isso é diferente de **"paralelismo"**. **Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo". @@ -105,117 +105,115 @@ Para ver essa diferença, imagine a seguinte história sobre hambúrgueres: ### Hambúrgueres concorrentes -Você vai com seu _crush_ :heart_eyes: na lanchonete, fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. +Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. 😍 -Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_ :heart_eyes:. +Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔 -Você paga. +O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saivam que têm que preparar seus hambúrgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes). -O caixa diz alguma coisa para o cara na cozinha para que ele tenha que preparar seus hambúrgueres (mesmo embora ele esteja preparando os lanches dos outros clientes). +Você paga. 💸 O caixa te entrega seu número de chamada. -Enquanto você espera, você vai com seu _crush_ :heart_eyes: e pega uma mesa, senta e conversa com seu _crush_ :heart_eyes: por um bom tempo (como seus hambúrgueres são muito saborosos, leva um tempo para serem preparados). +Enquanto você espera, você vai com seu _crush_ e pega uma mesa, senta e conversa com seu _crush_ por um bom tempo (já que seus hambúrgueres são muito saborosos, e leva um tempo para serem preparados). -Enquanto você está sentado na mesa com seu _crush_ :heart_eyes:, esperando os hambúrgueres, você pode gastar o tempo admirando como lindo, maravilhoso e esperto é seu _crush_ :heart_eyes:. +Já que você está sentado na mesa com seu _crush_, esperando os hambúrgueres, você pode passar esse tempo admirando o quão lindo, maravilhoso e esperto é seu _crush_ ✨😍✨. -Enquanto espera e conversa com seu _crush_ :heart_eyes:, de tempos em tempos, você verifica o número de chamada exibido no balcão para ver se já é sua vez. +Enquanto espera e conversa com seu _crush_, de tempos em tempos, você verifica o número da chamada exibido no balcão para ver se já é sua vez. -Então a certo ponto, é finalmente sua vez. Você vai no balcão, pega seus hambúrgueres e volta para a mesa. +Então em algum momento, é finalmente sua vez. Você vai ao balcão, pega seus hambúrgueres e volta para a mesa. -Você e seu _crush_ :heart_eyes: comem os hambúrgueres e aproveitam o tempo. +Você e seu _crush_ comem os hambúrgueres e aproveitam o tempo. ✨ --- -Imagine que você seja o computador / programa nessa história. +Imagine que você seja o computador / programa nessa história. -Enquanto você está na fila, tranquilo, esperando por sua vez, não está fazendo nada "produtivo". Mas a fila é rápida porquê o caixa só está pegando os pedidos, então está tudo bem. +Enquanto você está na fila, você está somente ocioso 😴, esperando por sua vez, sem fazer nada muito "produtivo". Mas a fila é rápida porque o caixa só está pegando os pedidos (não os preparando), então está tudo bem. -Então, quando é sua vez, você faz o trabalho "produtivo" de verdade, você processa o menu, decide o que quer, pega a escolha de seu _crush_ :heart_eyes:, paga, verifica se entregou o valor correto em dinheiro ou cartão de crédito, verifica se foi cobrado corretamente, verifica se seu pedido está correto etc. +Então, quando é sua vez, você faz trabalho realmente "produtivo", você processa o menu, decide o que quer, pega a escolha de seu _crush_, paga, verifica se entregou o cartão ou a cédula correta, verifica se foi cobrado corretamente, verifica se seu pedido está correto etc. -Mas então, embora você ainda não tenha os hambúrgueres, seu trabalho no caixa está "pausado", porquê você tem que esperar seus hambúrgueres estarem prontos. +Mas então, embora você ainda não tenha os hambúrgueres, seu trabalho no caixa está "pausado" ⏸, porque você tem que esperar 🕙 seus hambúrgueres ficarem prontos. -Mas enquanto você se afasta do balcão e senta na mesa com o número da sua chamada, você pode trocar sua atenção para seu _crush_ :heart_eyes:, e "trabalhar" nisso. Então você está novamente fazendo algo muito "produtivo", como flertar com seu _crush_ :heart_eyes:. +Contudo, à medida que você se afasta do balcão e senta na mesa, com um número para sua chamada, você pode trocar 🔀 sua atenção para seu _crush_, e "trabalhar" ⏯ 🤓 nisso. Então você está novamente fazendo algo muito "produtivo", como flertar com seu _crush_ 😍. -Então o caixa diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porquê você tem o número de chamada, e os outros tem os números deles. +Então o caixa 💁 diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porque você tem o seu número da chamada, e os outros têm os deles. -Então você espera que seu _crush_ :heart_eyes: termine a história que estava contando (terminar o trabalho atual / tarefa sendo processada), sorri gentilmente e diz que você está indo buscar os hambúrgueres. +Então você espera seu _crush_ terminar a história que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que você está indo buscar os hambúrgueres. -Então você vai no balcão, para a tarefa inicial que agora está finalizada, pega os hambúrgueres, e leva para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão. Agora é criada uma nova tarefa, "comer hambúrgueres", mas a tarefa anterior, "pegar os hambúrgueres" já está finalizada. +Então você vai ao balcão 🔀, para a tarefa inicial que agora está finalizada⏯, pega os hambúrgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão ⏹. Isso, por sua vez, cria uma nova tarefa, a de "comer hambúrgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambúrgueres" já está finalizada ⏹. ### Hambúrgueres paralelos -Você vai com seu _crush_ :heart_eyes: em uma lanchonete paralela. +Agora vamos imaginar que esses não são "Hambúrgueres Concorrentes", e sim "Hambúrgueres Paralelos" -Você fica na fila enquanto alguns (vamos dizer 8) caixas pegam os pedidos das pessoas na sua frente. +Você vai com seu _crush_ na lanchonete paralela. -Todo mundo antes de você está esperando pelos hambúrgueres estarem prontos antes de deixar o caixa porquê cada um dos 8 caixas vai e prepara o hambúrguer antes de pegar o próximo pedido. +Você fica na fila enquanto vários (vamos dizer 8) caixas que também são cozinheiros pegam os pedidos das pessoas na sua frente. -Então é finalmente sua vez, e pede 2 hambúrgueres muito saborosos para você e seu _crush_ :heart_eyes:. +Todo mundo na sua frente está esperando seus hambúrgueres ficarem prontos antes de deixar o caixa porque cada um dos 8 caixas vai e prepara o hambúrguer logo após receber o pedido, antes de pegar o próximo pedido. -Você paga. +Então é finalmente sua vez, você pede 2 hambúrgueres muito saborosos para você e seu _crush_. + +Você paga 💸. O caixa vai para a cozinha. -Você espera, na frente do balcão, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas. +Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas. -Enquanto você e seu _crush_ :heart_eyes: estão ocupados não permitindo que ninguém passe a frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_ :heart_eyes:. +Como você e seu _crush_ estão ocupados não permitindo que ninguém passe na frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_. 😞 -Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro. Você tem que esperar e estar lá no exato momento que o caixa / cozinheiro terminar os hambúrgueres e dá-los a você, ou então, outro alguém pode pegá-los. +Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro👨‍🍳. Você tem que esperar 🕙 e estar lá no exato momento que o caixa / cozinheiro 👨‍🍳 terminar os hambúrgueres e os der a você, ou então, outro alguém pode pegá-los. -Então seu caixa / cozinheiro finalmente volta com seus hambúrgueres, depois de um longo tempo esperando por eles em frente ao balcão. +Então seu caixa / cozinheiro 👨‍🍳 finalmente volta com seus hambúrgueres, depois de um longo tempo esperando 🕙 por eles em frente ao balcão. -Você pega seus hambúrgueres e vai para a mesa com seu _crush_ :heart_eyes:. +Você pega seus hambúrgueres e vai para a mesa com seu _crush_. -Vocês comem os hambúrgueres, e o trabalho está terminado. +Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹ -Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando os lanches na frente do balcão. +Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando 🕙 na frente do balcão. 😞 --- -Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_ :heart_eyes:), ambos esperando e dedicando a atenção de estar "esperando no balcão" por um bom tempo. +Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_), ambos esperando 🕙 e dedicando sua atenção ⏯ "esperando no balcão" 🕙 por um bom tempo. -A lanchonete paralela tem 8 processadores (caixas / cozinheiros). Enquanto a lanchonete dos hambúrgueres concorrentes tinham apenas 2 (um caixa e um cozinheiro). +A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro). -Ainda assim, a última experiência não foi a melhor. +Ainda assim, a experiência final não foi a melhor. 😞 --- -Essa poderia ser a história paralela equivalente aos hambúrgueres. +Essa seria o equivalente paralelo à histório dos hambúrgueres. 🍔 Para um exemplo "mais real", imagine um banco. -Até recentemente, a maioria dos bancos tinha muitos caixas e uma grande fila. +Até recentemente, a maioria dos bancos tinham muitos caixas 👨‍💼👨‍💼👨‍💼👨‍💼 e uma grande fila 🕙🕙🕙🕙🕙🕙🕙🕙. -Todos os caixas fazendo todo o trabalho, um cliente após o outro. +Todos os caixas fazendo todo o trabalho, um cliente após o outro 👨‍💼⏯. -E você tinha que esperar na fila por um longo tempo ou poderia perder a vez. +E você tinha que esperar 🕙 na fila por um longo tempo ou poderia perder a vez. -Você provavelmente não gostaria de levar seu _crush_ :heart_eyes: com você para um rolezinho no banco. +Você provavelmente não gostaria de levar seu _crush_ 😍 com você para um rolezinho no banco 🏦. ### Conclusão dos hambúrgueres -Nesse cenário dos "hambúrgueres com seu _crush_ :heart_eyes:", como tem muita espera, faz mais sentido ter um sistema concorrente. +Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯. Esse é o caso da maioria das aplicações web. -Geralmente são muitos usuários, e seu servidor está esperando pelas suas conexões não tão boas para enviar as requisições. +Muitos, muitos usuários, mas seu servidor está esperando 🕙 pela sua conexão não tão boa enviar suas requisições. -E então esperando novamente pelas respostas voltarem. +E então esperando 🕙 novamente as respostas voltarem. -Essa "espera" é medida em microssegundos, e ainda assim, somando tudo, é um monte de espera no final. +Essa "espera" 🕙 é medida em microssegundos, mas ainda assim, somando tudo, é um monte de espera no final. -Por isso que faz muito mais sentido utilizar código assíncrono para APIs web. +Por isso que faz bastante sentido utilizar código assíncrono ⏸🔀⏯ para APIs web. -A maioria dos frameworks Python existentes mais populares (incluindo Flask e Django) foram criados antes que os novos recursos assíncronos existissem em Python. Então, os meios que eles podem ser colocados em produção para suportar execução paralela mais a forma antiga de execução assíncrona não são tão poderosos quanto as novas capacidades. - -Mesmo embora a especificação principal para web assíncrono em Python (ASGI) foi desenvolvida no Django, para adicionar suporte para WebSockets. - -Esse tipo de assincronicidade é o que fez NodeJS popular (embora NodeJS não seja paralelo) e que essa seja a força do Go como uma linguagem de programa. +Esse tipo de assincronicidade é o que fez NodeJS popular (embora NodeJS não seja paralelo) e essa é a força do Go como uma linguagem de programação. E esse é o mesmo nível de performance que você tem com o **FastAPI**. -E como você pode ter paralelismo e sincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada próxima ao C (tudo graças ao Starlette). +E como você pode ter paralelismo e assincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada, mais próxima ao C (tudo graças ao Starlette). ### Concorrência é melhor que paralelismo? @@ -225,64 +223,64 @@ Concorrência é diferente de paralelismo. E é melhor em cenários **específic Então, para equilibrar tudo, imagine a seguinte historinha: -> Você tem que limpar uma grande casa suja. +> Você tem que limpar uma casa grande e suja. *Sim, essa é toda a história*. --- -Não há espera em lugar algum, apenas um monte de trabalho para ser feito, em múltiplos cômodos da casa. +Não há espera 🕙 em lugar algum, apenas um monte de trabalho para ser feito, em múltiplos cômodos da casa. -Você poderia ter chamadas como no exemplo dos hambúrgueres, primeiro a sala de estar, então a cozinha, mas você não está esperando por nada, apenas limpar e limpar, as chamadas não afetariam em nada. +Você poderia ter turnos como no exemplo dos hambúrgueres, primeiro a sala de estar, então a cozinha, mas como você não está esperando por nada, apenas limpando e limpando, as chamadas não afetariam em nada. -Levaria o mesmo tempo para finalizar com ou sem chamadas (concorrência) e você teria feito o mesmo tanto de trabalho. +Levaria o mesmo tempo para finalizar com ou sem turnos (concorrência) e você teria feito o mesmo tanto de trabalho. Mas nesse caso, se você trouxesse os 8 ex-caixas / cozinheiros / agora-faxineiros, e cada um deles (mais você) pudessem dividir a casa para limpá-la, vocês fariam toda a limpeza em **paralelo**, com a ajuda extra, e terminariam muito mais cedo. Nesse cenário, cada um dos faxineiros (incluindo você) poderia ser um processador, fazendo a sua parte do trabalho. -E a maior parte do tempo de execução é tomada por trabalho (ao invés de ficar esperando), e o trabalho em um computador é feito pela CPU, que podem gerar problemas que são chamados de "limite de CPU". +E a maior parte do tempo de execução é tomada por trabalho real (ao invés de ficar esperando), e o trabalho em um computador é feito pela CPU. Eles chamam esses problemas de "limitados por CPU". --- -Exemplos comuns de limite de CPU são coisas que exigem processamento matemático complexo. +Exemplos comuns de operações limitadas por CPU são coisas que exigem processamento matemático complexo. Por exemplo: * **Processamento de áudio** ou **imagem** -* **Visão do Computador**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores (cores, processamento que normalmente exige alguma computação em todos esses pixels ao mesmo tempo) +* **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação em todos esses pixels ao mesmo tempo -* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande folha de papel com números e multiplicando todos eles juntos e ao mesmo tempo. +* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande planilha com números e em multiplicar todos eles juntos e ao mesmo tempo. -* **Deep Learning**: Esse é um subcampo do Machine Learning, então o mesmo se aplica. A diferença é que não há apenas uma grande folha de papel com números para multiplicar, mas um grande conjunto de folhas de papel, e em muitos casos, você utiliza um processador especial para construir e/ou usar modelos. +* **Deep Learning**: Esse é um subcampo do Machine Learning, então, o mesmo se aplica. A diferença é que não há apenas uma grande planilha com números para multiplicar, mas um grande conjunto delas, e em muitos casos, você utiliza um processador especial para construir e/ou usar esses modelos. ### Concorrência + Paralelismo: Web + Machine learning Com **FastAPI** você pode levar a vantagem da concorrência que é muito comum para desenvolvimento web (o mesmo atrativo de NodeJS). -Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos pesados que geram **limite de CPU** como aqueles em sistemas de Machine Learning. +Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Machine Learning. -Isso, mais o simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras). +Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras). Para ver como alcançar esse paralelismo em produção veja a seção sobre [Deployment](deployment/index.md){.internal-link target=_blank}. ## `async` e `await` -Versões modernas do Python tem um modo muito intuitivo para definir código assíncrono. Isso faz parecer normal o código "sequencial" e fazer o "esperar" para você nos momentos certos. +Versões modernas do Python têm um modo muito intuitivo para definir código assíncrono. Isso faz parecer do mesmo jeito do código normal "sequencial" e fazer a "espera" para você nos momentos certos. -Quando tem uma operação que exigirá espera antes de dar os resultados e tem suporte para esses recursos Python, você pode escrever assim: +Quando tem uma operação que exigirá espera antes de dar os resultados e tem suporte para esses novos recursos do Python, você pode escrever assim: ```Python burgers = await get_burgers(2) ``` -A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` para finalizar suas coisas antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas nesse meio tempo (como receber outra requisição). +A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisição). Para o `await` funcionar, tem que estar dentro de uma função que suporte essa assincronicidade. Para fazer isso, apenas declare a função com `async def`: ```Python hl_lines="1" async def get_burgers(number: int): - # Fazer alguma coisa assíncrona para criar os hambúrgueres + # Faz alguma coisa assíncrona para criar os hambúrgueres return burgers ``` @@ -295,9 +293,9 @@ def get_sequential_burgers(number: int): return burgers ``` -Com `async def`, o Python sabe que, dentro dessa função, tem que estar ciente das expressões `await`, e que isso pode "pausar" a execução dessa função, e poderá fazer outra coisa antes de voltar. +Com `async def`, o Python sabe que, dentro dessa função, ele deve estar ciente das expressões `await`, e que isso poderá "pausar" ⏸ a execução dessa função, e ir fazer outra coisa 🔀 antes de voltar. -Quando você quiser chamar uma função `async def`, você tem que "esperar". Então, isso não funcionará: +Quando você quiser chamar uma função `async def`, você tem que "esperar" ela. Então, isso não funcionará: ```Python # Isso não irá funcionar, porquê get_burgers foi definido com: async def @@ -319,13 +317,24 @@ async def read_burgers(): Você deve ter observado que `await` pode ser usado somente dentro de funções definidas com `async def`. -Mas ao mesmo tempo, funções definidas com `async def` tem que ser aguardadas. Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também. +Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também. Então, sobre o ovo e a galinha, como você chama a primeira função async? Se você estivar trabalhando com **FastAPI** não terá que se preocupar com isso, porquê essa "primeira" função será a sua *função de operação de rota*, e o FastAPI saberá como fazer a coisa certa. -Mas se você quiser usar `async` / `await` sem FastAPI, verifique a documentação oficial Python. +Mas se você quiser usar `async` / `await` sem FastAPI, você também pode fazê-lo. + +### Escreva seu próprio código assíncrono + +Starlette (e **FastAPI**) são baseados no AnyIO, o que o torna compatível com ambos o asyncio da biblioteca padrão do Python, e o Trio. + +Em particular, você pode usar diretamente o AnyIO para seus casos de uso avançados de concorrência que requerem padrões mais avançados no seu próprio código. + +E até se você não estiver utilizando FastAPI, você também pode escrever suas próprias aplicações assíncronas com o AnyIO por ser altamente compatível e ganhar seus benefícios (e.g. *concorrência estruturada*). + +Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotações de tipo e obter melhor **autocompletar**, **erros de linha**, etc. Ela também possui uma introdução amigável e um tutorial para ajudar você a **entender** e escrever **seu próprio código async**: Asyncer. Seria particularmente útil se você precisar **combinar código async com código regular** (bloqueador/síncrono). + ### Outras formas de código assíncrono @@ -337,25 +346,25 @@ Essa mesma sintaxe (ou quase a mesma) foi também incluída recentemente em vers Mas antes disso, controlar código assíncrono era bem mais complexo e difícil. -Nas versões anteriores do Python, você poderia utilizar threads ou Gevent. Mas o código é um pouco mais complexo de entender, debugar, e pensar sobre. +Nas versões anteriores do Python, você poderia utilizar threads ou Gevent. Mas o código é bem mais complexo de entender, debugar, e pensar sobre. -Nas versões anteriores do NodeJS / Navegador JavaScript, você poderia utilizar "callbacks". O que leva ao inferno do callback. +Nas versões anteriores do NodeJS / Navegador JavaScript, você utilizaria "callbacks". O que leva ao inferno do callback. ## Corrotinas -**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é uma função que pode começar e terminar em algum ponto, mas que pode ser pausada internamente também, sempre que tiver um `await` dentro dela. +**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é algo como uma função, que pode começar e que vai terminar em algum ponto, mas que pode ser pausada ⏸ internamente também, sempre que tiver um `await` dentro dela. -Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como "corrotina". É comparável ao principal recurso chave do Go, a "Gorotina". +Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como usando "corrotinas". É comparável ao principal recurso chave do Go, a "Gorrotina". ## Conclusão -Vamos ver a mesma frase com o conteúdo cima: +Vamos ver a mesma frase de cima: -> Versões modernas do Python tem suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**. +> Versões modernas do Python têm suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**. -Isso pode fazer mais sentido agora. +Isso pode fazer mais sentido agora. ✨ -Tudo isso é o que deixa o FastAPI poderoso (através do Starlette) e que o faz ter uma performance impressionante. +Tudo isso é o que empodera o FastAPI (através do Starlette) e que o faz ter uma performance tão impressionante. ## Detalhes muito técnicos @@ -365,25 +374,25 @@ Você pode provavelmente pular isso. Esses são detalhes muito técnicos de como **FastAPI** funciona por baixo do capô. -Se você tem algum conhecimento técnico (corrotinas, threads, blocking etc) e está curioso sobre como o FastAPI controla o `async def` vs normal `def`, vá em frente. +Se você tem certo conhecimento técnico (corrotinas, threads, blocking etc) e está curioso sobre como o FastAPI controla o `async def` vs normal `def`, vá em frente. /// ### Funções de operação de rota -Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que então é aguardada, ao invés de ser chamada diretamente (ela poderia bloquear o servidor). +Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que é então aguardada, ao invés de ser chamada diretamente (já que ela bloquearia o servidor). -Se você está chegando de outro framework assíncrono que não faz o trabalho descrito acima e você está acostumado a definir triviais *funções de operação de rota* com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performem bloqueamento IO. +Se você está chegando de outro framework assíncrono que não funciona como descrito acima e você está acostumado a definir *funções de operação de rota* triviais somente de computação com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performe bloqueamento IO. -Ainda, em ambas as situações, as chances são que o **FastAPI** será [ainda mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seus frameworks antecessores. +Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seu framework anterior. ### Dependências -O mesmo se aplica para as dependências. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo. +O mesmo se aplica para as [dependências](tutorial/dependencies/index.md){.internal-link target=_blank}. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo. ### Sub-dependências -Você pode ter múltiplas dependências e sub-dependências exigindo uma a outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda poderia funcionar, e aquelas criadas com `def` podem ser chamadas em uma thread externa ao invés de serem "aguardadas". +Você pode ter múltiplas dependências e [sub-dependências](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requisitando uma à outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda funcionaria, e aquelas criadas com `def` normal seriam chamadas em uma thread externa (do threadpool) ao invés de serem "aguardadas". ### Outras funções de utilidade @@ -395,6 +404,6 @@ Se sua função de utilidade é uma função normal com `def`, ela será chamada --- -Novamente, esses são detalhes muito técnicos que provavelmente possam ser úteis caso você esteja procurando por eles. +Novamente, esses são detalhes muito técnicos que provavelmente seriam úteis caso você esteja procurando por eles. Caso contrário, você deve ficar bem com as dicas da seção acima: Com pressa?. From 89b4d1f076be7f7b30447344ef33cc895dade875 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 11:17:02 +0000 Subject: [PATCH 277/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d5730e247..a6a68584a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Translations +* 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). * 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki). * 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). * 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). From 3d60b5e23e878ca28e823fa65b06d67de95a6588 Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Sat, 26 Jul 2025 13:35:42 +0200 Subject: [PATCH 278/455] =?UTF-8?q?=F0=9F=93=9D=20Add=20discussion=20templ?= =?UTF-8?q?ate=20for=20new=20language=20translation=20requests=20(#13535)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- .github/DISCUSSION_TEMPLATE/translations.yml | 45 ++++++++++++++++++++ docs/en/docs/contributing.md | 37 +++++++++++----- 2 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 .github/DISCUSSION_TEMPLATE/translations.yml diff --git a/.github/DISCUSSION_TEMPLATE/translations.yml b/.github/DISCUSSION_TEMPLATE/translations.yml new file mode 100644 index 000000000..16e304d99 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/translations.yml @@ -0,0 +1,45 @@ +labels: [lang-all] +body: + - type: markdown + attributes: + value: | + Thanks for your interest in helping translate the FastAPI docs! 🌍 + + Please follow these instructions carefully to propose a new language translation. 🙏 + + This structured process helps ensure translations can be properly maintained long-term. + - type: checkboxes + id: checks + attributes: + label: Initial Checks + description: Please confirm and check all the following options. + options: + - label: I checked that this language is not already being translated in FastAPI docs. + required: true + - label: I searched existing discussions to ensure no one else proposed this language. + required: true + - label: I am a native speaker of the language I want to help translate. + required: true + - type: input + id: language + attributes: + label: Target Language + description: What language do you want to translate the FastAPI docs into? + placeholder: e.g. Latin + validations: + required: true + - type: textarea + id: additional_info + attributes: + label: Additional Information + description: Any other relevant information about your translation proposal + - type: markdown + attributes: + value: | + Translations are automatized with AI and then reviewed by native speakers. 🤖 🙋 + + This allows us to keep them consistent and up-to-date. + + If there are several native speakers commenting on this discussion and + committing to help review new translations, the FastAPI team will review it + and potentially make it an official translation. 😎 diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 91c39c927..2583fd1fb 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -315,30 +315,47 @@ Now you can translate it all and see how it looks as you save the file. Some of these files are updated very frequently and a translation would always be behind, or they include the main content from English source files, etc. +#### Request a New Language + +Let's say that you want to request translations for a language that is not yet translated, not even some pages. For example, Latin. + +If there is no discussion for that language, you can start by requesting the new language. For that, you can follow these steps: + +* Create a new discussion following the template. +* Get a few native speakers to comment on the discussion and commit to help review translations for that language. + +Once there are several people in the discussion, the FastAPI team can evaluate it and can make it an official translation. + +Then the docs will be automatically translated using AI, and the team of native speakers can review the translation, and help tweak the AI prompts. + +Once there's a new translation, for example if docs are updated or there's a new section, there will be a comment in the same discussion with the link to the new translation to review. + #### New Language -Let's say that you want to add translations for a language that is not yet translated, not even some pages. +/// note -Let's say you want to add translations for Creole, and it's not yet there in the docs. +These steps will be performed by the FastAPI team. -Checking the link from above, the code for "Creole" is `ht`. +/// -The next step is to run the script to generate a new translation directory: +Checking the link from above (List of ISO 639-1 codes), you can see that the 2-letter code for Latin is `la`. + +Now you can create a new directory for the new language, running the following script:
```console // Use the command new-lang, pass the language code as a CLI argument -$ python ./scripts/docs.py new-lang ht +$ python ./scripts/docs.py new-lang la -Successfully initialized: docs/ht +Successfully initialized: docs/la ```
-Now you can check in your code editor the newly created directory `docs/ht/`. +Now you can check in your code editor the newly created directory `docs/la/`. -That command created a file `docs/ht/mkdocs.yml` with a simple config that inherits everything from the `en` version: +That command created a file `docs/la/mkdocs.yml` with a simple config that inherits everything from the `en` version: ```yaml INHERIT: ../en/mkdocs.yml @@ -350,11 +367,11 @@ You could also simply create that file with those contents manually. /// -That command also created a dummy file `docs/ht/index.md` for the main page, you can start by translating that one. +That command also created a dummy file `docs/la/index.md` for the main page, you can start by translating that one. You can continue with the previous instructions for an "Existing Language" for that process. -You can make the first pull request with those two files, `docs/ht/mkdocs.yml` and `docs/ht/index.md`. 🎉 +You can make the first pull request with those two files, `docs/la/mkdocs.yml` and `docs/la/index.md`. 🎉 #### Preview the result From d67f092db84c7c5cb7b882aa1e25c8a10b6727b6 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 11:36:02 +0000 Subject: [PATCH 279/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a6a68584a..0e5fa6303 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Add discussion template for new language translation requests. PR [#13535](https://github.com/fastapi/fastapi/pull/13535) by [@alejsdev](https://github.com/alejsdev). + ### Translations * 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). From ae02be90b6857cac1a00ea47c154457effcdcb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 26 Jul 2025 20:57:50 +0200 Subject: [PATCH 280/455] =?UTF-8?q?=F0=9F=94=A8=20Update=20translations=20?= =?UTF-8?q?script=20to=20remove=20old=20(removed)=20files=20(#13928)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/es/llm-prompt.md | 50 ----------------------- scripts/translate.py | 93 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 86 insertions(+), 57 deletions(-) diff --git a/docs/es/llm-prompt.md b/docs/es/llm-prompt.md index 3340dbc99..936ed9bba 100644 --- a/docs/es/llm-prompt.md +++ b/docs/es/llm-prompt.md @@ -4,56 +4,6 @@ Use the informal grammar (use "tú" instead of "usted"). For instructions or titles in imperative, keep them in imperative, for example "Edit it" to "Edítalo". -There are special blocks of notes, tips and others that look like: - -/// note - -To translate it, keep the same line and add the translation after a vertical bar: - -/// note | Nota - -Some examples: - -Source: - -/// tip - -Result: - -/// tip | Consejo - -Source: - -/// details | Preview - -Result: - -/// details | Vista previa - -Source: - -/// warning - -Result: - -/// warning | Advertencia - -Source: - -/// info - -Result: - -/// info | Información - -Source: - -/// note | Technical Details - -Result: - -/// note | Detalles Técnicos - --- For the next terms, use the following translations: diff --git a/scripts/translate.py b/scripts/translate.py index 9a2136d1b..09533747b 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -5,6 +5,7 @@ from typing import Iterable import typer import yaml from pydantic_ai import Agent +from rich import print non_translated_sections = ( "reference/", @@ -28,8 +29,38 @@ The content is written in markdown, write the translation in markdown as well. D When there's an example of code, the console or a terminal, normally surrounded by triple backticks and a keyword like "console" or "bash" (e.g. ```console), do not translate the content, keep the original in English. The original content will be surrounded by triple percentage signs (%) and you should translate it to the target language. Do not include the triple percentage signs in the translation. + +There are special blocks of notes, tips and others that look like: + +/// note + +To translate it, keep the same line and add the translation after a vertical bar. + +For example, if you were translating to Spanish, you would write: + +/// note | Nota + +Some examples in Spanish: + +Source: + +/// tip + +Result: + +/// tip | Consejo + +Source: + +/// details | Preview + +Result: + +/// details | Vista previa """ +app = typer.Typer() + @lru_cache def get_langs() -> dict[str, str]: @@ -46,6 +77,17 @@ def generate_lang_path(*, lang: str, path: Path) -> Path: return out_path +def generate_en_path(*, lang: str, path: Path) -> Path: + en_docs_path = Path("docs/en/docs") + assert not str(path).startswith(str(en_docs_path)), ( + f"Path must not be inside {en_docs_path}" + ) + lang_docs_path = Path(f"docs/{lang}/docs") + out_path = Path(str(path).replace(str(lang_docs_path), str(en_docs_path))) + return out_path + + +@app.command() def translate_page(*, lang: str, path: Path) -> None: langs = get_langs() language = langs[lang] @@ -68,8 +110,8 @@ def translate_page(*, lang: str, path: Path) -> None: agent = Agent("openai:gpt-4o") prompt_segments = [ - lang_prompt_content, general_prompt, + lang_prompt_content, ] if old_translation: prompt_segments.extend( @@ -119,6 +161,7 @@ def iter_paths_to_translate() -> Iterable[Path]: yield path +@app.command() def translate_all(lang: str) -> None: paths_to_process: list[Path] = [] for path in iter_paths_to_translate(): @@ -151,12 +194,48 @@ def translate_all(lang: str) -> None: print(f"Done translating: {p}") -def main(*, lang: str, path: Path = None) -> None: - if path: - translate_page(lang=lang, path=path) - else: - translate_all(lang=lang) +@app.command() +def list_removable(lang: str) -> list[Path]: + removable_paths: list[Path] = [] + lang_paths = Path(f"docs/{lang}").rglob("*.md") + for path in lang_paths: + en_path = generate_en_path(lang=lang, path=path) + if not en_path.exists(): + removable_paths.append(path) + print(removable_paths) + return removable_paths + + +@app.command() +def list_all_removable() -> list[Path]: + all_removable_paths: list[Path] = [] + langs = get_langs() + for lang in langs: + if lang == "en": + continue + removable_paths = list_removable(lang) + all_removable_paths.extend(removable_paths) + print(all_removable_paths) + return all_removable_paths + + +@app.command() +def remove_removable(lang: str) -> None: + removable_paths = list_removable(lang) + for path in removable_paths: + path.unlink() + print(f"Removed: {path}") + print("Done removing all removable paths") + + +@app.command() +def remove_all_removable() -> None: + all_removable = list_all_removable() + for removable_path in all_removable: + removable_path.unlink() + print(f"Removed: {removable_path}") + print("Done removing all removable paths") if __name__ == "__main__": - typer.run(main) + app() From 4f0aae9d237059c48aace9cc222f62e3ef4f2ee5 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 18:58:14 +0000 Subject: [PATCH 281/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 0e5fa6303..3b94dfd8f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). * 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). From adc328e258d00c5717070a103626cb48a03abecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 26 Jul 2025 23:19:05 +0200 Subject: [PATCH 282/455] =?UTF-8?q?=F0=9F=94=A8=20Refactor=20translate=20s?= =?UTF-8?q?cript=20with=20extra=20feedback=20(prints)=20(#13932)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/translate.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/scripts/translate.py b/scripts/translate.py index 09533747b..6af12dc98 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -106,7 +106,9 @@ def translate_page(*, lang: str, path: Path) -> None: original_content = path.read_text() old_translation: str | None = None if out_path.exists(): + print(f"Found existing translation: {out_path}") old_translation = out_path.read_text() + print(f"Translating {path} to {lang} ({language})") agent = Agent("openai:gpt-4o") prompt_segments = [ @@ -131,13 +133,14 @@ def translate_page(*, lang: str, path: Path) -> None: ] ) prompt = "\n\n".join(prompt_segments) - + print(f"Running agent for {out_path}") result = agent.run_sync(prompt) out_content = f"{result.data.strip()}\n" + print(f"Saving translation to {out_path}") out_path.write_text(out_content) -def iter_paths_to_translate() -> Iterable[Path]: +def iter_all_en_paths() -> Iterable[Path]: """ Iterate on the markdown files to translate in order of priority. """ @@ -161,13 +164,16 @@ def iter_paths_to_translate() -> Iterable[Path]: yield path -@app.command() -def translate_all(lang: str) -> None: - paths_to_process: list[Path] = [] - for path in iter_paths_to_translate(): +def iter_en_paths_to_translate() -> Iterable[Path]: + for path in iter_all_en_paths(): if str(path).replace("docs/en/docs/", "").startswith(non_translated_sections): continue - paths_to_process.append(path) + yield path + + +@app.command() +def translate_all(lang: str) -> None: + paths_to_process = list(iter_en_paths_to_translate()) print("Original paths:") for p in paths_to_process: print(f" - {p}") From 4c40b484f1a6ecea0921dc58292c3f733ddf5d9b Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 21:19:29 +0000 Subject: [PATCH 283/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3b94dfd8f..56c325977 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). From 273b06adab5fd527492ff9ed3f98cfa653d10002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 26 Jul 2025 23:27:35 +0200 Subject: [PATCH 284/455] =?UTF-8?q?=E2=9A=92=EF=B8=8F=20Update=20translate?= =?UTF-8?q?=20script,=20show=20and=20update=20outdated=20translations=20(#?= =?UTF-8?q?13933)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- requirements-translations.txt | 1 + scripts/translate.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/requirements-translations.txt b/requirements-translations.txt index 7a2a8004e..90f718032 100644 --- a/requirements-translations.txt +++ b/requirements-translations.txt @@ -1 +1,2 @@ pydantic-ai==0.0.30 +GitPython==3.1.45 diff --git a/scripts/translate.py b/scripts/translate.py index 6af12dc98..b78d7211b 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -2,6 +2,7 @@ from functools import lru_cache from pathlib import Path from typing import Iterable +import git import typer import yaml from pydantic_ai import Agent @@ -243,5 +244,39 @@ def remove_all_removable() -> None: print("Done removing all removable paths") +@app.command() +def list_outdated(lang: str) -> list[Path]: + dir_path = Path(__file__).absolute().parent.parent + repo = git.Repo(dir_path) + + outdated_paths: list[Path] = [] + en_lang_paths = list(iter_en_paths_to_translate()) + for path in en_lang_paths: + lang_path = generate_lang_path(lang=lang, path=path) + if not lang_path.exists(): + outdated_paths.append(path) + continue + en_commit_datetime = list(repo.iter_commits(paths=path, max_count=1))[ + 0 + ].committed_datetime + lang_commit_datetime = list(repo.iter_commits(paths=lang_path, max_count=1))[ + 0 + ].committed_datetime + if lang_commit_datetime < en_commit_datetime: + outdated_paths.append(path) + print(outdated_paths) + return outdated_paths + + +@app.command() +def update_outdated(lang: str) -> None: + outdated_paths = list_outdated(lang) + for path in outdated_paths: + print(f"Updating lang: {lang} path: {path}") + translate_page(lang=lang, path=path) + print(f"Done updating: {path}") + print("Done updating all outdated paths") + + if __name__ == "__main__": app() From d5d302c3da11262f4e320a9af5dbb9d13386e1b5 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 26 Jul 2025 21:27:58 +0000 Subject: [PATCH 285/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 56c325977..f3984fa9e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). * 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 6516a6c4a60c91de881cc73c40a3c609001dd29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 27 Jul 2025 21:12:19 +0200 Subject: [PATCH 286/455] =?UTF-8?q?=F0=9F=91=B7=20Add=20CI=20to=20translat?= =?UTF-8?q?e=20with=20LLMs=20(#13937)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/translate.yml | 77 ++++++++++++++++++++++++++ scripts/translate.py | 96 +++++++++++++++++++++++++++++---- 2 files changed, 162 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/translate.yml diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml new file mode 100644 index 000000000..edbff6fe5 --- /dev/null +++ b/.github/workflows/translate.yml @@ -0,0 +1,77 @@ +name: Translate + +on: + workflow_dispatch: + inputs: + debug_enabled: + description: Run with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) + required: false + default: "false" + command: + description: Command to run + type: choice + options: + - translate-page + - translate-lang + - update-outdated + - add-missing + - update-and-add + - remove-all-removable + lang: + description: Language to translate to as a letter code (e.g. "es" for Spanish) + type: string + required: false + default: "" + en_path: + description: File path in English to translate (e.g. docs/en/docs/index.md) + type: string + required: false + default: "" + +env: + UV_SYSTEM_PYTHON: 1 + +jobs: + job: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Setup uv + uses: astral-sh/setup-uv@v6 + with: + version: "0.4.15" + enable-cache: true + cache-dependency-glob: | + requirements**.txt + pyproject.toml + - name: Install Dependencies + run: uv pip install -r requirements-github-actions.txt -r requirements-translations.txt + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: FastAPI Translate + run: | + python ./scripts/translate.py ${{ github.event.inputs.command }} + python ./scripts/translate.py make-pr + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + LANG: ${{ github.event.inputs.lang }} + EN_PATH: ${{ github.event.inputs.en_path }} diff --git a/scripts/translate.py b/scripts/translate.py index b78d7211b..5fdbe7220 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -1,10 +1,13 @@ +import secrets +import subprocess from functools import lru_cache from pathlib import Path -from typing import Iterable +from typing import Annotated, Iterable import git import typer import yaml +from github import Github from pydantic_ai import Agent from rich import print @@ -89,7 +92,11 @@ def generate_en_path(*, lang: str, path: Path) -> Path: @app.command() -def translate_page(*, lang: str, path: Path) -> None: +def translate_page( + *, + lang: Annotated[str, typer.Option(envvar="LANG")], + en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], +) -> None: langs = get_langs() language = langs[lang] lang_path = Path(f"docs/{lang}") @@ -99,17 +106,17 @@ def translate_page(*, lang: str, path: Path) -> None: lang_prompt_content = lang_prompt_path.read_text() en_docs_path = Path("docs/en/docs") - assert str(path).startswith(str(en_docs_path)), ( + assert str(en_path).startswith(str(en_docs_path)), ( f"Path must be inside {en_docs_path}" ) - out_path = generate_lang_path(lang=lang, path=path) + out_path = generate_lang_path(lang=lang, path=en_path) out_path.parent.mkdir(parents=True, exist_ok=True) - original_content = path.read_text() + original_content = en_path.read_text() old_translation: str | None = None if out_path.exists(): print(f"Found existing translation: {out_path}") old_translation = out_path.read_text() - print(f"Translating {path} to {lang} ({language})") + print(f"Translating {en_path} to {lang} ({language})") agent = Agent("openai:gpt-4o") prompt_segments = [ @@ -173,7 +180,7 @@ def iter_en_paths_to_translate() -> Iterable[Path]: @app.command() -def translate_all(lang: str) -> None: +def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: paths_to_process = list(iter_en_paths_to_translate()) print("Original paths:") for p in paths_to_process: @@ -197,7 +204,7 @@ def translate_all(lang: str) -> None: print(f"Total paths to process: {len(missing_paths)}") for p in missing_paths: print(f"Translating: {p}") - translate_page(lang="es", path=p) + translate_page(lang="es", en_path=p) print(f"Done translating: {p}") @@ -244,6 +251,18 @@ def remove_all_removable() -> None: print("Done removing all removable paths") +@app.command() +def list_missing(lang: str) -> list[Path]: + missing_paths: list[Path] = [] + en_lang_paths = list(iter_en_paths_to_translate()) + for path in en_lang_paths: + lang_path = generate_lang_path(lang=lang, path=path) + if not lang_path.exists(): + missing_paths.append(path) + print(missing_paths) + return missing_paths + + @app.command() def list_outdated(lang: str) -> list[Path]: dir_path = Path(__file__).absolute().parent.parent @@ -254,7 +273,6 @@ def list_outdated(lang: str) -> list[Path]: for path in en_lang_paths: lang_path = generate_lang_path(lang=lang, path=path) if not lang_path.exists(): - outdated_paths.append(path) continue en_commit_datetime = list(repo.iter_commits(paths=path, max_count=1))[ 0 @@ -269,14 +287,70 @@ def list_outdated(lang: str) -> list[Path]: @app.command() -def update_outdated(lang: str) -> None: +def update_outdated(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: outdated_paths = list_outdated(lang) for path in outdated_paths: print(f"Updating lang: {lang} path: {path}") - translate_page(lang=lang, path=path) + translate_page(lang=lang, en_path=path) print(f"Done updating: {path}") print("Done updating all outdated paths") +@app.command() +def add_missing(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: + missing_paths = list_missing(lang) + for path in missing_paths: + print(f"Adding lang: {lang} path: {path}") + translate_page(lang=lang, en_path=path) + print(f"Done adding: {path}") + print("Done adding all missing paths") + + +@app.command() +def update_and_add(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: + print(f"Updating outdated translations for {lang}") + update_outdated(lang=lang) + print(f"Adding missing translations for {lang}") + add_missing(lang=lang) + print(f"Done updating and adding for {lang}") + + +@app.command() +def make_pr( + *, + lang: Annotated[str, typer.Option(envvar="LANG")], + github_token: Annotated[str, typer.Option(envvar="GITHUB_TOKEN")], + github_repository: Annotated[str, typer.Option(envvar="GITHUB_REPOSITORY")], +) -> None: + print("Setting up GitHub Actions git user") + repo = git.Repo(Path(__file__).absolute().parent.parent) + if not repo.is_dirty(untracked_files=True): + print("Repository is clean, no changes to commit") + return + subprocess.run(["git", "config", "user.name", "github-actions"], check=True) + subprocess.run( + ["git", "config", "user.email", "github-actions@github.com"], check=True + ) + branch_name = f"translate-{lang}-{secrets.token_hex(4)}" + print(f"Creating a new branch {branch_name}") + subprocess.run(["git", "checkout", "-b", branch_name], check=True) + print("Adding updated files") + lang_path = Path(f"docs/{lang}") + subprocess.run(["git", "add", str(lang_path)], check=True) + print("Committing updated file") + message = f"🌐 Update translations - {lang}" + subprocess.run(["git", "commit", "-m", message], check=True) + print("Pushing branch") + subprocess.run(["git", "push", "origin", branch_name], check=True) + print("Creating PR") + g = Github(github_token) + gh_repo = g.get_repo(github_repository) + pr = gh_repo.create_pull( + title=message, body=message, base="master", head=branch_name + ) + print(f"Created PR: {pr.number}") + print("Finished") + + if __name__ == "__main__": app() From c74e7d1ce45ddd39e5bf364aa20662855626de14 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Jul 2025 19:12:39 +0000 Subject: [PATCH 287/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f3984fa9e..f7fec547a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). * 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). * 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). From 9aab3d9e2239c51628f580eff442b630bd165d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 28 Jul 2025 01:51:53 +0200 Subject: [PATCH 288/455] =?UTF-8?q?=E2=9A=92=EF=B8=8F=20Tweak=20translate?= =?UTF-8?q?=20script=20and=20CI=20(#13939)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/translate.yml | 4 +- scripts/translate.py | 79 ++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index edbff6fe5..fc6b4d730 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -17,7 +17,7 @@ on: - add-missing - update-and-add - remove-all-removable - lang: + language: description: Language to translate to as a letter code (e.g. "es" for Spanish) type: string required: false @@ -73,5 +73,5 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - LANG: ${{ github.event.inputs.lang }} + LANGUAGE: ${{ github.event.inputs.language }} EN_PATH: ${{ github.event.inputs.en_path }} diff --git a/scripts/translate.py b/scripts/translate.py index 5fdbe7220..e18449685 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -94,12 +94,12 @@ def generate_en_path(*, lang: str, path: Path) -> Path: @app.command() def translate_page( *, - lang: Annotated[str, typer.Option(envvar="LANG")], + language: Annotated[str, typer.Option(envvar="LANGUAGE")], en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], ) -> None: langs = get_langs() - language = langs[lang] - lang_path = Path(f"docs/{lang}") + language_name = langs[language] + lang_path = Path(f"docs/{language}") lang_path.mkdir(exist_ok=True) lang_prompt_path = lang_path / "llm-prompt.md" assert lang_prompt_path.exists(), f"Prompt file not found: {lang_prompt_path}" @@ -109,14 +109,14 @@ def translate_page( assert str(en_path).startswith(str(en_docs_path)), ( f"Path must be inside {en_docs_path}" ) - out_path = generate_lang_path(lang=lang, path=en_path) + out_path = generate_lang_path(lang=language, path=en_path) out_path.parent.mkdir(parents=True, exist_ok=True) original_content = en_path.read_text() old_translation: str | None = None if out_path.exists(): print(f"Found existing translation: {out_path}") old_translation = out_path.read_text() - print(f"Translating {en_path} to {lang} ({language})") + print(f"Translating {en_path} to {language} ({language_name})") agent = Agent("openai:gpt-4o") prompt_segments = [ @@ -135,7 +135,7 @@ def translate_page( ) prompt_segments.extend( [ - f"Translate to {language} ({lang}).", + f"Translate to {language} ({language_name}).", "Original content:", f"%%%\n{original_content}%%%", ] @@ -180,7 +180,7 @@ def iter_en_paths_to_translate() -> Iterable[Path]: @app.command() -def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: +def translate_lang(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: paths_to_process = list(iter_en_paths_to_translate()) print("Original paths:") for p in paths_to_process: @@ -189,7 +189,7 @@ def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: missing_paths: list[Path] = [] skipped_paths: list[Path] = [] for p in paths_to_process: - lang_path = generate_lang_path(lang=lang, path=p) + lang_path = generate_lang_path(lang=language, path=p) if lang_path.exists(): skipped_paths.append(p) continue @@ -204,16 +204,16 @@ def translate_lang(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: print(f"Total paths to process: {len(missing_paths)}") for p in missing_paths: print(f"Translating: {p}") - translate_page(lang="es", en_path=p) + translate_page(language="es", en_path=p) print(f"Done translating: {p}") @app.command() -def list_removable(lang: str) -> list[Path]: +def list_removable(language: str) -> list[Path]: removable_paths: list[Path] = [] - lang_paths = Path(f"docs/{lang}").rglob("*.md") + lang_paths = Path(f"docs/{language}").rglob("*.md") for path in lang_paths: - en_path = generate_en_path(lang=lang, path=path) + en_path = generate_en_path(lang=language, path=path) if not en_path.exists(): removable_paths.append(path) print(removable_paths) @@ -234,8 +234,8 @@ def list_all_removable() -> list[Path]: @app.command() -def remove_removable(lang: str) -> None: - removable_paths = list_removable(lang) +def remove_removable(language: str) -> None: + removable_paths = list_removable(language) for path in removable_paths: path.unlink() print(f"Removed: {path}") @@ -252,11 +252,11 @@ def remove_all_removable() -> None: @app.command() -def list_missing(lang: str) -> list[Path]: +def list_missing(language: str) -> list[Path]: missing_paths: list[Path] = [] en_lang_paths = list(iter_en_paths_to_translate()) for path in en_lang_paths: - lang_path = generate_lang_path(lang=lang, path=path) + lang_path = generate_lang_path(lang=language, path=path) if not lang_path.exists(): missing_paths.append(path) print(missing_paths) @@ -264,14 +264,14 @@ def list_missing(lang: str) -> list[Path]: @app.command() -def list_outdated(lang: str) -> list[Path]: +def list_outdated(language: str) -> list[Path]: dir_path = Path(__file__).absolute().parent.parent repo = git.Repo(dir_path) outdated_paths: list[Path] = [] en_lang_paths = list(iter_en_paths_to_translate()) for path in en_lang_paths: - lang_path = generate_lang_path(lang=lang, path=path) + lang_path = generate_lang_path(lang=language, path=path) if not lang_path.exists(): continue en_commit_datetime = list(repo.iter_commits(paths=path, max_count=1))[ @@ -287,38 +287,38 @@ def list_outdated(lang: str) -> list[Path]: @app.command() -def update_outdated(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: - outdated_paths = list_outdated(lang) +def update_outdated(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + outdated_paths = list_outdated(language) for path in outdated_paths: - print(f"Updating lang: {lang} path: {path}") - translate_page(lang=lang, en_path=path) + print(f"Updating lang: {language} path: {path}") + translate_page(language=language, en_path=path) print(f"Done updating: {path}") print("Done updating all outdated paths") @app.command() -def add_missing(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: - missing_paths = list_missing(lang) +def add_missing(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + missing_paths = list_missing(language) for path in missing_paths: - print(f"Adding lang: {lang} path: {path}") - translate_page(lang=lang, en_path=path) + print(f"Adding lang: {language} path: {path}") + translate_page(language=language, en_path=path) print(f"Done adding: {path}") print("Done adding all missing paths") @app.command() -def update_and_add(lang: Annotated[str, typer.Option(envvar="LANG")]) -> None: - print(f"Updating outdated translations for {lang}") - update_outdated(lang=lang) - print(f"Adding missing translations for {lang}") - add_missing(lang=lang) - print(f"Done updating and adding for {lang}") +def update_and_add(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + print(f"Updating outdated translations for {language}") + update_outdated(language=language) + print(f"Adding missing translations for {language}") + add_missing(language=language) + print(f"Done updating and adding for {language}") @app.command() def make_pr( *, - lang: Annotated[str, typer.Option(envvar="LANG")], + language: Annotated[str | None, typer.Option(envvar="LANGUAGE")] = None, github_token: Annotated[str, typer.Option(envvar="GITHUB_TOKEN")], github_repository: Annotated[str, typer.Option(envvar="GITHUB_REPOSITORY")], ) -> None: @@ -331,14 +331,19 @@ def make_pr( subprocess.run( ["git", "config", "user.email", "github-actions@github.com"], check=True ) - branch_name = f"translate-{lang}-{secrets.token_hex(4)}" + branch_name = "translate" + if language: + branch_name += f"-{language}" + branch_name += f"-{secrets.token_hex(4)}" print(f"Creating a new branch {branch_name}") subprocess.run(["git", "checkout", "-b", branch_name], check=True) print("Adding updated files") - lang_path = Path(f"docs/{lang}") - subprocess.run(["git", "add", str(lang_path)], check=True) + git_path = Path("docs") + subprocess.run(["git", "add", str(git_path)], check=True) print("Committing updated file") - message = f"🌐 Update translations - {lang}" + message = "🌐 Update translations" + if language: + message += f" for {language}" subprocess.run(["git", "commit", "-m", message], check=True) print("Pushing branch") subprocess.run(["git", "push", "origin", branch_name], check=True) From c6566716092b1d98eb5cb1b6827b98b3d378ed8a Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 27 Jul 2025 23:52:18 +0000 Subject: [PATCH 289/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index f7fec547a..c7af5d6fa 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). * 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). * 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). From 616106ca7686821860c5f4d947cf2a9896bc1225 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 22:17:52 +0200 Subject: [PATCH 290/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13943)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.4 → v0.12.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.4...v0.12.5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e461b0133..0f882b221 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.4 + rev: v0.12.5 hooks: - id: ruff args: From 7b2631a88d69ca651d0cf270cde542ec880ae107 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 28 Jul 2025 20:18:19 +0000 Subject: [PATCH 291/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c7af5d6fa..bd8ebf16c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). * 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). From b40acb83c9023af2e52e9b31e63b54db3793447d Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 30 Jul 2025 18:37:49 +0200 Subject: [PATCH 292/455] =?UTF-8?q?=E2=9A=92=EF=B8=8F=20Update=20translate?= =?UTF-8?q?=20script,=20update=20prompt=20to=20minimize=20generated=20diff?= =?UTF-8?q?=20(#13947)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/translate.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/translate.py b/scripts/translate.py index e18449685..2fdc18ca0 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -26,6 +26,8 @@ non_translated_sections = ( general_prompt = """ For technical terms in English that don't have a common translation term use the original term in English. +If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content. + For code snippets or fragments, surrounded by backticks (`), don't translate the content, keep the original in English. For example, `list`, `dict`, keep them as is. The content is written in markdown, write the translation in markdown as well. Don't add triple backticks (`) around the generated translation content. @@ -127,8 +129,15 @@ def translate_page( prompt_segments.extend( [ "There's an existing previous translation for this content that is probably outdated with old content or old instructions.", - "Update the translation given your current instructions and the original content.", - "If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content.", + "Update the translation only where necessary:", + "- If the original English content has changed, reflect that in the translation.", + "- If the previous translation violates current instructions, update it.", + "- Otherwise, preserve the original translation **line-by-line** as-is.", + "Do not:", + "- Rephrase or rewrite correct lines just to improve the style.", + "- Add or remove line breaks unless the English source changed.", + "- Change formatting or whitespace unless absolutely required.", + "Only change what must be changed. The goal is to minimize diffs for easier review.", "Previous translation:", f"%%%\n{old_translation}%%%", ] From 8af92a61399e8d1ac6cfccd600201aca248ea724 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 30 Jul 2025 16:38:11 +0000 Subject: [PATCH 293/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bd8ebf16c..43219f175 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). * 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). From e326cec10ebab167d8ae77cf211b29bfa19e7195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 31 Jul 2025 19:47:31 +0200 Subject: [PATCH 294/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20Add?= =?UTF-8?q?=20Railway=20(#13953)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + docs/en/data/sponsors.yml | 3 +++ docs/en/data/sponsors_badge.yml | 1 + docs/en/docs/deployment/cloud.md | 1 + docs/en/docs/img/sponsors/railway-banner.png | Bin 0 -> 11596 bytes docs/en/docs/img/sponsors/railway.png | Bin 0 -> 26226 bytes docs/en/overrides/main.html | 6 ++++++ 7 files changed, 12 insertions(+) create mode 100644 docs/en/docs/img/sponsors/railway-banner.png create mode 100644 docs/en/docs/img/sponsors/railway.png diff --git a/README.md b/README.md index b3eaa6b35..a0752ed10 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ The key features are: + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 784fd6692..19e8a8e3c 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -29,6 +29,9 @@ gold: - url: https://vibe.mobb.ai/?utm_source=Fast+APi&utm_medium=Image&utm_campaign=MVS title: Secure Your AI-Generated Code to Unlock Dev Productivity img: https://fastapi.tiangolo.com/img/sponsors/mobbai.png + - url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi + title: Deploy enterprise applications at startup speed + img: https://fastapi.tiangolo.com/img/sponsors/railway.png silver: - url: https://databento.com/ title: Pay as you go for market data diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index a8895c8ed..0090e6865 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -44,3 +44,4 @@ logins: - LambdaTest-Inc - dribia - madisonredtfeldt + - railwayapp diff --git a/docs/en/docs/deployment/cloud.md b/docs/en/docs/deployment/cloud.md index d713379c3..c6d408f8c 100644 --- a/docs/en/docs/deployment/cloud.md +++ b/docs/en/docs/deployment/cloud.md @@ -15,3 +15,4 @@ You might want to try their services and follow their guides: * Platform.sh * Porter * Render +* Railway diff --git a/docs/en/docs/img/sponsors/railway-banner.png b/docs/en/docs/img/sponsors/railway-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..f6146a7c1fc50352357367a6de6964fa473acff7 GIT binary patch literal 11596 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

v|w1?s_p#Ev#~&IU|!f!yE=Jl)n% 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 F{{Rhzf!Y87 literal 0 HcmV?d00001 diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 22630e188..12585507d 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -86,6 +86,12 @@ +

{% endblock %} From cf726c93d910513da09c5b7dca93dd0cc40e4333 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 31 Jul 2025 17:47:55 +0000 Subject: [PATCH 295/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 43219f175..a488ebcdd 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). From 8abfa0f106b1f3c40ed858c64cd8035c0b4ac4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 31 Jul 2025 20:20:49 +0200 Subject: [PATCH 296/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20sponsors:=20Dat?= =?UTF-8?q?abento=20link=20and=20sponsors=5Fbadge=20data=20(#13954)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/en/data/sponsors.yml | 2 +- docs/en/data/sponsors_badge.yml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0752ed10..0e421c347 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ The key features are: - + diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 19e8a8e3c..2b3cd282d 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -33,7 +33,7 @@ gold: title: Deploy enterprise applications at startup speed img: https://fastapi.tiangolo.com/img/sponsors/railway.png silver: - - url: https://databento.com/ + - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display title: Pay as you go for market data img: https://fastapi.tiangolo.com/img/sponsors/databento.svg - url: https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index 0090e6865..62ba6a84c 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -45,3 +45,4 @@ logins: - dribia - madisonredtfeldt - railwayapp + - subtotal From 1e4f123eb042cc910b9726ac73ff83e8d012ccbe Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 31 Jul 2025 18:21:09 +0000 Subject: [PATCH 297/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a488ebcdd..72ca423d6 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From a9fbc4b8f508d938bbfe280ee4df6f028194b6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 08:16:58 +0200 Subject: [PATCH 298/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Contributors=20and=20Translators=20(#13955)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/contributors.yml | 20 ++--- docs/en/data/translation_reviewers.yml | 103 +++++++++++++++++-------- docs/en/data/translators.yml | 20 +++-- 3 files changed, 94 insertions(+), 49 deletions(-) diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index e06510ac4..05ff0c7d4 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,21 +1,21 @@ tiangolo: login: tiangolo - count: 753 + count: 768 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 104 + count: 106 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: login: alejsdev - count: 47 + count: 48 avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci - count: 33 + count: 37 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci github-actions: @@ -138,6 +138,11 @@ AlexWendland: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/3949212?u=c4c0c615e0ea33d00bfe16b779cf6ebc0f58071c&v=4 url: https://github.com/AlexWendland +YuriiMotov: + login: YuriiMotov + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov divums: login: divums count: 3 @@ -421,7 +426,7 @@ davidefiocco: adriencaccia: login: adriencaccia count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/19605940?u=980b0b366a02791a5600b2e9f9ac2037679acaa8&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/19605940?u=9a59081f46bfc9d839886a49d5092cf572879049&v=4 url: https://github.com/adriencaccia jamescurtin: login: jamescurtin @@ -553,8 +558,3 @@ blueswen: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1564148?u=6d6b8cc8f2b5cef715e68d6175154a8a94d518ee&v=4 url: https://github.com/blueswen -YuriiMotov: - login: YuriiMotov - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 4f3c95b27..8eaf93d9c 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -10,12 +10,12 @@ Xewus: url: https://github.com/Xewus sodaMelon: login: sodaMelon - count: 126 + count: 127 avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 url: https://github.com/sodaMelon ceb10n: login: ceb10n - count: 112 + count: 116 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n tokusumi: @@ -40,8 +40,8 @@ alv2017: url: https://github.com/alv2017 nazarepiedady: login: nazarepiedady - count: 83 - avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=8dc25777dc9cb51fb0dbba2f137988953d330b78&v=4 + count: 86 + avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=f69ddc4ea8bda3bdfac7aa0e2ea38de282e6ee2d&v=4 url: https://github.com/nazarepiedady AlertRED: login: AlertRED @@ -123,6 +123,11 @@ JavierSanchezCastro: count: 38 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +alejsdev: + login: alejsdev + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 + url: https://github.com/alejsdev stlucasgarcia: login: stlucasgarcia count: 36 @@ -133,11 +138,6 @@ SwftAlpc: count: 36 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc -alejsdev: - login: alejsdev - count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 - url: https://github.com/alejsdev timothy-jeong: login: timothy-jeong count: 36 @@ -178,6 +178,11 @@ LorhanSohaky: count: 30 avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 url: https://github.com/LorhanSohaky +YuriiMotov: + login: YuriiMotov + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov Vincy1230: login: Vincy1230 count: 30 @@ -243,11 +248,6 @@ mycaule: count: 25 avatarUrl: https://avatars.githubusercontent.com/u/6161385?u=e3cec75bd6d938a0d73fae0dc5534d1ab2ed1b0e&v=4 url: https://github.com/mycaule -YuriiMotov: - login: YuriiMotov - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov Aruelius: login: Aruelius count: 24 @@ -548,6 +548,11 @@ KNChiu: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/36751646?v=4 url: https://github.com/KNChiu +maru0123-2004: + login: maru0123-2004 + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 + url: https://github.com/maru0123-2004 mariacamilagl: login: mariacamilagl count: 10 @@ -606,13 +611,8 @@ nick-cjyx9: lucasbalieiro: login: lucasbalieiro count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=eabaf4aebbaa88a94a4886273edba689012cee70&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4 url: https://github.com/lucasbalieiro -maru0123-2004: - login: maru0123-2004 - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 - url: https://github.com/maru0123-2004 Zhongheng-Cheng: login: Zhongheng-Cheng count: 10 @@ -753,11 +753,6 @@ anthonycepeda: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4 url: https://github.com/anthonycepeda -Muaytie666: - login: Muaytie666 - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/198508825?v=4 - url: https://github.com/Muaytie666 fabioueno: login: fabioueno count: 7 @@ -1028,6 +1023,11 @@ devluisrodrigues: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4 url: https://github.com/11kkw +soroushgh1: + login: soroushgh1 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=5e26f6a5f66cdb32d7b56e6ab362bf18ba7858b9&v=4 + url: https://github.com/soroushgh1 lpdswing: login: lpdswing count: 4 @@ -1163,6 +1163,11 @@ cookie-byte217: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/57880178?v=4 url: https://github.com/cookie-byte217 +AbolfazlKameli: + login: AbolfazlKameli + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=05d405115fc834d46260ec24ec7b28e23a13477e&v=4 + url: https://github.com/AbolfazlKameli tyronedamasceno: login: tyronedamasceno count: 3 @@ -1251,7 +1256,7 @@ rafsaf: frnsimoes: login: frnsimoes count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=a405e8f10654251e239a4a1d9dd5bda59216727d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=fd8d408946633acc4bea057c207e6c0833871527&v=4 url: https://github.com/frnsimoes lieryan: login: lieryan @@ -1403,16 +1408,21 @@ tienduong-21: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/80129618?v=4 url: https://github.com/tienduong-21 -soroushgh1: - login: soroushgh1 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=5e26f6a5f66cdb32d7b56e6ab362bf18ba7858b9&v=4 - url: https://github.com/soroushgh1 zbellos: login: zbellos count: 3 avatarUrl: https://avatars.githubusercontent.com/u/204500646?v=4 url: https://github.com/zbellos +Mohammad222PR: + login: Mohammad222PR + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +EdmilsonRodrigues: + login: EdmilsonRodrigues + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues blaisep: login: blaisep count: 2 @@ -1508,11 +1518,11 @@ its0x08: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/15280042?u=d7c2058f29d4e8fbdae09b194e04c5e410350211&v=4 url: https://github.com/its0x08 -lindsayzhou: - login: lindsayzhou +linsein: + login: linsein count: 2 avatarUrl: https://avatars.githubusercontent.com/u/23748021?u=4db169ce262b69aa7292f82b785436544f69fb88&v=4 - url: https://github.com/lindsayzhou + url: https://github.com/linsein 0xflotus: login: 0xflotus count: 2 @@ -1668,6 +1678,11 @@ siavashyj: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4 url: https://github.com/siavashyj +Ramin-RX7: + login: Ramin-RX7 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/52785580?u=b3678f779ad0ee9cd9dca9e50ccb804b5eb990a5&v=4 + url: https://github.com/Ramin-RX7 DevSpace88: login: DevSpace88 count: 2 @@ -1763,6 +1778,11 @@ logan2d5: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/146642263?u=dbd6621f8b0330d6919f6a7131277b92e26fbe87&v=4 url: https://github.com/logan2d5 +guspan-tanadi: + login: guspan-tanadi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36249910?v=4 + url: https://github.com/guspan-tanadi tiaggo16: login: tiaggo16 count: 2 @@ -1793,6 +1813,11 @@ ivintoiu: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 url: https://github.com/ivintoiu +TechnoService2: + login: TechnoService2 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/142113388?v=4 + url: https://github.com/TechnoService2 EgorOnishchuk: login: EgorOnishchuk count: 2 @@ -1818,3 +1843,13 @@ NavesSapnis: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 url: https://github.com/NavesSapnis +eqsdxr: + login: eqsdxr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +syedasamina56: + login: syedasamina56 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/183273097?v=4 + url: https://github.com/syedasamina56 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 3cd6120d0..410c9c826 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -121,7 +121,7 @@ batlopes: lucasbalieiro: login: lucasbalieiro count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=eabaf4aebbaa88a94a4886273edba689012cee70&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4 url: https://github.com/lucasbalieiro Alexandrhub: login: Alexandrhub @@ -208,6 +208,16 @@ k94-ishi: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 url: https://github.com/k94-ishi +Mohammad222PR: + login: Mohammad222PR + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +NavesSapnis: + login: NavesSapnis + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis jfunez: login: jfunez count: 3 @@ -528,8 +538,8 @@ EgorOnishchuk: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 url: https://github.com/EgorOnishchuk -NavesSapnis: - login: NavesSapnis +EdmilsonRodrigues: + login: EdmilsonRodrigues count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 - url: https://github.com/NavesSapnis + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues From a0ede1839abe958544b4b5e9afb1dc6c5608c421 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 1 Aug 2025 06:17:21 +0000 Subject: [PATCH 299/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 72ca423d6..3aae933c1 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). * ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). From 3ad01a124707f05f743a85dfd6544dea79188b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 08:19:53 +0200 Subject: [PATCH 300/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Sponsors=20(#13956)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/github_sponsors.yml | 136 ++++++++++++++----------------- 1 file changed, 59 insertions(+), 77 deletions(-) diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 0cb200185..778ec6a95 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -1,7 +1,4 @@ sponsors: -- - login: classmethod - avatarUrl: https://avatars.githubusercontent.com/u/1532151?v=4 - url: https://github.com/classmethod - - login: renderinc avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 url: https://github.com/renderinc @@ -23,15 +20,15 @@ sponsors: - login: subtotal avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 url: https://github.com/subtotal + - login: railwayapp + avatarUrl: https://avatars.githubusercontent.com/u/66716858?v=4 + url: https://github.com/railwayapp - login: Nixtla avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 url: https://github.com/Nixtla - login: scalar avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 url: https://github.com/scalar -- - login: ObliviousAI - avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 - url: https://github.com/ObliviousAI - - login: dribia avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4 url: https://github.com/dribia @@ -50,10 +47,7 @@ sponsors: - login: permitio avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 url: https://github.com/permitio -- - login: xoflare - avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 - url: https://github.com/xoflare - - login: marvin-robot +- - login: marvin-robot avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4 url: https://github.com/marvin-robot - login: mercedes-benz @@ -62,9 +56,6 @@ sponsors: - login: Ponte-Energy-Partners avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4 url: https://github.com/Ponte-Energy-Partners - - login: snapit-cypher - avatarUrl: https://avatars.githubusercontent.com/u/115662654?v=4 - url: https://github.com/snapit-cypher - login: LambdaTest-Inc avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 url: https://github.com/LambdaTest-Inc @@ -101,24 +92,18 @@ sponsors: - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - - login: CoodingPenguin - avatarUrl: https://avatars.githubusercontent.com/u/37505775?u=6a9e1f6647fbf95f99afeee82a3682e15fc6e959&v=4 - url: https://github.com/CoodingPenguin - - login: deight93 - avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 - url: https://github.com/deight93 - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky - login: ramonalmeidam avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 url: https://github.com/ramonalmeidam - - login: kaoru0310 - avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 - url: https://github.com/kaoru0310 - - login: RaamEEIL - avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 - url: https://github.com/RaamEEIL + - login: roboflow + avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 + url: https://github.com/roboflow + - login: dudikbender + avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 + url: https://github.com/dudikbender - login: ehaca avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 url: https://github.com/ehaca @@ -134,27 +119,21 @@ sponsors: - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure + - login: kaoru0310 + avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 + url: https://github.com/kaoru0310 - login: DelfinaCare avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4 url: https://github.com/DelfinaCare - login: Karine-Bauch avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4 url: https://github.com/Karine-Bauch - - login: eruditis - avatarUrl: https://avatars.githubusercontent.com/u/95244703?v=4 - url: https://github.com/eruditis - login: jugeeem avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4 url: https://github.com/jugeeem - login: logic-automation avatarUrl: https://avatars.githubusercontent.com/u/144732884?v=4 url: https://github.com/logic-automation - - login: roboflow - avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 - url: https://github.com/roboflow - - login: dudikbender - avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 - url: https://github.com/dudikbender - login: patsatsia avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 url: https://github.com/patsatsia @@ -197,6 +176,12 @@ sponsors: - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 url: https://github.com/gorhack + - login: Ryandaydev + avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 + url: https://github.com/Ryandaydev + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog - login: vincentkoc avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 url: https://github.com/vincentkoc @@ -215,9 +200,6 @@ sponsors: - login: pamelafox avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4 url: https://github.com/pamelafox - - login: ericof - avatarUrl: https://avatars.githubusercontent.com/u/306014?u=cf7c8733620397e6584a451505581c01c5d842d7&v=4 - url: https://github.com/ericof - login: wshayes avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes @@ -251,12 +233,9 @@ sponsors: - login: ashi-agrawal avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 url: https://github.com/ashi-agrawal - - login: Ryandaydev - avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 - url: https://github.com/Ryandaydev - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog + - login: RaamEEIL + avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 + url: https://github.com/RaamEEIL - login: oliverxchen avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 url: https://github.com/oliverxchen @@ -275,9 +254,9 @@ sponsors: - login: hiancdtrsnm avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4 url: https://github.com/hiancdtrsnm -- - login: jpizquierdo - avatarUrl: https://avatars.githubusercontent.com/u/6716239?v=4 - url: https://github.com/jpizquierdo +- - login: manoelpqueiroz + avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4 + url: https://github.com/manoelpqueiroz - - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy @@ -296,9 +275,9 @@ sponsors: - login: caviri avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 url: https://github.com/caviri - - login: joshuatz - avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 - url: https://github.com/joshuatz + - login: hgalytoby + avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 + url: https://github.com/hgalytoby - login: SebTota avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 url: https://github.com/SebTota @@ -320,21 +299,15 @@ sponsors: - login: bnkc avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4 url: https://github.com/bnkc - - login: lukzmu - avatarUrl: https://avatars.githubusercontent.com/u/175964415?u=75348f25bb99a5f92ddb40c0b9b1ff7acb39c150&v=4 - url: https://github.com/lukzmu - - login: hgalytoby - avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 - url: https://github.com/hgalytoby + - login: johnl28 + avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4 + url: https://github.com/johnl28 - login: PunRabbit avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4 url: https://github.com/PunRabbit - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ - - login: browniebroke - avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 - url: https://github.com/browniebroke - login: miguelgr avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 url: https://github.com/miguelgr @@ -362,12 +335,6 @@ sponsors: - login: tochikuji avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 url: https://github.com/tochikuji - - login: moonape1226 - avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 - url: https://github.com/moonape1226 - - login: msehnout - avatarUrl: https://avatars.githubusercontent.com/u/9369632?u=8c988f1b008a3f601385a3616f9327820f66e3a5&v=4 - url: https://github.com/msehnout - login: xncbf avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 url: https://github.com/xncbf @@ -389,12 +356,12 @@ sponsors: - login: Zuzah avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4 url: https://github.com/Zuzah - - login: artempronevskiy - avatarUrl: https://avatars.githubusercontent.com/u/12235104?u=03df6e1e55c9c6fe5d230adabb8dd7d43d8bbe8f&v=4 - url: https://github.com/artempronevskiy - login: TheR1D avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4 url: https://github.com/TheR1D + - login: joshuatz + avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 + url: https://github.com/joshuatz - login: danielunderwood avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 url: https://github.com/danielunderwood @@ -419,39 +386,54 @@ sponsors: - login: harsh183 avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 url: https://github.com/harsh183 + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 - - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba + - login: KOZ39 + avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 + url: https://github.com/KOZ39 - login: rwxd avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 url: https://github.com/rwxd - login: morzan1001 avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 url: https://github.com/morzan1001 - - login: sadikkuzu - avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 - url: https://github.com/sadikkuzu - login: Olegt0rr avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 url: https://github.com/Olegt0rr - login: larsyngvelundin avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 url: https://github.com/larsyngvelundin + - login: v4lerdon + avatarUrl: https://avatars.githubusercontent.com/u/98405746?u=10969728d51e8f08e203f5d65fda948c21545c73&v=4 + url: https://github.com/v4lerdon + - login: hauanitech + avatarUrl: https://avatars.githubusercontent.com/u/211940501?u=48f70c3ef9b89c598d2dde528cda2d4f6468a135&v=4 + url: https://github.com/hauanitech + - login: igor-kan + avatarUrl: https://avatars.githubusercontent.com/u/61065863?u=3bade33799d183510fd381e2e4f5e1b61af8631a&v=4 + url: https://github.com/igor-kan - login: 0ne-stone avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 url: https://github.com/0ne-stone - - login: darixsamani - avatarUrl: https://avatars.githubusercontent.com/u/67915678?u=cfa82128692eeeec4bf0e7a0faaa9a614695c0f9&v=4 - url: https://github.com/darixsamani + - login: t3llscode + avatarUrl: https://avatars.githubusercontent.com/u/65864434?u=35df974cec16993343bf6494d60a14e71f66c5af&v=4 + url: https://github.com/t3llscode - login: nayasinghania - avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=af853245a21fe052b6a27e41a8de8cf4cdf76e85&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4 url: https://github.com/nayasinghania - login: Toothwitch avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 url: https://github.com/Toothwitch - - login: roboman-tech - avatarUrl: https://avatars.githubusercontent.com/u/8183070?u=fdeaa2ed29f598eb7901693884c0ad32b16982e3&v=4 - url: https://github.com/roboman-tech - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi + - login: sadikkuzu + avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 + url: https://github.com/sadikkuzu + - login: roboman-tech + avatarUrl: https://avatars.githubusercontent.com/u/8183070?u=fdeaa2ed29f598eb7901693884c0ad32b16982e3&v=4 + url: https://github.com/roboman-tech From 1c1c2e8ab971a2d650032260d4d39a124e28aa17 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 1 Aug 2025 06:20:13 +0000 Subject: [PATCH 301/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3aae933c1..a81b54a65 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). From 79d2576508b62ff8918db358756694d73e55b9af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 08:22:27 +0200 Subject: [PATCH 302/455] =?UTF-8?q?=E2=AC=86=20Bump=20tiangolo/latest-chan?= =?UTF-8?q?ges=20from=200.3.2=20to=200.4.0=20(#13952)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [tiangolo/latest-changes](https://github.com/tiangolo/latest-changes) from 0.3.2 to 0.4.0. - [Release notes](https://github.com/tiangolo/latest-changes/releases) - [Commits](https://github.com/tiangolo/latest-changes/compare/0.3.2...0.4.0) --- updated-dependencies: - dependency-name: tiangolo/latest-changes dependency-version: 0.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/latest-changes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index b8b5c42ee..208ab0c65 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -34,7 +34,7 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - - uses: tiangolo/latest-changes@0.3.2 + - uses: tiangolo/latest-changes@0.4.0 with: token: ${{ secrets.GITHUB_TOKEN }} latest_changes_file: docs/en/docs/release-notes.md From 6e69d62bfeb538cb82e9c69f53e939a25268cf79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 06:22:46 +0000 Subject: [PATCH 303/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index a81b54a65..8bc413f26 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). From e7401d2e4283211c3d53faa6915415327b0957c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:09:18 +0200 Subject: [PATCH 304/455] =?UTF-8?q?=E2=AC=86=20Bump=20mkdocs-material=20fr?= =?UTF-8?q?om=209.6.15=20to=209.6.16=20(#13961)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.15 to 9.6.16. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.6.15...9.6.16) --- updated-dependencies: - dependency-name: mkdocs-material dependency-version: 9.6.16 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 5c5701f73..4713d187e 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,6 +1,6 @@ -e . -r requirements-docs-tests.txt -mkdocs-material==9.6.15 +mkdocs-material==9.6.16 mdx-include >=1.4.1,<2.0.0 mkdocs-redirects>=1.2.1,<1.3.0 typer == 0.16.0 From d07159797b4eef6a38ec09b351c3cc1c7669bad3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 13:09:46 +0000 Subject: [PATCH 305/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8bc413f26..170e579b5 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). From 2e16e105c9a0085d4deb952e39a78d919a29c3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 15:19:22 +0200 Subject: [PATCH 306/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20GitHu?= =?UTF-8?q?b=20topic=20repositories=20(#13962)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/topic_repos.yml | 384 +++++++++++++++++------------------ 1 file changed, 192 insertions(+), 192 deletions(-) diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index ab9f21995..631edbb77 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,91 +1,96 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 34156 + stars: 35002 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 30835 + stars: 31317 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21631 + stars: 21680 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 18125 + stars: 18700 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 16249 + stars: 16469 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: 13279 + stars: 13663 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 12334 + stars: 12716 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 9934 + stars: 10099 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8838 + stars: 8850 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 7962 + stars: 8305 owner_login: JoeanAmier owner_html_url: https://github.com/JoeanAmier -- name: nonebot2 - html_url: https://github.com/nonebot/nonebot2 - stars: 6834 - owner_login: nonebot - owner_html_url: https://github.com/nonebot - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 6783 + stars: 6936 owner_login: vastsa owner_html_url: https://github.com/vastsa +- name: nonebot2 + html_url: https://github.com/nonebot/nonebot2 + stars: 6911 + owner_login: nonebot + owner_html_url: https://github.com/nonebot - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 5846 + stars: 6767 owner_login: tadata-org owner_html_url: https://github.com/tadata-org +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 6202 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 5773 + stars: 5878 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev -- name: serge - html_url: https://github.com/serge-chat/serge - stars: 5728 - owner_login: serge-chat - owner_html_url: https://github.com/serge-chat - name: polar html_url: https://github.com/polarsource/polar - stars: 5709 + stars: 5872 owner_login: polarsource owner_html_url: https://github.com/polarsource +- name: serge + html_url: https://github.com/serge-chat/serge + stars: 5740 + owner_login: serge-chat + owner_html_url: https://github.com/serge-chat - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 5336 + stars: 5429 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4317 + stars: 4345 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql - name: chatgpt-web-share @@ -93,184 +98,184 @@ stars: 4301 owner_login: chatpire owner_html_url: https://github.com/chatpire +- name: poem + html_url: https://github.com/poem-web/poem + stars: 4107 + owner_login: poem-web + owner_html_url: https://github.com/poem-web - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4106 + stars: 4103 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 4045 + stars: 4079 owner_login: dynaconf owner_html_url: https://github.com/dynaconf -- name: poem - html_url: https://github.com/poem-web/poem - stars: 4037 - owner_login: poem-web - owner_html_url: https://github.com/poem-web -- name: farfalle - html_url: https://github.com/rashadphz/farfalle - stars: 3348 - owner_login: rashadphz - owner_html_url: https://github.com/rashadphz - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3347 + stars: 3430 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: 3309 - 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: 3291 - owner_login: koxudaxi - owner_html_url: https://github.com/koxudaxi - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3288 + stars: 3420 owner_login: pydantic owner_html_url: https://github.com/pydantic +- name: farfalle + html_url: https://github.com/rashadphz/farfalle + stars: 3391 + owner_login: rashadphz + owner_html_url: https://github.com/rashadphz +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 3375 + owner_login: remsky + owner_html_url: https://github.com/remsky +- name: datamodel-code-generator + html_url: https://github.com/koxudaxi/datamodel-code-generator + stars: 3354 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi +- name: fastapi-admin + html_url: https://github.com/fastapi-admin/fastapi-admin + stars: 3353 + owner_login: fastapi-admin + owner_html_url: https://github.com/fastapi-admin - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3201 + stars: 3277 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor - name: opyrator html_url: https://github.com/ml-tooling/opyrator - stars: 3132 + stars: 3131 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 3099 - owner_login: remsky - owner_html_url: https://github.com/remsky - name: docarray html_url: https://github.com/docarray/docarray - stars: 3075 + stars: 3085 owner_login: docarray owner_html_url: https://github.com/docarray -- name: fastapi-realworld-example-app - html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2902 - owner_login: nsidnev - owner_html_url: https://github.com/nsidnev - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 2888 + stars: 2921 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ +- name: fastapi-realworld-example-app + html_url: https://github.com/nsidnev/fastapi-realworld-example-app + stars: 2919 + 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: 2775 + stars: 2789 owner_login: tiangolo owner_html_url: https://github.com/tiangolo - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2537 + stars: 2560 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2427 + stars: 2434 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2397 + stars: 2419 owner_login: Buuntu owner_html_url: https://github.com/Buuntu - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2334 + stars: 2369 owner_login: s3rius owner_html_url: https://github.com/s3rius - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2295 + stars: 2304 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2235 + stars: 2272 owner_login: aminalaee owner_html_url: https://github.com/aminalaee - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2181 + stars: 2192 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs +- name: supabase-py + html_url: https://github.com/supabase/supabase-py + stars: 2141 + owner_login: supabase + owner_html_url: https://github.com/supabase - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2119 + stars: 2140 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2100 + stars: 2107 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils -- name: supabase-py - html_url: https://github.com/supabase/supabase-py - stars: 2084 - owner_login: supabase - owner_html_url: https://github.com/supabase - name: solara html_url: https://github.com/widgetti/solara - stars: 2056 + stars: 2063 owner_login: widgetti owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1923 + stars: 1943 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1821 + stars: 1819 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1765 + stars: 1774 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: 1756 + stars: 1769 owner_login: ycd owner_html_url: https://github.com/ycd - name: ormar html_url: https://github.com/collerek/ormar - stars: 1755 + stars: 1761 owner_login: collerek owner_html_url: https://github.com/collerek -- name: langchain-serve - html_url: https://github.com/jina-ai/langchain-serve - stars: 1631 - owner_login: jina-ai - owner_html_url: https://github.com/jina-ai - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1629 + stars: 1658 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm -- name: termpair - html_url: https://github.com/cs01/termpair - stars: 1616 - owner_login: cs01 - owner_html_url: https://github.com/cs01 +- name: langchain-serve + html_url: https://github.com/jina-ai/langchain-serve + stars: 1632 + owner_login: jina-ai + owner_html_url: https://github.com/jina-ai - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1603 + stars: 1628 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators +- name: termpair + html_url: https://github.com/cs01/termpair + stars: 1617 + owner_login: cs01 + owner_html_url: https://github.com/cs01 - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1589 + stars: 1607 owner_login: long2ice owner_html_url: https://github.com/long2ice - name: coronavirus-tracker-api @@ -280,137 +285,152 @@ owner_html_url: https://github.com/ExpDev07 - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1533 + stars: 1551 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1518 + stars: 1522 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: awesome-fastapi-projects - html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1461 - owner_login: Kludex - owner_html_url: https://github.com/Kludex - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1409 + stars: 1505 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao +- name: awesome-fastapi-projects + html_url: https://github.com/Kludex/awesome-fastapi-projects + stars: 1468 + owner_login: Kludex + owner_html_url: https://github.com/Kludex - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1393 + stars: 1403 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1378 + stars: 1396 owner_login: uriyyo owner_html_url: https://github.com/uriyyo +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1378 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1348 + stars: 1373 owner_login: teamhide owner_html_url: https://github.com/teamhide +- name: bracket + html_url: https://github.com/evroon/bracket + stars: 1367 + owner_login: evroon + owner_html_url: https://github.com/evroon - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1344 + stars: 1345 owner_login: ebhy owner_html_url: https://github.com/ebhy - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1284 + stars: 1300 owner_login: amisadmin owner_html_url: https://github.com/amisadmin -- name: bracket - html_url: https://github.com/evroon/bracket - stars: 1274 - owner_login: evroon - owner_html_url: https://github.com/evroon - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1265 + stars: 1284 owner_login: liaogx owner_html_url: https://github.com/liaogx - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1216 + stars: 1232 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: bolt-python - html_url: https://github.com/slackapi/bolt-python - stars: 1190 - owner_login: slackapi - owner_html_url: https://github.com/slackapi - name: fastcrud html_url: https://github.com/benavlabs/fastcrud - stars: 1169 + stars: 1208 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1167 + stars: 1200 owner_login: trallnag owner_html_url: https://github.com/trallnag -- name: fastapi_production_template - html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1165 - owner_login: zhanymkanov - owner_html_url: https://github.com/zhanymkanov +- name: bolt-python + html_url: https://github.com/slackapi/bolt-python + stars: 1197 + owner_login: slackapi + owner_html_url: https://github.com/slackapi - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1163 + stars: 1188 owner_login: aws-samples owner_html_url: https://github.com/aws-samples -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1142 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai -- name: odmantic - html_url: https://github.com/art049/odmantic - stars: 1121 - owner_login: art049 - owner_html_url: https://github.com/art049 - name: fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 1118 + stars: 1178 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices +- name: fastapi_production_template + html_url: https://github.com/zhanymkanov/fastapi_production_template + stars: 1173 + owner_login: zhanymkanov + owner_html_url: https://github.com/zhanymkanov +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1148 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1116 + stars: 1134 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 -- name: FastAPI-boilerplate - html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1070 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs +- name: odmantic + html_url: https://github.com/art049/odmantic + stars: 1122 + owner_login: art049 + owner_html_url: https://github.com/art049 - name: restish html_url: https://github.com/rest-sh/restish - stars: 1069 + stars: 1088 owner_login: rest-sh owner_html_url: https://github.com/rest-sh +- name: fastapi-scaf + html_url: https://github.com/atpuxiner/fastapi-scaf + stars: 1061 + owner_login: atpuxiner + owner_html_url: https://github.com/atpuxiner - name: runhouse html_url: https://github.com/run-house/runhouse - stars: 1037 + stars: 1041 owner_login: run-house owner_html_url: https://github.com/run-house +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 1037 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: autollm html_url: https://github.com/viddexa/autollm - stars: 994 + stars: 997 owner_login: viddexa owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 992 + stars: 994 owner_login: ajndkr owner_html_url: https://github.com/ajndkr +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge + stars: 981 + owner_login: IBM + owner_html_url: https://github.com/IBM - name: authx html_url: https://github.com/yezz123/authx - stars: 953 + stars: 967 owner_login: yezz123 owner_html_url: https://github.com/yezz123 - name: secure @@ -418,78 +438,58 @@ stars: 941 owner_login: TypeError owner_html_url: https://github.com/TypeError +- name: flock + html_url: https://github.com/Onelevenvy/flock + stars: 937 + owner_login: Onelevenvy + owner_html_url: https://github.com/Onelevenvy - name: energy-forecasting html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 928 + stars: 934 owner_login: iusztinpaul owner_html_url: https://github.com/iusztinpaul - name: langcorn html_url: https://github.com/msoedov/langcorn - stars: 927 + stars: 932 owner_login: msoedov owner_html_url: https://github.com/msoedov - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 901 + stars: 917 owner_login: developmentseed owner_html_url: https://github.com/developmentseed -- name: flock - html_url: https://github.com/Onelevenvy/flock - stars: 896 - owner_login: Onelevenvy - owner_html_url: https://github.com/Onelevenvy -- name: fastapi-langgraph-agent-production-ready-template - html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 896 - owner_login: wassim249 - owner_html_url: https://github.com/wassim249 - name: marker-api html_url: https://github.com/adithya-s-k/marker-api - stars: 875 + stars: 880 owner_login: adithya-s-k owner_html_url: https://github.com/adithya-s-k - name: httpdbg html_url: https://github.com/cle-b/httpdbg - stars: 870 + stars: 875 owner_login: cle-b owner_html_url: https://github.com/cle-b - name: fastapi-do-zero html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 855 + stars: 873 owner_login: dunossauro owner_html_url: https://github.com/dunossauro -- name: ludic - html_url: https://github.com/getludic/ludic - stars: 849 - owner_login: getludic - owner_html_url: https://github.com/getludic - name: fastapi-observability html_url: https://github.com/blueswen/fastapi-observability - stars: 837 + stars: 861 owner_login: blueswen owner_html_url: https://github.com/blueswen -- name: fastapi-scaf - html_url: https://github.com/atpuxiner/fastapi-scaf - stars: 821 - owner_login: atpuxiner - owner_html_url: https://github.com/atpuxiner -- name: starlette-admin - html_url: https://github.com/jowilf/starlette-admin - stars: 808 - owner_login: jowilf - owner_html_url: https://github.com/jowilf -- name: fastapi-mail - html_url: https://github.com/sabuhish/fastapi-mail - stars: 807 - owner_login: sabuhish - owner_html_url: https://github.com/sabuhish +- name: ludic + html_url: https://github.com/getludic/ludic + stars: 854 + owner_login: getludic + owner_html_url: https://github.com/getludic - name: aktools html_url: https://github.com/akfamily/aktools - stars: 796 + stars: 839 owner_login: akfamily owner_html_url: https://github.com/akfamily - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 782 + stars: 836 owner_login: insistence owner_html_url: https://github.com/insistence From 92ea53baca590b7a9a61c4b7f0530a1dc7a68e02 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 13:19:48 +0000 Subject: [PATCH 307/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 170e579b5..9b64aeb32 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). From b42e28753e4f6b810e9f8a876e02ff6fc1ec434a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 15:50:16 +0200 Subject: [PATCH 308/455] =?UTF-8?q?=E2=AC=86=20Bump=20pydantic-ai=20from?= =?UTF-8?q?=200.0.30=20to=200.4.10=20(#13958)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pydantic-ai](https://github.com/pydantic/pydantic-ai) from 0.0.30 to 0.4.10. - [Release notes](https://github.com/pydantic/pydantic-ai/releases) - [Changelog](https://github.com/pydantic/pydantic-ai/blob/main/docs/changelog.md) - [Commits](https://github.com/pydantic/pydantic-ai/compare/v0.0.30...v0.4.10) --- updated-dependencies: - dependency-name: pydantic-ai dependency-version: 0.4.10 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-translations.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-translations.txt b/requirements-translations.txt index 90f718032..a62ba3ac1 100644 --- a/requirements-translations.txt +++ b/requirements-translations.txt @@ -1,2 +1,2 @@ -pydantic-ai==0.0.30 +pydantic-ai==0.4.10 GitPython==3.1.45 From 391887db91d9873db6a927b8d905b6d25e7ac882 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 13:50:42 +0000 Subject: [PATCH 309/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 9b64aeb32..d4e17f549 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). From f8013621ccfff954fba1061c13dde96105ec221c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 16:06:33 +0200 Subject: [PATCH 310/455] =?UTF-8?q?=E2=AC=86=20Bump=20cairosvg=20from=202.?= =?UTF-8?q?7.1=20to=202.8.2=20(#13959)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [cairosvg](https://github.com/Kozea/CairoSVG) from 2.7.1 to 2.8.2. - [Release notes](https://github.com/Kozea/CairoSVG/releases) - [Changelog](https://github.com/Kozea/CairoSVG/blob/main/NEWS.rst) - [Commits](https://github.com/Kozea/CairoSVG/compare/2.7.1...2.8.2) --- updated-dependencies: - dependency-name: cairosvg dependency-version: 2.8.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 4713d187e..eeb41b5ce 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -10,7 +10,7 @@ jieba==0.42.1 # For image processing by Material for MkDocs pillow==11.3.0 # For image processing by Material for MkDocs -cairosvg==2.7.1 +cairosvg==2.8.2 mkdocstrings[python]==0.26.1 griffe-typingdoc==0.2.8 # For griffe, it formats with black From 37dd99ffe39356e2263bc8f0ab006560184db740 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 14:06:58 +0000 Subject: [PATCH 311/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d4e17f549..c76b31323 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). From 11893d9cea2d8dabcc5dc9071624f64c0a11a5e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 16:09:11 +0200 Subject: [PATCH 312/455] =?UTF-8?q?=E2=AC=86=20Bump=20ruff=20from=200.11.2?= =?UTF-8?q?=20to=200.12.7=20(#13957)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.2 to 0.12.7. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.11.2...0.12.7) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.12.7 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements-docs-tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs-tests.txt b/requirements-docs-tests.txt index e7684a2e3..f9a490975 100644 --- a/requirements-docs-tests.txt +++ b/requirements-docs-tests.txt @@ -1,4 +1,4 @@ # For mkdocstrings and tests httpx >=0.23.0,<0.29.0 # For linting and generating docs versions -ruff ==0.11.2 +ruff ==0.12.7 From c40bd0e426ee803ef56be9848276e86ab3d603dc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 14:09:56 +0000 Subject: [PATCH 313/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c76b31323..bb228270c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). From f736e48ab3e46684bf379407e27a1bd7f300a865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 1 Aug 2025 16:32:33 +0200 Subject: [PATCH 314/455] =?UTF-8?q?=F0=9F=91=A5=20Update=20FastAPI=20Peopl?= =?UTF-8?q?e=20-=20Experts=20(#13963)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions --- docs/en/data/people.yml | 320 ++++++++++++++++++++-------------------- 1 file changed, 156 insertions(+), 164 deletions(-) diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index e3eab5d01..714d2eac7 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -9,8 +9,8 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo - login: YuriiMotov - count: 941 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 952 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: github-actions count: 769 @@ -53,11 +53,11 @@ experts: avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 93 + count: 94 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro - login: luzzodev - count: 84 + count: 87 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: raphaelauv @@ -192,6 +192,14 @@ experts: count: 19 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: sehraramiz + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz - login: retnikt count: 18 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 @@ -200,10 +208,6 @@ experts: count: 18 avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 url: https://github.com/zoliknemet -- login: sehraramiz - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz - login: Hultner count: 17 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 @@ -228,6 +232,10 @@ experts: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 url: https://github.com/jonatasoli +- login: abhint + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 + url: https://github.com/abhint - login: ghost count: 15 avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4 @@ -236,31 +244,52 @@ experts: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 url: https://github.com/jorgerpo -- login: pythonweb2 - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 -- login: abhint - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 - url: https://github.com/abhint last_month_experts: - login: YuriiMotov - count: 289 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 69 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 12 + count: 8 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev +- login: valentinDruzhinin + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: eqsdxr + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R +three_months_experts: +- login: YuriiMotov + count: 736 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov +- login: luzzodev + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin - login: raceychan count: 6 avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 url: https://github.com/raceychan -- login: valentinDruzhinin - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin +- login: sachinh35 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 - login: DoctorJohn count: 5 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 @@ -269,59 +298,30 @@ last_month_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 url: https://github.com/eqsdxr -- login: sachinh35 - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: JavierSanchezCastro + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: purepani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani - login: tiangolo count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo -- login: Brikas - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 - url: https://github.com/Brikas - login: TaigoFr count: 2 avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 url: https://github.com/TaigoFr -three_months_experts: -- login: YuriiMotov - count: 732 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov -- login: luzzodev - count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 - url: https://github.com/luzzodev -- login: valentinDruzhinin - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin -- login: sachinh35 - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 - url: https://github.com/sachinh35 -- login: raceychan - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 - url: https://github.com/raceychan -- login: DoctorJohn - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 - url: https://github.com/DoctorJohn -- login: eqsdxr - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 - url: https://github.com/eqsdxr -- login: tiangolo +- login: Garrett-R count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: JavierSanchezCastro - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R - login: henrymcl count: 2 avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 @@ -334,47 +334,39 @@ three_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 url: https://github.com/Brikas -- login: TaigoFr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr - login: davidhuser count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 url: https://github.com/davidhuser -- login: KianAnbarestani - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani - login: Kludex count: 2 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex six_months_experts: - login: YuriiMotov - count: 749 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 754 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: luzzodev count: 51 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: alv2017 - count: 26 + count: 23 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -- login: Kludex - count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex - login: valentinDruzhinin - count: 14 + count: 19 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin - login: jgould22 count: 13 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 +- login: Kludex + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex - login: JavierSanchezCastro count: 10 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 @@ -399,18 +391,34 @@ six_months_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 url: https://github.com/DoctorJohn -- login: sehraramiz - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz - login: eqsdxr count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 url: https://github.com/eqsdxr +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe +- login: purepani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani +- login: WilliamDEdwards + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: TaigoFr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R - login: EverStarck count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 @@ -435,10 +443,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 url: https://github.com/JacobHayes -- login: TaigoFr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr - login: davidhuser count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 @@ -451,10 +455,6 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 url: https://github.com/KianAnbarestani -- login: Ykaiqx - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/Ykaiqx - login: sinisaos count: 2 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 @@ -463,71 +463,63 @@ six_months_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 url: https://github.com/Ale-Cas -- login: nbx3 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 - login: marsboy02 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=efe3aa9e4b22689df7633a96328fb35bf4a23905&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=04cc319d6605f8d1ba3a0bed9f4f55a582719ae6&v=4 url: https://github.com/marsboy02 - login: vtgn count: 2 avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 url: https://github.com/vtgn -- login: Trinkes - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9466879?v=4 - url: https://github.com/Trinkes one_year_experts: - login: YuriiMotov - count: 831 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 820 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov - login: luzzodev - count: 84 + count: 87 avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev - login: Kludex - count: 55 + count: 51 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: sinisaos - count: 41 + count: 39 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos +- login: JavierSanchezCastro + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro - login: alv2017 count: 26 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -- login: JavierSanchezCastro - count: 25 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro - login: tiangolo - count: 22 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin - login: jgould22 count: 17 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 -- login: valentinDruzhinin - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin - login: Kfir-G count: 13 avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 url: https://github.com/Kfir-G -- login: estebanx64 - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 - login: sehraramiz count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz +- login: estebanx64 + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 + url: https://github.com/estebanx64 - login: ceb10n count: 10 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 @@ -541,7 +533,7 @@ one_year_experts: avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 url: https://github.com/yauhen-sobaleu - login: n8sty - count: 8 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty - login: yvallois @@ -556,10 +548,6 @@ one_year_experts: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 url: https://github.com/DoctorJohn -- login: AIdjis - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 - url: https://github.com/AIdjis - login: eqsdxr count: 4 avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 @@ -572,10 +560,6 @@ one_year_experts: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=4ba43bd63c169b5c015137d8916752a44001445a&v=4 url: https://github.com/yokwejuste -- login: PhysicallyActive - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 - url: https://github.com/PhysicallyActive - login: svlandeg count: 4 avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 @@ -584,13 +568,17 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 url: https://github.com/mattmess1221 +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB - login: pythonweb2 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 url: https://github.com/pythonweb2 - login: viniciusCalcantara count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=80f3ec7427fa6a41d5896984d0c526432f2299fa&v=4 url: https://github.com/viniciusCalcantara - login: davidhuser count: 3 @@ -604,14 +592,14 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 url: https://github.com/dbfreem +- login: PhysicallyActive + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 + url: https://github.com/PhysicallyActive - login: SobikXexe count: 3 avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 url: https://github.com/SobikXexe -- login: DeoLeung - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 - url: https://github.com/DeoLeung - login: pawelad count: 3 avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 @@ -624,10 +612,42 @@ one_year_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 url: https://github.com/Minibrams +- login: AIdjis + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 + url: https://github.com/AIdjis +- login: dolfinus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus +- login: slafs + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 + url: https://github.com/slafs +- login: purepani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani +- login: ddahan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 + url: https://github.com/ddahan - login: yanggeorge count: 2 avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 url: https://github.com/yanggeorge +- login: WilliamDEdwards + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: TaigoFr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R - login: mmzeynalli count: 2 avatarUrl: https://avatars.githubusercontent.com/u/33568903?u=19efd0c0722730b83a70b7c86c36e5b7d83e07d2&v=4 @@ -640,10 +660,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 url: https://github.com/EverStarck -- login: slafs - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs - login: henrymcl count: 2 avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 @@ -676,10 +692,6 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 url: https://github.com/JacobHayes -- login: TaigoFr - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 - url: https://github.com/TaigoFr - login: rlimberger count: 2 avatarUrl: https://avatars.githubusercontent.com/u/4841242?u=6a13252caf3cedceb07b6e2775b6592445d13b70&v=4 @@ -700,23 +712,3 @@ one_year_experts: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 url: https://github.com/PidgeyBE -- login: KianAnbarestani - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 - url: https://github.com/KianAnbarestani -- login: Ykaiqx - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=1eebf5ce25a8067f7bfa6251a24f667be492d9d6&v=4 - url: https://github.com/Ykaiqx -- login: AliYmn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=a77e2605e3ce6aaf6fef8ad4a7b0d32954fba47a&v=4 - url: https://github.com/AliYmn -- login: dolfinus - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 - url: https://github.com/dolfinus -- login: gelezo43 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 - url: https://github.com/gelezo43 From 6df50d40fe195adc026af169d6ebf298a1c183a5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 1 Aug 2025 14:32:59 +0000 Subject: [PATCH 315/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bb228270c..b57ff80f0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). From 5c8d5214ff6a45e269c482b1940a46a931fda995 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 07:43:20 +0200 Subject: [PATCH 316/455] =?UTF-8?q?=E2=AC=86=20Bump=20actions/download-art?= =?UTF-8?q?ifact=20from=204=20to=205=20(#13975)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy-docs.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 9ca69b208..c088d4ad1 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -48,7 +48,7 @@ jobs: run: | rm -rf ./site mkdir ./site - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: path: ./site/ pattern: docs-site-* diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index d8a5dfb30..4788b4f1b 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -34,7 +34,7 @@ jobs: requirements**.txt pyproject.toml - run: uv pip install -r requirements-github-actions.txt - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: coverage-html path: htmlcov diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c3940be01..1f9df620c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -122,7 +122,7 @@ jobs: - name: Install Dependencies run: uv pip install -r requirements-tests.txt - name: Get coverage files - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: pattern: coverage-* path: coverage From 6cee687a7903aad5678a7beeb76929c2af417b22 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 Aug 2025 05:43:40 +0000 Subject: [PATCH 317/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b57ff80f0..1a116c720 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). From 6ccad060814a7a9c5170f1f37e38eb42b93f76f0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 07:44:02 +0200 Subject: [PATCH 318/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13969)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.5 → v0.12.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.5...v0.12.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f882b221..c2e628466 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.5 + rev: v0.12.7 hooks: - id: ruff args: From 12b36a048c5433d7555294a67ed8bc159ceb1383 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 Aug 2025 05:44:22 +0000 Subject: [PATCH 319/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1a116c720..8458d3547 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). From ba0f6121b97876ecda096afdfca94628223d9c23 Mon Sep 17 00:00:00 2001 From: Chai Landau <112015853+chailandau@users.noreply.github.com> Date: Fri, 8 Aug 2025 01:48:21 -0400 Subject: [PATCH 320/455] =?UTF-8?q?=F0=9F=94=A7=20Update=20Speakeasy=20spo?= =?UTF-8?q?nsor=20graphic=20(#13971)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/img/sponsors/speakeasy.png | Bin 11887 -> 18817 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/en/docs/img/sponsors/speakeasy.png b/docs/en/docs/img/sponsors/speakeasy.png index 5ddc25487b6b52ea5da49effe465605de207ee3d..7bb9c3a18e1efa4f7d65c3c2ba8a817a3a4f71dc 100644 GIT binary patch literal 18817 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
lE-+3E5_5E z@({rTx?dreyh)b#*3Qm!jTw_?e3X&*I9-6rm@QsAcHAv3FZ&lR*2ouMTw3x+rr_m^ zrShe5KD7{TGtvj-HbY4lmlnx&?)!VV({Q5^`V_}RFDw+h`1z9!y$jvGBf;?BVKxgU zdnM)>y0YQ8^Eg^OKN4pN(P8=U?5hk%J%U;HP~zfe9nbi@;pjY)7717LJyc)KFMcP0(R*0@d1+S249f>o=x2|!Vi^)94r{+~moXDP zpfT}~mXTm1hB(ANFI?#rlEF<{^1;p=_?Q9Z@oNP-Us=}%>jdf1Qm5nJz`_#J8Vx;R z(YqACK=I8|-=?$CPW4S8t0R%8S_jQw|HV-GW)#2b2xVh;TH}a$1eO3z@5?EFUJowP z3%5EJ@;u!Ymgym0RON|T@>I)M#eWMYhg6)FJ8RV^MqjF>4bha!H(gf3oCmKC_>Px9 zNWi#uk7O1TPq2*q@Dw>8W9&`R!o%vdmy+H_xKkt_;FDxqVVUc^i-V7qE zoJZi#3U2!{NN<#Dw!ViXF8iQWQ$2TQta^ z6)x66#w>&GoON7GDPxvY#>Mh$!w~CmLv^(1mjQBvRg6L=vgybDkj6S65a5bK0=%M9 zT&t8-%t*KVd(t&p`f0iq|7KS0hzwhN)uAQM65}N$gl4^N@c0>Y>X7c^Yj6m?Y zz>-;3;L70VU5z~V3XB&yB#saqtMOzx+gcYJ*A>rfiM0!zAFlCA{iq23c5rUJ_?g?@@tH7b27#10d zw?i{x77;OGs+2GmbZ;MGy2ZSr<0!U3DSFppypomLoI97?I3e0%9gam?NMKTg!?J#{ z2Dj)5;j!Sy;La0bf?bt2M!%Iegh%uJ(39~o0&dZfXqueaFj4jrLInUuZ zI99Jvryr|t6<-R9MFPgU!{Ly|tX=O0<52F6^>ug8efPN+o`2pS-i`N~CzG*Tzr9W_ zNP{M!ihY6PVc&3{VWF`jMjKm=5EdNj4fsF~I4yq&_{8n)?7i$Bn!o*pON1~wm`vRs zD6n^{^TP(oBY0AUUYBJ)#*`$KC$*!R2WJXTs}x$|3DIHUN~PycI{H*=Y~j&$Y51WR z$;)Ws*L4BmfF`2aSneb#*(W(_H;d)YJzDzYvGCpjW}A!QCia3J8b_y8@tveiN(X^L5fP)KQDhLhTf zSVEd7cu6t*GQ_+rE00WzDXPUot22w$!%~Wvf>gC>Rh$(c>Rcq=s`8c`g*te;9=gyW z!Yv?G6`7}^smw`@x9F6vk_Bg8Aqe%dRl*f2Th#$rN}%(^LX56?uk+%y>KvI`D-6zZ(2^ojHTf3FqHbEwz2RsaA107*qo IM6N<$f{ZBLzW@LL literal 11887 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 From 753bb9fb9ffc01865abff74f43e367cb8f70e723 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 Aug 2025 05:48:47 +0000 Subject: [PATCH 321/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8458d3547..414e54965 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). From 7df361eb41e74c764d6001674e23027fda02b7cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 23:44:06 +0200 Subject: [PATCH 322/455] =?UTF-8?q?=E2=AC=86=20Bump=20actions/checkout=20f?= =?UTF-8?q?rom=204=20to=205=20(#13986)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 6 +++--- .github/workflows/contributors.yml | 2 +- .github/workflows/deploy-docs.yml | 2 +- .github/workflows/label-approved.yml | 2 +- .github/workflows/latest-changes.yml | 2 +- .github/workflows/notify-translations.yml | 2 +- .github/workflows/people.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/smokeshow.yml | 2 +- .github/workflows/sponsors.yml | 2 +- .github/workflows/test-redistribute.yml | 2 +- .github/workflows/test.yml | 6 +++--- .github/workflows/topic-repos.yml | 2 +- .github/workflows/translate.yml | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index e84e4e4ab..4b01354ed 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -21,7 +21,7 @@ jobs: outputs: docs: ${{ steps.filter.outputs.docs }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # For pull requests it's not necessary to checkout the code but for the main branch it is - uses: dorny/paths-filter@v3 id: filter @@ -47,7 +47,7 @@ jobs: outputs: langs: ${{ steps.show-langs.outputs.langs }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: @@ -89,7 +89,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 34b54b452..d957aa46e 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index c088d4ad1..40590793e 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -23,7 +23,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 908a9453d..5cd12e5d8 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -20,7 +20,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 208ab0c65..2fa832fab 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: # To allow latest-changes to commit to the main branch token: ${{ secrets.FASTAPI_LATEST_CHANGES }} diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 621d1253a..e5f0c3ebb 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -28,7 +28,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index c1df3455e..2e4ec1326 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bf88d59b1..5a83cf7d8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,7 +20,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 4788b4f1b..27f078838 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -21,7 +21,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version: '3.9' diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index 6da4d90e1..07153b6a9 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -24,7 +24,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index 693f0c603..71d21ae52 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -22,7 +22,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f9df620c..620e55df3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,7 +23,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: @@ -61,7 +61,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: @@ -107,7 +107,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version: '3.8' diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index 433aeb00b..9e953010d 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -19,7 +19,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index fc6b4d730..b7c3efe13 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -42,7 +42,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v5 with: From 078324583c1bbc2ac87e628c692a5a83435f97ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 Aug 2025 21:44:33 +0000 Subject: [PATCH 323/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 414e54965..8bd9d8bbb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -23,6 +23,7 @@ hide: ### Internal +* ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). From f1b144995898dc6bdf3ebca8d9e145ddf60cdc52 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sat, 16 Aug 2025 05:59:47 +0800 Subject: [PATCH 324/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20`docs/en/docs/a?= =?UTF-8?q?dvanced/generate-clients.md`=20(#13793)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/advanced/generate-clients.md | 145 +++++++--------------- 1 file changed, 46 insertions(+), 99 deletions(-) diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 55e6a08b1..e8b2fefbd 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -1,34 +1,42 @@ -# Generate Clients +# Generating SDKs -As **FastAPI** is based on the OpenAPI specification, you get automatic compatibility with many tools, including the automatic API docs (provided by Swagger UI). +Because **FastAPI** is based on the **OpenAPI** specification, its APIs can be described in a standard format that many tools understand. -One particular advantage that is not necessarily obvious is that you can **generate clients** (sometimes called **SDKs** ) for your API, for many different **programming languages**. +This makes it easy to generate up-to-date **documentation**, client libraries (**SDKs**) in multiple languages, and **testing** or **automation workflows** that stay in sync with your code. -## OpenAPI Client Generators +In this guide, you'll learn how to generate a **TypeScript SDK** for your FastAPI backend. -There are many tools to generate clients from **OpenAPI**. +## Open Source SDK Generators -A common tool is OpenAPI Generator. +A versatile option is the OpenAPI Generator, which supports **many programming languages** and can generate SDKs from your OpenAPI specification. -If you are building a **frontend**, a very interesting alternative is openapi-ts. +For **TypeScript clients**, Hey API is a purpose-built solution, providing an optimized experience for the TypeScript ecosystem. -## Client and SDK Generators - Sponsor +You can discover more SDK generators on OpenAPI.Tools. -There are also some **company-backed** Client and SDK generators based on OpenAPI (FastAPI), in some cases they can offer you **additional features** on top of high-quality generated SDKs/clients. +/// tip -Some of them also ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**. +FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you use must support this version. -And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good service** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇 +/// + +## SDK Generators from FastAPI Sponsors + +This section highlights **venture-backed** and **company-supported** solutions from companies that sponsor FastAPI. These products provide **additional features** and **integrations** on top of high-quality generated SDKs. + +By ✨ [**sponsoring FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, these companies help ensure the framework and its **ecosystem** remain healthy and **sustainable**. + +Their sponsorship also demonstrates a strong commitment to the FastAPI **community** (you), showing that they care not only about offering a **great service** but also about supporting a **robust and thriving framework**, FastAPI. 🙇 For example, you might want to try: * Speakeasy -* Stainless +* Stainless * liblab -There are also several other companies offering similar services that you can search and find online. 🤓 +Some of these solutions may also be open source or offer free tiers, so you can try them without a financial commitment. Other commercial SDK generators are available and can be found online. 🤓 -## Generate a TypeScript Frontend Client +## Create a TypeScript SDK Let's start with a simple FastAPI application: @@ -38,78 +46,31 @@ Notice that the *path operations* define the models they use for request payload ### API Docs -If you go to the API docs, you will see that it has the **schemas** for the data to be sent in requests and received in responses: +If you go to `/docs`, you will see that it has the **schemas** for the data to be sent in requests and received in responses: You can see those schemas because they were declared with the models in the app. -That information is available in the app's **OpenAPI schema**, and then shown in the API docs (by Swagger UI). +That information is available in the app's **OpenAPI schema**, and then shown in the API docs. -And that same information from the models that is included in OpenAPI is what can be used to **generate the client code**. +That same information from the models that is included in OpenAPI is what can be used to **generate the client code**. -### Generate a TypeScript Client +### Hey API -Now that we have the app with the models, we can generate the client code for the frontend. +Once we have a FastAPI app with the models, we can use Hey API to generate a TypeScript client. The fastest way to do that is via npx. -#### Install `openapi-ts` - -You can install `openapi-ts` in your frontend code with: - -
- -```console -$ npm install @hey-api/openapi-ts --save-dev - ----> 100% +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ``` -
+This will generate a TypeScript SDK in `./src/client`. -#### Generate Client Code +You can learn how to install `@hey-api/openapi-ts` and read about the generated output on their website. -To generate the client code you can use the command line application `openapi-ts` that would now be installed. +### Using the SDK -Because it is installed in the local project, you probably wouldn't be able to call that command directly, but you would put it on your `package.json` file. - -It could look like this: - -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} -``` - -After having that NPM `generate-client` script there, you can run it with: - -
- -```console -$ npm run generate-client - -frontend-app@1.0.0 generate-client /home/user/code/frontend-app -> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios -``` - -
- -That command will generate code in `./src/client` and will use `axios` (the frontend HTTP library) internally. - -### Try Out the Client Code - -Now you can import and use the client code, it could look like this, notice that you get autocompletion for the methods: +Now you can import and use the client code. It could look like this, notice that you get autocompletion for the methods: @@ -133,7 +94,7 @@ The response object will also have autocompletion: ## FastAPI App with Tags -In many cases your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*. +In many cases, your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*. For example, you could have a section for **items** and another section for **users**, and they could be separated by tags: @@ -143,18 +104,18 @@ For example, you could have a section for **items** and another section for **us If you generate a client for a FastAPI app using tags, it will normally also separate the client code based on the tags. -This way you will be able to have things ordered and grouped correctly for the client code: +This way, you will be able to have things ordered and grouped correctly for the client code: -In this case you have: +In this case, you have: * `ItemsService` * `UsersService` ### Client Method Names -Right now the generated method names like `createItemItemsPost` don't look very clean: +Right now, the generated method names like `createItemItemsPost` don't look very clean: ```TypeScript ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) @@ -170,13 +131,13 @@ But I'll show you how to improve that next. 🤓 You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients. -In this case you will have to ensure that each operation ID is **unique** in some other way. +In this case, you will have to ensure that each operation ID is **unique** in some other way. For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation* **name** (the function name). ### Custom Generate Unique ID Function -FastAPI uses a **unique ID** for each *path operation*, it is used for the **operation ID** and also for the names of any needed custom models, for requests or responses. +FastAPI uses a **unique ID** for each *path operation*, which is used for the **operation ID** and also for the names of any needed custom models, for requests or responses. You can customize that function. It takes an `APIRoute` and outputs a string. @@ -188,7 +149,7 @@ You can then pass that custom function to **FastAPI** as the `generate_unique_id ### Generate a TypeScript Client with Custom Operation IDs -Now if you generate the client again, you will see that it has the improved method names: +Now, if you generate the client again, you will see that it has the improved method names: @@ -202,7 +163,7 @@ We already know that this method is related to the **items** because that word i We will probably still want to keep it for OpenAPI in general, as that will ensure that the operation IDs are **unique**. -But for the generated client we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**. +But for the generated client, we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**. We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this: @@ -220,24 +181,10 @@ With that, the operation IDs would be renamed from things like `items-get_items` ### Generate a TypeScript Client with the Preprocessed OpenAPI -Now as the end result is in a file `openapi.json`, you would modify the `package.json` to use that local file, for example: +Since the end result is now in an `openapi.json` file, you need to update your input location: -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client ``` After generating the new client, you would now have **clean method names**, with all the **autocompletion**, **inline errors**, etc: @@ -246,7 +193,7 @@ After generating the new client, you would now have **clean method names**, with ## Benefits -When using the automatically generated clients you would get **autocompletion** for: +When using the automatically generated clients, you would get **autocompletion** for: * Methods. * Request payloads in the body, query parameters, etc. @@ -256,6 +203,6 @@ You would also have **inline errors** for everything. And whenever you update the backend code, and **regenerate** the frontend, it would have any new *path operations* available as methods, the old ones removed, and any other change would be reflected on the generated code. 🤓 -This also means that if something changed it will be **reflected** on the client code automatically. And if you **build** the client it will error out if you have any **mismatch** in the data used. +This also means that if something changed, it will be **reflected** on the client code automatically. And if you **build** the client, it will error out if you have any **mismatch** in the data used. So, you would **detect many errors** very early in the development cycle instead of having to wait for the errors to show up to your final users in production and then trying to debug where the problem is. ✨ From dbc9d3a0cee5dc855451353e185890bc78a6666e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 Aug 2025 22:00:13 +0000 Subject: [PATCH 325/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8bd9d8bbb..badd0ed25 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Update `docs/en/docs/advanced/generate-clients.md`. PR [#13793](https://github.com/fastapi/fastapi/pull/13793) by [@mrlubos](https://github.com/mrlubos). * 📝 Add discussion template for new language translation requests. PR [#13535](https://github.com/fastapi/fastapi/pull/13535) by [@alejsdev](https://github.com/alejsdev). ### Translations From d12c1ac82c1bf571bab078e0d047d868727a26de Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 00:00:47 +0200 Subject: [PATCH 326/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13983)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0) - [github.com/astral-sh/ruff-pre-commit: v0.12.7 → v0.12.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.7...v0.12.8) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c2e628466..7175d21eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ default_language_version: python: python3.10 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-added-large-files - id: check-toml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.7 + rev: v0.12.8 hooks: - id: ruff args: From 9c7abbff43121bca35bec3156a428105e98c0324 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 Aug 2025 22:01:21 +0000 Subject: [PATCH 327/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index badd0ed25..bfa253408 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13983](https://github.com/fastapi/fastapi/pull/13983) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From df779885fa094da506193a3772c6ab0335728790 Mon Sep 17 00:00:00 2001 From: Mika <44454249+anfreshman@users.noreply.github.com> Date: Mon, 18 Aug 2025 14:34:40 +0800 Subject: [PATCH 328/455] =?UTF-8?q?=F0=9F=93=9D=20Fix=20code=20include=20f?= =?UTF-8?q?or=20Pydantic=20models=20example=20in=20`docs/zh/docs/python-ty?= =?UTF-8?q?pes.md`=20(#13997)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated the Pydantic expiration example in the Chinese documentation --- docs/zh/docs/python-types.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index ba767da87..a7f76d97f 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -240,7 +240,29 @@ John Doe 下面的例子来自 Pydantic 官方文档: -{* ../../docs_src/python_types/tutorial010.py *} +//// tab | Python 3.10+ + +```Python +{!> ../../docs_src/python_types/tutorial011_py310.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python +{!> ../../docs_src/python_types/tutorial011_py39.py!} +``` + +//// + +//// tab | Python 3.8+ + +```Python +{!> ../../docs_src/python_types/tutorial011.py!} +``` + +//// /// info From c23051682bbeb254faee28fe80beeeab1764f7c4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 Aug 2025 06:35:06 +0000 Subject: [PATCH 329/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bfa253408..5bb2fa4f2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Translations +* 📝 Fix code include for Pydantic models example in `docs/zh/docs/python-types.md`. PR [#13997](https://github.com/fastapi/fastapi/pull/13997) by [@anfreshman](https://github.com/anfreshman). * 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). * 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki). * 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). From 6a45249303cf5ce8c9cde2c35497d2d12a4221a1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 23:07:04 +0200 Subject: [PATCH 330/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#13999)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.8 → v0.12.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.8...v0.12.9) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7175d21eb..bd899fea3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.8 + rev: v0.12.9 hooks: - id: ruff args: From 5c3a70d5b6def6f5ee471c3f9c7e6d2b2c6f6200 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 Aug 2025 21:07:25 +0000 Subject: [PATCH 331/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5bb2fa4f2..7747fa12e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -25,6 +25,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13999](https://github.com/fastapi/fastapi/pull/13999) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13983](https://github.com/fastapi/fastapi/pull/13983) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). From f75c1532f612137795b291f42fb507f7f103807b Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Wed, 20 Aug 2025 11:10:51 +0200 Subject: [PATCH 332/455] =?UTF-8?q?=E2=AC=86=20Bump=20`mkdocs-macros-plugi?= =?UTF-8?q?n`=20from=201.3.7=20to=201.3.9=20(#14003)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump mkdocs-macros-plugin from 1.3.7 to 1.3.9 --- requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index eeb41b5ce..24b79236c 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -15,5 +15,5 @@ mkdocstrings[python]==0.26.1 griffe-typingdoc==0.2.8 # For griffe, it formats with black black==25.1.0 -mkdocs-macros-plugin==1.3.7 +mkdocs-macros-plugin==1.3.9 markdown-include-variants==0.0.4 From 9cf7b70d7b282b0671dbb1a93a4cbc31aac58abe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 20 Aug 2025 09:11:20 +0000 Subject: [PATCH 333/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 7747fa12e..1b2291312 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -25,6 +25,7 @@ hide: ### Internal +* ⬆ Bump `mkdocs-macros-plugin` from 1.3.7 to 1.3.9. PR [#14003](https://github.com/fastapi/fastapi/pull/14003) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13999](https://github.com/fastapi/fastapi/pull/13999) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13983](https://github.com/fastapi/fastapi/pull/13983) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot). From 6be02e3d5261b1341a76d0e0f337ec5aa78f4e62 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 22:03:02 +0200 Subject: [PATCH 334/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#14016)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.9 → v0.12.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.9...v0.12.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd899fea3..e9e299b1c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.9 + rev: v0.12.10 hooks: - id: ruff args: From 6db05770f6f42d6c3e96e5e228b8fc7447026ce3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 25 Aug 2025 20:03:24 +0000 Subject: [PATCH 335/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1b2291312..c0e015ab0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -25,6 +25,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14016](https://github.com/fastapi/fastapi/pull/14016) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump `mkdocs-macros-plugin` from 1.3.7 to 1.3.9. PR [#14003](https://github.com/fastapi/fastapi/pull/14003) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13999](https://github.com/fastapi/fastapi/pull/13999) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13983](https://github.com/fastapi/fastapi/pull/13983) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 784f068abaa57aa25eac104e6d831ca12980f90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sun, 31 Aug 2025 11:11:15 +0200 Subject: [PATCH 336/455] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20Update=20`mkdoc?= =?UTF-8?q?s=5Fhooks`=20to=20handle=20headers=20with=20permalinks=20when?= =?UTF-8?q?=20building=20docs=20(#14025)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yurii Motov --- scripts/mkdocs_hooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mkdocs_hooks.py b/scripts/mkdocs_hooks.py index 0bc4929a4..e4a49165c 100644 --- a/scripts/mkdocs_hooks.py +++ b/scripts/mkdocs_hooks.py @@ -110,7 +110,7 @@ def generate_renamed_section_items( # Creating a new section makes it render it collapsed by default # no idea why, so, let's just modify the existing one # new_section = Section(title=new_title, children=new_children) - item.title = new_title + item.title = new_title.split("{ #")[0] item.children = new_children new_items.append(item) else: From 7653de2715c17feddfdc5621f9097aaae3e374b1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 31 Aug 2025 09:11:36 +0000 Subject: [PATCH 337/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c0e015ab0..f4da2cc41 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -25,6 +25,7 @@ hide: ### Internal +* 🛠️ Update `mkdocs_hooks` to handle headers with permalinks when building docs. PR [#14025](https://github.com/fastapi/fastapi/pull/14025) by [@tiangolo](https://github.com/tiangolo). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14016](https://github.com/fastapi/fastapi/pull/14016) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ⬆ Bump `mkdocs-macros-plugin` from 1.3.7 to 1.3.9. PR [#14003](https://github.com/fastapi/fastapi/pull/14003) by [@YuriiMotov](https://github.com/YuriiMotov). * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13999](https://github.com/fastapi/fastapi/pull/13999) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From c55f7138a11e9d315db95c1a29711b0d36baa33d Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sun, 31 Aug 2025 11:15:41 +0200 Subject: [PATCH 338/455] =?UTF-8?q?=F0=9F=93=9D=20Add=20permalinks=20to=20?= =?UTF-8?q?headers=20in=20English=20docs=20(#13993)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- README.md | 44 +++++------ docs/en/docs/about/index.md | 2 +- docs/en/docs/advanced/additional-responses.md | 12 +-- .../docs/advanced/additional-status-codes.md | 6 +- .../en/docs/advanced/advanced-dependencies.md | 12 +-- docs/en/docs/advanced/async-tests.md | 14 ++-- docs/en/docs/advanced/behind-a-proxy.md | 26 +++---- docs/en/docs/advanced/custom-response.md | 40 +++++----- docs/en/docs/advanced/dataclasses.md | 10 +-- docs/en/docs/advanced/events.md | 22 +++--- docs/en/docs/advanced/generate-clients.md | 32 ++++---- docs/en/docs/advanced/index.md | 6 +- docs/en/docs/advanced/middleware.md | 14 ++-- docs/en/docs/advanced/openapi-callbacks.md | 20 ++--- docs/en/docs/advanced/openapi-webhooks.md | 10 +-- .../path-operation-advanced-configuration.md | 20 ++--- .../advanced/response-change-status-code.md | 6 +- docs/en/docs/advanced/response-cookies.md | 8 +- docs/en/docs/advanced/response-directly.md | 10 +-- docs/en/docs/advanced/response-headers.md | 8 +- .../docs/advanced/security/http-basic-auth.md | 16 ++-- docs/en/docs/advanced/security/index.md | 6 +- .../docs/advanced/security/oauth2-scopes.md | 30 ++++---- docs/en/docs/advanced/settings.md | 36 ++++----- docs/en/docs/advanced/sub-applications.md | 14 ++-- docs/en/docs/advanced/templates.md | 16 ++-- docs/en/docs/advanced/testing-dependencies.md | 8 +- docs/en/docs/advanced/testing-events.md | 2 +- docs/en/docs/advanced/testing-websockets.md | 2 +- .../docs/advanced/using-request-directly.md | 8 +- docs/en/docs/advanced/websockets.md | 22 +++--- docs/en/docs/advanced/wsgi.md | 6 +- docs/en/docs/alternatives.md | 48 ++++++------ docs/en/docs/async.md | 42 +++++------ docs/en/docs/benchmarks.md | 4 +- docs/en/docs/deployment/cloud.md | 4 +- docs/en/docs/deployment/concepts.md | 56 +++++++------- docs/en/docs/deployment/docker.md | 74 +++++++++---------- docs/en/docs/deployment/https.md | 28 +++---- docs/en/docs/deployment/index.md | 6 +- docs/en/docs/deployment/manually.md | 14 ++-- docs/en/docs/deployment/server-workers.md | 10 +-- docs/en/docs/deployment/versions.md | 14 ++-- docs/en/docs/environment-variables.md | 14 ++-- docs/en/docs/fastapi-cli.md | 6 +- docs/en/docs/features.md | 28 +++---- docs/en/docs/help-fastapi.md | 50 ++++++------- docs/en/docs/history-design-future.md | 14 ++-- docs/en/docs/how-to/conditional-openapi.md | 6 +- docs/en/docs/how-to/configure-swagger-ui.md | 12 +-- docs/en/docs/how-to/custom-docs-ui-assets.md | 30 ++++---- .../docs/how-to/custom-request-and-route.md | 14 ++-- docs/en/docs/how-to/extending-openapi.md | 18 ++--- docs/en/docs/how-to/general.md | 20 ++--- docs/en/docs/how-to/graphql.md | 10 +-- docs/en/docs/how-to/index.md | 2 +- .../docs/how-to/separate-openapi-schemas.md | 20 ++--- docs/en/docs/how-to/testing-database.md | 2 +- docs/en/docs/index.md | 46 ++++++------ docs/en/docs/learn/index.md | 2 +- docs/en/docs/project-generation.md | 4 +- docs/en/docs/python-types.md | 40 +++++----- docs/en/docs/resources/index.md | 2 +- docs/en/docs/tutorial/background-tasks.md | 16 ++-- docs/en/docs/tutorial/bigger-applications.md | 42 +++++------ docs/en/docs/tutorial/body-fields.md | 10 +-- docs/en/docs/tutorial/body-multiple-params.md | 14 ++-- docs/en/docs/tutorial/body-nested-models.md | 32 ++++---- docs/en/docs/tutorial/body-updates.md | 14 ++-- docs/en/docs/tutorial/body.md | 22 +++--- docs/en/docs/tutorial/cookie-param-models.md | 10 +-- docs/en/docs/tutorial/cookie-params.md | 8 +- docs/en/docs/tutorial/cors.md | 16 ++-- docs/en/docs/tutorial/debugging.md | 10 +-- .../dependencies/classes-as-dependencies.md | 14 ++-- ...pendencies-in-path-operation-decorators.md | 16 ++-- .../dependencies/dependencies-with-yield.md | 28 +++---- .../dependencies/global-dependencies.md | 4 +- docs/en/docs/tutorial/dependencies/index.md | 28 +++---- .../tutorial/dependencies/sub-dependencies.md | 12 +-- docs/en/docs/tutorial/encoder.md | 4 +- docs/en/docs/tutorial/extra-data-types.md | 6 +- docs/en/docs/tutorial/extra-models.md | 26 +++---- docs/en/docs/tutorial/first-steps.md | 42 +++++------ docs/en/docs/tutorial/handling-errors.md | 28 +++---- docs/en/docs/tutorial/header-param-models.md | 12 +-- docs/en/docs/tutorial/header-params.md | 12 +-- docs/en/docs/tutorial/index.md | 8 +- docs/en/docs/tutorial/metadata.md | 20 ++--- docs/en/docs/tutorial/middleware.md | 10 +-- .../tutorial/path-operation-configuration.md | 18 ++--- .../path-params-numeric-validations.md | 20 ++--- docs/en/docs/tutorial/path-params.md | 40 +++++----- docs/en/docs/tutorial/query-param-models.md | 10 +-- .../tutorial/query-params-str-validations.md | 52 ++++++------- docs/en/docs/tutorial/query-params.md | 12 +-- docs/en/docs/tutorial/request-files.md | 22 +++--- docs/en/docs/tutorial/request-form-models.md | 10 +-- .../docs/tutorial/request-forms-and-files.md | 8 +- docs/en/docs/tutorial/request-forms.md | 10 +-- docs/en/docs/tutorial/response-model.md | 44 +++++------ docs/en/docs/tutorial/response-status-code.md | 8 +- docs/en/docs/tutorial/schema-extra-example.md | 30 ++++---- docs/en/docs/tutorial/security/first-steps.md | 20 ++--- .../tutorial/security/get-current-user.md | 16 ++-- docs/en/docs/tutorial/security/index.md | 16 ++-- docs/en/docs/tutorial/security/oauth2-jwt.md | 28 +++---- .../docs/tutorial/security/simple-oauth2.md | 36 ++++----- docs/en/docs/tutorial/sql-databases.md | 54 +++++++------- docs/en/docs/tutorial/static-files.md | 10 +-- docs/en/docs/tutorial/testing.md | 18 ++--- docs/en/docs/virtual-environments.md | 46 ++++++------ 112 files changed, 1060 insertions(+), 1060 deletions(-) diff --git a/README.md b/README.md index 0e421c347..95d123819 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The key features are: * estimation based on tests on an internal development team, building production applications. -## Sponsors +## Sponsors { #sponsors } @@ -69,7 +69,7 @@ The key features are: Other sponsors -## Opinions +## Opinions { #opinions } "_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" @@ -115,7 +115,7 @@ The key features are: --- -## **Typer**, the FastAPI of CLIs +## **Typer**, the FastAPI of CLIs { #typer-the-fastapi-of-clis } @@ -123,14 +123,14 @@ If you are building a CLI app to be **Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 -## Requirements +## Requirements { #requirements } FastAPI stands on the shoulders of giants: * Starlette for the web parts. * Pydantic for the data parts. -## Installation +## Installation { #installation } Create and activate a virtual environment and then install FastAPI: @@ -146,9 +146,9 @@ $ pip install "fastapi[standard]" **Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals. -## Example +## Example { #example } -### Create it +### Create it { #create-it } Create a file `main.py` with: @@ -199,7 +199,7 @@ If you don't know, check the _"In a hurry?"_ section about -### Check it +### Check it { #check-it } Open your browser at http://127.0.0.1:8000/items/5?q=somequery. @@ -258,7 +258,7 @@ You already created an API that: * The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. * The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. -### Interactive API docs +### Interactive API docs { #interactive-api-docs } Now go to http://127.0.0.1:8000/docs. @@ -266,7 +266,7 @@ You will see the automatic interactive API documentation (provided by http://127.0.0.1:8000/redoc. @@ -274,7 +274,7 @@ You will see the alternative automatic documentation (provided by http://127.0.0.1:8000/docs. @@ -328,7 +328,7 @@ Now go to http://127.0.0.1:8000/redoc. @@ -336,7 +336,7 @@ And now, go to one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) To understand more about it, see the section Benchmarks. -## Dependencies +## Dependencies { #dependencies } FastAPI depends on Pydantic and Starlette. -### `standard` Dependencies +### `standard` Dependencies { #standard-dependencies } When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies: @@ -478,15 +478,15 @@ Used by FastAPI: * `fastapi-cli[standard]` - to provide the `fastapi` command. * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. -### Without `standard` Dependencies +### Without `standard` Dependencies { #without-standard-dependencies } If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. -### Without `fastapi-cloud-cli` +### Without `fastapi-cloud-cli` { #without-fastapi-cloud-cli } If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. -### Additional Optional Dependencies +### Additional Optional Dependencies { #additional-optional-dependencies } There are some additional dependencies you might want to install. @@ -500,6 +500,6 @@ Additional optional FastAPI dependencies: * orjson - Required if you want to use `ORJSONResponse`. * ujson - Required if you want to use `UJSONResponse`. -## License +## License { #license } This project is licensed under the terms of the MIT license. diff --git a/docs/en/docs/about/index.md b/docs/en/docs/about/index.md index 27b78696b..d178dfec7 100644 --- a/docs/en/docs/about/index.md +++ b/docs/en/docs/about/index.md @@ -1,3 +1,3 @@ -# About +# About { #about } About FastAPI, its design, inspiration and more. 🤓 diff --git a/docs/en/docs/advanced/additional-responses.md b/docs/en/docs/advanced/additional-responses.md index 03d48c2a7..799532c5b 100644 --- a/docs/en/docs/advanced/additional-responses.md +++ b/docs/en/docs/advanced/additional-responses.md @@ -1,4 +1,4 @@ -# Additional Responses in OpenAPI +# Additional Responses in OpenAPI { #additional-responses-in-openapi } /// warning @@ -14,7 +14,7 @@ Those additional responses will be included in the OpenAPI schema, so they will But for those additional responses you have to make sure you return a `Response` like `JSONResponse` directly, with your status code and content. -## Additional Response with `model` +## Additional Response with `model` { #additional-response-with-model } You can pass to your *path operation decorators* a parameter `responses`. @@ -169,7 +169,7 @@ The schemas are referenced to another place inside the OpenAPI schema: } ``` -## Additional media types for the main response +## Additional media types for the main response { #additional-media-types-for-the-main-response } You can use this same `responses` parameter to add different media types for the same main response. @@ -191,7 +191,7 @@ But if you have specified a custom response class with `None` as its media type, /// -## Combining information +## Combining information { #combining-information } You can also combine response information from multiple places, including the `response_model`, `status_code`, and `responses` parameters. @@ -209,7 +209,7 @@ It will all be combined and included in your OpenAPI, and shown in the API docs: -## Combine predefined responses and custom ones +## Combine predefined responses and custom ones { #combine-predefined-responses-and-custom-ones } You might want to have some predefined responses that apply to many *path operations*, but you want to combine them with custom responses needed by each *path operation*. @@ -239,7 +239,7 @@ For example: {* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *} -## More information about OpenAPI responses +## More information about OpenAPI responses { #more-information-about-openapi-responses } To see what exactly you can include in the responses, you can check these sections in the OpenAPI specification: diff --git a/docs/en/docs/advanced/additional-status-codes.md b/docs/en/docs/advanced/additional-status-codes.md index 077a00488..23bcd13c3 100644 --- a/docs/en/docs/advanced/additional-status-codes.md +++ b/docs/en/docs/advanced/additional-status-codes.md @@ -1,10 +1,10 @@ -# Additional Status Codes +# Additional Status Codes { #additional-status-codes } By default, **FastAPI** will return the responses using a `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`. It will use the default status code or the one you set in your *path operation*. -## Additional status codes +## Additional status codes { #additional-status-codes_1 } If you want to return additional status codes apart from the main one, you can do that by returning a `Response` directly, like a `JSONResponse`, and set the additional status code directly. @@ -34,7 +34,7 @@ You could also use `from starlette.responses import JSONResponse`. /// -## OpenAPI and API docs +## OpenAPI and API docs { #openapi-and-api-docs } If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know beforehand what you are going to return. diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index f933fd264..c71c11404 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -1,6 +1,6 @@ -# Advanced Dependencies +# Advanced Dependencies { #advanced-dependencies } -## Parameterized dependencies +## Parameterized dependencies { #parameterized-dependencies } All the dependencies we have seen are a fixed function or class. @@ -10,7 +10,7 @@ Let's imagine that we want to have a dependency that checks if the query paramet But we want to be able to parameterize that fixed content. -## A "callable" instance +## A "callable" instance { #a-callable-instance } In Python there's a way to make an instance of a class a "callable". @@ -22,7 +22,7 @@ To do that, we declare a method `__call__`: In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later. -## Parameterize the instance +## Parameterize the instance { #parameterize-the-instance } And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency: @@ -30,7 +30,7 @@ And now, we can use `__init__` to declare the parameters of the instance that we In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code. -## Create an instance +## Create an instance { #create-an-instance } We could create an instance of this class with: @@ -38,7 +38,7 @@ We could create an instance of this class with: And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`. -## Use the instance as a dependency +## Use the instance as a dependency { #use-the-instance-as-a-dependency } Then, we could use this `checker` in a `Depends(checker)`, instead of `Depends(FixedContentQueryChecker)`, because the dependency is the instance, `checker`, not the class itself. diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md index 8d6929222..7b6f08371 100644 --- a/docs/en/docs/advanced/async-tests.md +++ b/docs/en/docs/advanced/async-tests.md @@ -1,4 +1,4 @@ -# Async Tests +# Async Tests { #async-tests } You have already seen how to test your **FastAPI** applications using the provided `TestClient`. Up to now, you have only seen how to write synchronous tests, without using `async` functions. @@ -6,11 +6,11 @@ Being able to use asynchronous functions in your tests could be useful, for exam Let's look at how we can make that work. -## pytest.mark.anyio +## pytest.mark.anyio { #pytest-mark-anyio } If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. AnyIO provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously. -## HTTPX +## HTTPX { #httpx } Even if your **FastAPI** application uses normal `def` functions instead of `async def`, it is still an `async` application underneath. @@ -18,7 +18,7 @@ The `TestClient` does some magic inside to call the asynchronous FastAPI applica The `TestClient` is based on HTTPX, and luckily, we can use it directly to test the API. -## Example +## Example { #example } For a simple example, let's consider a file structure similar to the one described in [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} and [Testing](../tutorial/testing.md){.internal-link target=_blank}: @@ -38,7 +38,7 @@ The file `test_main.py` would have the tests for `main.py`, it could look like t {* ../../docs_src/async_tests/test_main.py *} -## Run it +## Run it { #run-it } You can run your tests as usual via: @@ -52,7 +52,7 @@ $ pytest -## In Detail +## In Detail { #in-detail } The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously: @@ -88,7 +88,7 @@ If your application relies on lifespan events, the `AsyncClient` won't trigger t /// -## Other Asynchronous Function Calls +## Other Asynchronous Function Calls { #other-asynchronous-function-calls } As the testing function is now asynchronous, you can now also call (and `await`) other `async` functions apart from sending requests to your FastAPI application in your tests, exactly as you would call them anywhere else in your code. diff --git a/docs/en/docs/advanced/behind-a-proxy.md b/docs/en/docs/advanced/behind-a-proxy.md index 1f0d0fd9f..0f100306a 100644 --- a/docs/en/docs/advanced/behind-a-proxy.md +++ b/docs/en/docs/advanced/behind-a-proxy.md @@ -1,4 +1,4 @@ -# Behind a Proxy +# Behind a Proxy { #behind-a-proxy } In some situations, you might need to use a **proxy** server like Traefik or Nginx with a configuration that adds an extra path prefix that is not seen by your application. @@ -10,7 +10,7 @@ The `root_path` is used to handle these specific cases. And it's also used internally when mounting sub-applications. -## Proxy with a stripped path prefix +## Proxy with a stripped path prefix { #proxy-with-a-stripped-path-prefix } Having a proxy with a stripped path prefix, in this case, means that you could declare a path at `/app` in your code, but then, you add a layer on top (the proxy) that would put your **FastAPI** application under a path like `/api/v1`. @@ -66,7 +66,7 @@ The docs UI would also need the OpenAPI schema to declare that this API `server` In this example, the "Proxy" could be something like **Traefik**. And the server would be something like FastAPI CLI with **Uvicorn**, running your FastAPI application. -### Providing the `root_path` +### Providing the `root_path` { #providing-the-root-path } To achieve this, you can use the command line option `--root-path` like: @@ -90,7 +90,7 @@ And the `--root-path` command line option provides that `root_path`. /// -### Checking the current `root_path` +### Checking the current `root_path` { #checking-the-current-root-path } You can get the current `root_path` used by your application for each request, it is part of the `scope` dictionary (that's part of the ASGI spec). @@ -119,7 +119,7 @@ The response would be something like: } ``` -### Setting the `root_path` in the FastAPI app +### Setting the `root_path` in the FastAPI app { #setting-the-root-path-in-the-fastapi-app } Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app: @@ -127,7 +127,7 @@ Alternatively, if you don't have a way to provide a command line option like `-- Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn. -### About `root_path` +### About `root_path` { #about-root-path } Keep in mind that the server (Uvicorn) won't use that `root_path` for anything else than passing it to the app. @@ -144,7 +144,7 @@ So, it won't expect to be accessed at `http://127.0.0.1:8000/api/v1/app`. Uvicorn will expect the proxy to access Uvicorn at `http://127.0.0.1:8000/app`, and then it would be the proxy's responsibility to add the extra `/api/v1` prefix on top. -## About proxies with a stripped path prefix +## About proxies with a stripped path prefix { #about-proxies-with-a-stripped-path-prefix } Keep in mind that a proxy with stripped path prefix is only one of the ways to configure it. @@ -152,7 +152,7 @@ Probably in many cases the default will be that the proxy doesn't have a strippe In a case like that (without a stripped path prefix), the proxy would listen on something like `https://myawesomeapp.com`, and then if the browser goes to `https://myawesomeapp.com/api/v1/app` and your server (e.g. Uvicorn) listens on `http://127.0.0.1:8000` the proxy (without a stripped path prefix) would access Uvicorn at the same path: `http://127.0.0.1:8000/api/v1/app`. -## Testing locally with Traefik +## Testing locally with Traefik { #testing-locally-with-traefik } You can easily run the experiment locally with a stripped path prefix using Traefik. @@ -231,7 +231,7 @@ $ fastapi run main.py --root-path /api/v1 -### Check the responses +### Check the responses { #check-the-responses } Now, if you go to the URL with the port for Uvicorn: http://127.0.0.1:8000/app, you will see the normal response: @@ -267,7 +267,7 @@ And the version without the path prefix (`http://127.0.0.1:8000/app`), provided That demonstrates how the Proxy (Traefik) uses the path prefix and how the server (Uvicorn) uses the `root_path` from the option `--root-path`. -### Check the docs UI +### Check the docs UI { #check-the-docs-ui } But here's the fun part. ✨ @@ -287,7 +287,7 @@ Right as we wanted it. ✔️ This is because FastAPI uses this `root_path` to create the default `server` in OpenAPI with the URL provided by `root_path`. -## Additional servers +## Additional servers { #additional-servers } /// warning @@ -346,7 +346,7 @@ The docs UI will interact with the server that you select. /// -### Disable automatic server from `root_path` +### Disable automatic server from `root_path` { #disable-automatic-server-from-root-path } If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`: @@ -354,7 +354,7 @@ If you don't want **FastAPI** to include an automatic server using the `root_pat and then it won't include it in the OpenAPI schema. -## Mounting a sub-application +## Mounting a sub-application { #mounting-a-sub-application } If you need to mount a sub-application (as described in [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}) while also using a proxy with `root_path`, you can do it normally, as you would expect. diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md index 8268dd81a..5473d939c 100644 --- a/docs/en/docs/advanced/custom-response.md +++ b/docs/en/docs/advanced/custom-response.md @@ -1,4 +1,4 @@ -# Custom Response - HTML, Stream, File, others +# Custom Response - HTML, Stream, File, others { #custom-response-html-stream-file-others } By default, **FastAPI** will return the responses using `JSONResponse`. @@ -18,7 +18,7 @@ If you use a response class with no media type, FastAPI will expect your respons /// -## Use `ORJSONResponse` +## Use `ORJSONResponse` { #use-orjsonresponse } For example, if you are squeezing performance, you can install and use `orjson` and set the response to be `ORJSONResponse`. @@ -48,7 +48,7 @@ The `ORJSONResponse` is only available in FastAPI, not in Starlette. /// -## HTML Response +## HTML Response { #html-response } To return a response with HTML directly from **FastAPI**, use `HTMLResponse`. @@ -67,7 +67,7 @@ And it will be documented as such in OpenAPI. /// -### Return a `Response` +### Return a `Response` { #return-a-response } As seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}, you can also override the response directly in your *path operation*, by returning it. @@ -87,13 +87,13 @@ Of course, the actual `Content-Type` header, status code, etc, will come from th /// -### Document in OpenAPI and override `Response` +### Document in OpenAPI and override `Response` { #document-in-openapi-and-override-response } If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `response_class` parameter AND return a `Response` object. The `response_class` will then be used only to document the OpenAPI *path operation*, but your `Response` will be used as is. -#### Return an `HTMLResponse` directly +#### Return an `HTMLResponse` directly { #return-an-htmlresponse-directly } For example, it could be something like: @@ -107,7 +107,7 @@ But as you passed the `HTMLResponse` in the `response_class` too, **FastAPI** wi -## Available responses +## Available responses { #available-responses } Here are some of the available responses. @@ -121,7 +121,7 @@ You could also use `from starlette.responses import HTMLResponse`. /// -### `Response` +### `Response` { #response } The main `Response` class, all the other responses inherit from it. @@ -138,23 +138,23 @@ FastAPI (actually Starlette) will automatically include a Content-Length header. {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} -### `HTMLResponse` +### `HTMLResponse` { #htmlresponse } Takes some text or bytes and returns an HTML response, as you read above. -### `PlainTextResponse` +### `PlainTextResponse` { #plaintextresponse } Takes some text or bytes and returns a plain text response. {* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *} -### `JSONResponse` +### `JSONResponse` { #jsonresponse } Takes some data and returns an `application/json` encoded response. This is the default response used in **FastAPI**, as you read above. -### `ORJSONResponse` +### `ORJSONResponse` { #orjsonresponse } A fast alternative JSON response using `orjson`, as you read above. @@ -164,7 +164,7 @@ This requires installing `orjson` for example with `pip install orjson`. /// -### `UJSONResponse` +### `UJSONResponse` { #ujsonresponse } An alternative JSON response using `ujson`. @@ -188,7 +188,7 @@ It's possible that `ORJSONResponse` might be a faster alternative. /// -### `RedirectResponse` +### `RedirectResponse` { #redirectresponse } Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default. @@ -213,13 +213,13 @@ You can also use the `status_code` parameter combined with the `response_class` {* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *} -### `StreamingResponse` +### `StreamingResponse` { #streamingresponse } Takes an async generator or a normal generator/iterator and streams the response body. {* ../../docs_src/custom_response/tutorial007.py hl[2,14] *} -#### Using `StreamingResponse` with file-like objects +#### Using `StreamingResponse` with file-like objects { #using-streamingresponse-with-file-like-objects } If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object. @@ -243,7 +243,7 @@ Notice that here as we are using standard `open()` that doesn't support `async` /// -### `FileResponse` +### `FileResponse` { #fileresponse } Asynchronously streams a file as the response. @@ -264,7 +264,7 @@ You can also use the `response_class` parameter: In this case, you can return the file path directly from your *path operation* function. -## Custom response class +## Custom response class { #custom-response-class } You can create your own custom response class, inheriting from `Response` and using it. @@ -292,7 +292,7 @@ Now instead of returning: Of course, you will probably find much better ways to take advantage of this than formatting JSON. 😉 -## Default response class +## Default response class { #default-response-class } When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default. @@ -308,6 +308,6 @@ You can still override `response_class` in *path operations* as before. /// -## Additional documentation +## Additional documentation { #additional-documentation } You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/en/docs/advanced/dataclasses.md b/docs/en/docs/advanced/dataclasses.md index 2936c6d5d..b7b9b65c5 100644 --- a/docs/en/docs/advanced/dataclasses.md +++ b/docs/en/docs/advanced/dataclasses.md @@ -1,4 +1,4 @@ -# Using Dataclasses +# Using Dataclasses { #using-dataclasses } FastAPI is built on top of **Pydantic**, and I have been showing you how to use Pydantic models to declare requests and responses. @@ -28,7 +28,7 @@ But if you have a bunch of dataclasses laying around, this is a nice trick to us /// -## Dataclasses in `response_model` +## Dataclasses in `response_model` { #dataclasses-in-response-model } You can also use `dataclasses` in the `response_model` parameter: @@ -40,7 +40,7 @@ This way, its schema will show up in the API docs user interface: -## Dataclasses in Nested Data Structures +## Dataclasses in Nested Data Structures { #dataclasses-in-nested-data-structures } You can also combine `dataclasses` with other type annotations to make nested data structures. @@ -84,12 +84,12 @@ You can combine `dataclasses` with other type annotations in many different comb Check the in-code annotation tips above to see more specific details. -## Learn More +## Learn More { #learn-more } You can also combine `dataclasses` with other Pydantic models, inherit from them, include them in your own models, etc. To learn more, check the Pydantic docs about dataclasses. -## Version +## Version { #version } This is available since FastAPI version `0.67.0`. 🔖 diff --git a/docs/en/docs/advanced/events.md b/docs/en/docs/advanced/events.md index 19465d891..c805e81ee 100644 --- a/docs/en/docs/advanced/events.md +++ b/docs/en/docs/advanced/events.md @@ -1,4 +1,4 @@ -# Lifespan Events +# Lifespan Events { #lifespan-events } You can define logic (code) that should be executed before the application **starts up**. This means that this code will be executed **once**, **before** the application **starts receiving requests**. @@ -8,7 +8,7 @@ Because this code is executed before the application **starts** taking requests, This can be very useful for setting up **resources** that you need to use for the whole app, and that are **shared** among requests, and/or that you need to **clean up** afterwards. For example, a database connection pool, or loading a shared machine learning model. -## Use Case +## Use Case { #use-case } Let's start with an example **use case** and then see how to solve it with this. @@ -22,7 +22,7 @@ You could load it at the top level of the module/file, but that would also mean That's what we'll solve, let's load the model before the requests are handled, but only right before the application starts receiving requests, not while the code is being loaded. -## Lifespan +## Lifespan { #lifespan } You can define this *startup* and *shutdown* logic using the `lifespan` parameter of the `FastAPI` app, and a "context manager" (I'll show you what that is in a second). @@ -44,7 +44,7 @@ Maybe you need to start a new version, or you just got tired of running it. 🤷 /// -### Lifespan function +### Lifespan function { #lifespan-function } The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`. @@ -54,7 +54,7 @@ The first part of the function, before the `yield`, will be executed **before** And the part after the `yield` will be executed **after** the application has finished. -### Async Context Manager +### Async Context Manager { #async-context-manager } If you check, the function is decorated with an `@asynccontextmanager`. @@ -84,7 +84,7 @@ The `lifespan` parameter of the `FastAPI` app takes an **async context manager** {* ../../docs_src/events/tutorial003.py hl[22] *} -## Alternative Events (deprecated) +## Alternative Events (deprecated) { #alternative-events-deprecated } /// warning @@ -100,7 +100,7 @@ You can define event handlers (functions) that need to be executed before the ap These functions can be declared with `async def` or normal `def`. -### `startup` event +### `startup` event { #startup-event } To add a function that should be run before the application starts, declare it with the event `"startup"`: @@ -112,7 +112,7 @@ You can add more than one event handler function. And your application won't start receiving requests until all the `startup` event handlers have completed. -### `shutdown` event +### `shutdown` event { #shutdown-event } To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`: @@ -138,7 +138,7 @@ So, we declare the event handler function with standard `def` instead of `async /// -### `startup` and `shutdown` together +### `startup` and `shutdown` together { #startup-and-shutdown-together } There's a high chance that the logic for your *startup* and *shutdown* is connected, you might want to start something and then finish it, acquire a resource and then release it, etc. @@ -146,7 +146,7 @@ Doing that in separated functions that don't share logic or variables together i Because of that, it's now recommended to instead use the `lifespan` as explained above. -## Technical Details +## Technical Details { #technical-details } Just a technical detail for the curious nerds. 🤓 @@ -160,6 +160,6 @@ Including how to handle lifespan state that can be used in other areas of your c /// -## Sub Applications +## Sub Applications { #sub-applications } 🚨 Keep in mind that these lifespan events (startup and shutdown) will only be executed for the main application, not for [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}. diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index e8b2fefbd..897c30808 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -1,4 +1,4 @@ -# Generating SDKs +# Generating SDKs { #generating-sdks } Because **FastAPI** is based on the **OpenAPI** specification, its APIs can be described in a standard format that many tools understand. @@ -6,7 +6,7 @@ This makes it easy to generate up-to-date **documentation**, client libraries (< In this guide, you'll learn how to generate a **TypeScript SDK** for your FastAPI backend. -## Open Source SDK Generators +## Open Source SDK Generators { #open-source-sdk-generators } A versatile option is the OpenAPI Generator, which supports **many programming languages** and can generate SDKs from your OpenAPI specification. @@ -20,7 +20,7 @@ FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you /// -## SDK Generators from FastAPI Sponsors +## SDK Generators from FastAPI Sponsors { #sdk-generators-from-fastapi-sponsors } This section highlights **venture-backed** and **company-supported** solutions from companies that sponsor FastAPI. These products provide **additional features** and **integrations** on top of high-quality generated SDKs. @@ -36,7 +36,7 @@ For example, you might want to try: Some of these solutions may also be open source or offer free tiers, so you can try them without a financial commitment. Other commercial SDK generators are available and can be found online. 🤓 -## Create a TypeScript SDK +## Create a TypeScript SDK { #create-a-typescript-sdk } Let's start with a simple FastAPI application: @@ -44,7 +44,7 @@ Let's start with a simple FastAPI application: Notice that the *path operations* define the models they use for request payload and response payload, using the models `Item` and `ResponseMessage`. -### API Docs +### API Docs { #api-docs } If you go to `/docs`, you will see that it has the **schemas** for the data to be sent in requests and received in responses: @@ -56,7 +56,7 @@ That information is available in the app's **OpenAPI schema**, and then shown in That same information from the models that is included in OpenAPI is what can be used to **generate the client code**. -### Hey API +### Hey API { #hey-api } Once we have a FastAPI app with the models, we can use Hey API to generate a TypeScript client. The fastest way to do that is via npx. @@ -68,7 +68,7 @@ This will generate a TypeScript SDK in `./src/client`. You can learn how to install `@hey-api/openapi-ts` and read about the generated output on their website. -### Using the SDK +### Using the SDK { #using-the-sdk } Now you can import and use the client code. It could look like this, notice that you get autocompletion for the methods: @@ -92,7 +92,7 @@ The response object will also have autocompletion: -## FastAPI App with Tags +## FastAPI App with Tags { #fastapi-app-with-tags } In many cases, your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*. @@ -100,7 +100,7 @@ For example, you could have a section for **items** and another section for **us {* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} -### Generate a TypeScript Client with Tags +### Generate a TypeScript Client with Tags { #generate-a-typescript-client-with-tags } If you generate a client for a FastAPI app using tags, it will normally also separate the client code based on the tags. @@ -113,7 +113,7 @@ In this case, you have: * `ItemsService` * `UsersService` -### Client Method Names +### Client Method Names { #client-method-names } Right now, the generated method names like `createItemItemsPost` don't look very clean: @@ -127,7 +127,7 @@ OpenAPI requires that each operation ID is unique across all the *path operation But I'll show you how to improve that next. 🤓 -## Custom Operation IDs and Better Method Names +## Custom Operation IDs and Better Method Names { #custom-operation-ids-and-better-method-names } You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients. @@ -135,7 +135,7 @@ In this case, you will have to ensure that each operation ID is **unique** in so For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation* **name** (the function name). -### Custom Generate Unique ID Function +### Custom Generate Unique ID Function { #custom-generate-unique-id-function } FastAPI uses a **unique ID** for each *path operation*, which is used for the **operation ID** and also for the names of any needed custom models, for requests or responses. @@ -147,7 +147,7 @@ You can then pass that custom function to **FastAPI** as the `generate_unique_id {* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} -### Generate a TypeScript Client with Custom Operation IDs +### Generate a TypeScript Client with Custom Operation IDs { #generate-a-typescript-client-with-custom-operation-ids } Now, if you generate the client again, you will see that it has the improved method names: @@ -155,7 +155,7 @@ Now, if you generate the client again, you will see that it has the improved met As you see, the method names now have the tag and then the function name, now they don't include information from the URL path and the HTTP operation. -### Preprocess the OpenAPI Specification for the Client Generator +### Preprocess the OpenAPI Specification for the Client Generator { #preprocess-the-openapi-specification-for-the-client-generator } The generated code still has some **duplicated information**. @@ -179,7 +179,7 @@ We could download the OpenAPI JSON to a file `openapi.json` and then we could ** With that, the operation IDs would be renamed from things like `items-get_items` to just `get_items`, that way the client generator can generate simpler method names. -### Generate a TypeScript Client with the Preprocessed OpenAPI +### Generate a TypeScript Client with the Preprocessed OpenAPI { #generate-a-typescript-client-with-the-preprocessed-openapi } Since the end result is now in an `openapi.json` file, you need to update your input location: @@ -191,7 +191,7 @@ After generating the new client, you would now have **clean method names**, with -## Benefits +## Benefits { #benefits } When using the automatically generated clients, you would get **autocompletion** for: diff --git a/docs/en/docs/advanced/index.md b/docs/en/docs/advanced/index.md index 47385e2c6..9355516fb 100644 --- a/docs/en/docs/advanced/index.md +++ b/docs/en/docs/advanced/index.md @@ -1,6 +1,6 @@ -# Advanced User Guide +# Advanced User Guide { #advanced-user-guide } -## Additional Features +## Additional Features { #additional-features } The main [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} should be enough to give you a tour through all the main features of **FastAPI**. @@ -14,7 +14,7 @@ And it's possible that for your use case, the solution is in one of them. /// -## Read the Tutorial first +## Read the Tutorial first { #read-the-tutorial-first } You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank}. diff --git a/docs/en/docs/advanced/middleware.md b/docs/en/docs/advanced/middleware.md index 1d40b1c8f..4ca07676b 100644 --- a/docs/en/docs/advanced/middleware.md +++ b/docs/en/docs/advanced/middleware.md @@ -1,4 +1,4 @@ -# Advanced Middleware +# Advanced Middleware { #advanced-middleware } In the main tutorial you read how to add [Custom Middleware](../tutorial/middleware.md){.internal-link target=_blank} to your application. @@ -6,7 +6,7 @@ And then you also read how to handle [CORS with the `CORSMiddleware`](../tutoria In this section we'll see how to use other middlewares. -## Adding ASGI middlewares +## Adding ASGI middlewares { #adding-asgi-middlewares } As **FastAPI** is based on Starlette and implements the ASGI specification, you can use any ASGI middleware. @@ -39,7 +39,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") `app.add_middleware()` receives a middleware class as the first argument and any additional arguments to be passed to the middleware. -## Integrated middlewares +## Integrated middlewares { #integrated-middlewares } **FastAPI** includes several middlewares for common use cases, we'll see next how to use them. @@ -51,7 +51,7 @@ For the next examples, you could also use `from starlette.middleware.something i /// -## `HTTPSRedirectMiddleware` +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } Enforces that all incoming requests must either be `https` or `wss`. @@ -59,7 +59,7 @@ Any incoming request to `http` or `ws` will be redirected to the secure scheme i {* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *} -## `TrustedHostMiddleware` +## `TrustedHostMiddleware` { #trustedhostmiddleware } Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks. @@ -71,7 +71,7 @@ The following arguments are supported: If an incoming request does not validate correctly then a `400` response will be sent. -## `GZipMiddleware` +## `GZipMiddleware` { #gzipmiddleware } Handles GZip responses for any request that includes `"gzip"` in the `Accept-Encoding` header. @@ -84,7 +84,7 @@ The following arguments are supported: * `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`. * `compresslevel` - Used during GZip compression. It is an integer ranging from 1 to 9. Defaults to `9`. Lower value results in faster compression but larger file sizes, while higher value results in slower compression but smaller file sizes. -## Other middlewares +## Other middlewares { #other-middlewares } There are many other ASGI middlewares. diff --git a/docs/en/docs/advanced/openapi-callbacks.md b/docs/en/docs/advanced/openapi-callbacks.md index ca9065a89..059d893c2 100644 --- a/docs/en/docs/advanced/openapi-callbacks.md +++ b/docs/en/docs/advanced/openapi-callbacks.md @@ -1,4 +1,4 @@ -# OpenAPI Callbacks +# OpenAPI Callbacks { #openapi-callbacks } You could create an API with a *path operation* that could trigger a request to an *external API* created by someone else (probably the same developer that would be *using* your API). @@ -6,7 +6,7 @@ The process that happens when your API app calls the *external API* is named a " In this case, you could want to document how that external API *should* look like. What *path operation* it should have, what body it should expect, what response it should return, etc. -## An app with callbacks +## An app with callbacks { #an-app-with-callbacks } Let's see all this with an example. @@ -23,7 +23,7 @@ Then your API will (let's imagine): * Send a notification back to the API user (the external developer). * This will be done by sending a POST request (from *your API*) to some *external API* provided by that external developer (this is the "callback"). -## The normal **FastAPI** app +## The normal **FastAPI** app { #the-normal-fastapi-app } Let's first see how the normal API app would look like before adding the callback. @@ -41,7 +41,7 @@ The `callback_url` query parameter uses a Pydantic OpenAPI 3 expression (see more below) where it can use variables with parameters and parts of the original request sent to *your API*. -### The callback path expression +### The callback path expression { #the-callback-path-expression } The callback *path* can have an OpenAPI 3 expression that can contain parts of the original request sent to *your API*. @@ -163,7 +163,7 @@ Notice how the callback URL used contains the URL received as a query parameter /// -### Add the callback router +### Add the callback router { #add-the-callback-router } At this point you have the *callback path operation(s)* needed (the one(s) that the *external developer* should implement in the *external API*) in the callback router you created above. @@ -177,7 +177,7 @@ Notice that you are not passing the router itself (`invoices_callback_router`) t /// -### Check the docs +### Check the docs { #check-the-docs } Now you can start your app and go to http://127.0.0.1:8000/docs. diff --git a/docs/en/docs/advanced/openapi-webhooks.md b/docs/en/docs/advanced/openapi-webhooks.md index 97aaa41af..416cf4b75 100644 --- a/docs/en/docs/advanced/openapi-webhooks.md +++ b/docs/en/docs/advanced/openapi-webhooks.md @@ -1,4 +1,4 @@ -# OpenAPI Webhooks +# OpenAPI Webhooks { #openapi-webhooks } There are cases where you want to tell your API **users** that your app could call *their* app (sending a request) with some data, normally to **notify** of some type of **event**. @@ -6,7 +6,7 @@ This means that instead of the normal process of your users sending requests to This is normally called a **webhook**. -## Webhooks steps +## Webhooks steps { #webhooks-steps } The process normally is that **you define** in your code what is the message that you will send, the **body of the request**. @@ -16,7 +16,7 @@ And **your users** define in some way (for example in a web dashboard somewhere) All the **logic** about how to register the URLs for webhooks and the code to actually send those requests is up to you. You write it however you want to in **your own code**. -## Documenting webhooks with **FastAPI** and OpenAPI +## Documenting webhooks with **FastAPI** and OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } With **FastAPI**, using OpenAPI, you can define the names of these webhooks, the types of HTTP operations that your app can send (e.g. `POST`, `PUT`, etc.) and the request **bodies** that your app would send. @@ -28,7 +28,7 @@ Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0` /// -## An app with webhooks +## An app with webhooks { #an-app-with-webhooks } When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`. @@ -46,7 +46,7 @@ Notice that with webhooks you are actually not declaring a *path* (like `/items/ This is because it is expected that **your users** would define the actual **URL path** where they want to receive the webhook request in some other way (e.g. a web dashboard). -### Check the docs +### Check the docs { #check-the-docs } Now you can start your app and go to http://127.0.0.1:8000/docs. diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md index c4814ebd2..b9961f9f3 100644 --- a/docs/en/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md @@ -1,6 +1,6 @@ -# Path Operation Advanced Configuration +# Path Operation Advanced Configuration { #path-operation-advanced-configuration } -## OpenAPI operationId +## OpenAPI operationId { #openapi-operationid } /// warning @@ -14,7 +14,7 @@ You would have to make sure that it is unique for each operation. {* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *} -### Using the *path operation function* name as the operationId +### Using the *path operation function* name as the operationId { #using-the-path-operation-function-name-as-the-operationid } If you want to use your APIs' function names as `operationId`s, you can iterate over all of them and override each *path operation's* `operation_id` using their `APIRoute.name`. @@ -36,13 +36,13 @@ Even if they are in different modules (Python files). /// -## Exclude from OpenAPI +## Exclude from OpenAPI { #exclude-from-openapi } To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`: {* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *} -## Advanced description from docstring +## Advanced description from docstring { #advanced-description-from-docstring } You can limit the lines used from the docstring of a *path operation function* for OpenAPI. @@ -52,7 +52,7 @@ It won't show up in the documentation, but other tools (such as Sphinx) will be {* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *} -## Additional Responses +## Additional Responses { #additional-responses } You probably have seen how to declare the `response_model` and `status_code` for a *path operation*. @@ -62,7 +62,7 @@ You can also declare additional responses with their models, status codes, etc. There's a whole chapter here in the documentation about it, you can read it at [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}. -## OpenAPI Extra +## OpenAPI Extra { #openapi-extra } When you declare a *path operation* in your application, **FastAPI** automatically generates the relevant metadata about that *path operation* to be included in the OpenAPI schema. @@ -88,7 +88,7 @@ If you only need to declare additional responses, a more convenient way to do it You can extend the OpenAPI schema for a *path operation* using the parameter `openapi_extra`. -### OpenAPI Extensions +### OpenAPI Extensions { #openapi-extensions } This `openapi_extra` can be helpful, for example, to declare [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): @@ -129,7 +129,7 @@ And if you see the resulting OpenAPI (at `/openapi.json` in your API), you will } ``` -### Custom OpenAPI *path operation* schema +### Custom OpenAPI *path operation* schema { #custom-openapi-path-operation-schema } The dictionary in `openapi_extra` will be deeply merged with the automatically generated OpenAPI schema for the *path operation*. @@ -145,7 +145,7 @@ In this example, we didn't declare any Pydantic model. In fact, the request body Nevertheless, we can declare the expected schema for the request body. -### Custom OpenAPI content type +### Custom OpenAPI content type { #custom-openapi-content-type } Using this same trick, you could use a Pydantic model to define the JSON Schema that is then included in the custom OpenAPI schema section for the *path operation*. diff --git a/docs/en/docs/advanced/response-change-status-code.md b/docs/en/docs/advanced/response-change-status-code.md index 6d3f9f3e8..912ed0f1a 100644 --- a/docs/en/docs/advanced/response-change-status-code.md +++ b/docs/en/docs/advanced/response-change-status-code.md @@ -1,10 +1,10 @@ -# Response - Change Status Code +# Response - Change Status Code { #response-change-status-code } You probably read before that you can set a default [Response Status Code](../tutorial/response-status-code.md){.internal-link target=_blank}. But in some cases you need to return a different status code than the default. -## Use case +## Use case { #use-case } For example, imagine that you want to return an HTTP status code of "OK" `200` by default. @@ -14,7 +14,7 @@ But you still want to be able to filter and convert the data you return with a ` For those cases, you can use a `Response` parameter. -## Use a `Response` parameter +## Use a `Response` parameter { #use-a-response-parameter } You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies and headers). diff --git a/docs/en/docs/advanced/response-cookies.md b/docs/en/docs/advanced/response-cookies.md index f6d17f35d..d8f77b56a 100644 --- a/docs/en/docs/advanced/response-cookies.md +++ b/docs/en/docs/advanced/response-cookies.md @@ -1,6 +1,6 @@ -# Response Cookies +# Response Cookies { #response-cookies } -## Use a `Response` parameter +## Use a `Response` parameter { #use-a-response-parameter } You can declare a parameter of type `Response` in your *path operation function*. @@ -16,7 +16,7 @@ And if you declared a `response_model`, it will still be used to filter and conv You can also declare the `Response` parameter in dependencies, and set cookies (and headers) in them. -## Return a `Response` directly +## Return a `Response` directly { #return-a-response-directly } You can also create cookies when returning a `Response` directly in your code. @@ -36,7 +36,7 @@ And also that you are not sending any data that should have been filtered by a ` /// -### More info +### More info { #more-info } /// note | Technical Details diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md index 759b762b5..3197e1bd4 100644 --- a/docs/en/docs/advanced/response-directly.md +++ b/docs/en/docs/advanced/response-directly.md @@ -1,4 +1,4 @@ -# Return a Response Directly +# Return a Response Directly { #return-a-response-directly } When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc. @@ -10,7 +10,7 @@ But you can return a `JSONResponse` directly from your *path operations*. It might be useful, for example, to return custom headers or cookies. -## Return a `Response` +## Return a `Response` { #return-a-response } In fact, you can return any `Response` or any sub-class of it. @@ -26,7 +26,7 @@ It won't do any data conversion with Pydantic models, it won't convert the conte This gives you a lot of flexibility. You can return any data type, override any data declaration or validation, etc. -## Using the `jsonable_encoder` in a `Response` +## Using the `jsonable_encoder` in a `Response` { #using-the-jsonable-encoder-in-a-response } Because **FastAPI** doesn't make any changes to a `Response` you return, you have to make sure its contents are ready for it. @@ -44,7 +44,7 @@ You could also use `from starlette.responses import JSONResponse`. /// -## Returning a custom `Response` +## Returning a custom `Response` { #returning-a-custom-response } The example above shows all the parts you need, but it's not very useful yet, as you could have just returned the `item` directly, and **FastAPI** would put it in a `JSONResponse` for you, converting it to a `dict`, etc. All that by default. @@ -56,7 +56,7 @@ You could put your XML content in a string, put that in a `Response`, and return {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} -## Notes +## Notes { #notes } When you return a `Response` directly its data is not validated, converted (serialized), or documented automatically. diff --git a/docs/en/docs/advanced/response-headers.md b/docs/en/docs/advanced/response-headers.md index 97e888983..98747eabd 100644 --- a/docs/en/docs/advanced/response-headers.md +++ b/docs/en/docs/advanced/response-headers.md @@ -1,6 +1,6 @@ -# Response Headers +# Response Headers { #response-headers } -## Use a `Response` parameter +## Use a `Response` parameter { #use-a-response-parameter } You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies). @@ -16,7 +16,7 @@ And if you declared a `response_model`, it will still be used to filter and conv You can also declare the `Response` parameter in dependencies, and set headers (and cookies) in them. -## Return a `Response` directly +## Return a `Response` directly { #return-a-response-directly } You can also add headers when you return a `Response` directly. @@ -34,7 +34,7 @@ And as the `Response` can be used frequently to set headers and cookies, **FastA /// -## Custom Headers +## Custom Headers { #custom-headers } Keep in mind that custom proprietary headers can be added using the 'X-' prefix. diff --git a/docs/en/docs/advanced/security/http-basic-auth.md b/docs/en/docs/advanced/security/http-basic-auth.md index 234e2f940..01b98eeff 100644 --- a/docs/en/docs/advanced/security/http-basic-auth.md +++ b/docs/en/docs/advanced/security/http-basic-auth.md @@ -1,4 +1,4 @@ -# HTTP Basic Auth +# HTTP Basic Auth { #http-basic-auth } For the simplest cases, you can use HTTP Basic Auth. @@ -12,7 +12,7 @@ That tells the browser to show the integrated prompt for a username and password Then, when you type that username and password, the browser sends them in the header automatically. -## Simple HTTP Basic Auth +## Simple HTTP Basic Auth { #simple-http-basic-auth } * Import `HTTPBasic` and `HTTPBasicCredentials`. * Create a "`security` scheme" using `HTTPBasic`. @@ -26,7 +26,7 @@ When you try to open the URL for the first time (or click the "Execute" button i -## Check the username +## Check the username { #check-the-username } Here's a more complete example. @@ -52,7 +52,7 @@ if not (credentials.username == "stanleyjobson") or not (credentials.password == But by using the `secrets.compare_digest()` it will be secure against a type of attacks called "timing attacks". -### Timing Attacks +### Timing Attacks { #timing-attacks } But what's a "timing attack"? @@ -80,19 +80,19 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": Python will have to compare the whole `stanleyjobso` in both `stanleyjobsox` and `stanleyjobson` before realizing that both strings are not the same. So it will take some extra microseconds to reply back "Incorrect username or password". -#### The time to answer helps the attackers +#### The time to answer helps the attackers { #the-time-to-answer-helps-the-attackers } At that point, by noticing that the server took some microseconds longer to send the "Incorrect username or password" response, the attackers will know that they got _something_ right, some of the initial letters were right. And then they can try again knowing that it's probably something more similar to `stanleyjobsox` than to `johndoe`. -#### A "professional" attack +#### A "professional" attack { #a-professional-attack } Of course, the attackers would not try all this by hand, they would write a program to do it, possibly with thousands or millions of tests per second. And they would get just one extra correct letter at a time. But doing that, in some minutes or hours the attackers would have guessed the correct username and password, with the "help" of our application, just using the time taken to answer. -#### Fix it with `secrets.compare_digest()` +#### Fix it with `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest } But in our code we are actually using `secrets.compare_digest()`. @@ -100,7 +100,7 @@ In short, it will take the same time to compare `stanleyjobsox` to `stanleyjobso That way, using `secrets.compare_digest()` in your application code, it will be safe against this whole range of security attacks. -### Return the error +### Return the error { #return-the-error } After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again: diff --git a/docs/en/docs/advanced/security/index.md b/docs/en/docs/advanced/security/index.md index edb42132e..996d716b4 100644 --- a/docs/en/docs/advanced/security/index.md +++ b/docs/en/docs/advanced/security/index.md @@ -1,6 +1,6 @@ -# Advanced Security +# Advanced Security { #advanced-security } -## Additional Features +## Additional Features { #additional-features } There are some extra features to handle security apart from the ones covered in the [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank}. @@ -12,7 +12,7 @@ And it's possible that for your use case, the solution is in one of them. /// -## Read the Tutorial first +## Read the Tutorial first { #read-the-tutorial-first } The next sections assume you already read the main [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank}. diff --git a/docs/en/docs/advanced/security/oauth2-scopes.md b/docs/en/docs/advanced/security/oauth2-scopes.md index 4cb0b39bc..0a84435e6 100644 --- a/docs/en/docs/advanced/security/oauth2-scopes.md +++ b/docs/en/docs/advanced/security/oauth2-scopes.md @@ -1,4 +1,4 @@ -# OAuth2 scopes +# OAuth2 scopes { #oauth2-scopes } You can use OAuth2 scopes directly with **FastAPI**, they are integrated to work seamlessly. @@ -26,7 +26,7 @@ But if you know you need it, or you are curious, keep reading. /// -## OAuth2 scopes and OpenAPI +## OAuth2 scopes and OpenAPI { #oauth2-scopes-and-openapi } The OAuth2 specification defines "scopes" as a list of strings separated by spaces. @@ -58,7 +58,7 @@ For OAuth2 they are just strings. /// -## Global view +## Global view { #global-view } First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes: @@ -66,7 +66,7 @@ First, let's quickly see the parts that change from the examples in the main **T Now let's review those changes step by step. -## OAuth2 Security scheme +## OAuth2 Security scheme { #oauth2-security-scheme } The first change is that now we are declaring the OAuth2 security scheme with two available scopes, `me` and `items`. @@ -82,7 +82,7 @@ This is the same mechanism used when you give permissions while logging in with -## JWT token with scopes +## JWT token with scopes { #jwt-token-with-scopes } Now, modify the token *path operation* to return the scopes requested. @@ -100,7 +100,7 @@ But in your application, for security, you should make sure you only add the sco {* ../../docs_src/security/tutorial005_an_py310.py hl[156] *} -## Declare scopes in *path operations* and dependencies +## Declare scopes in *path operations* and dependencies { #declare-scopes-in-path-operations-and-dependencies } Now we declare that the *path operation* for `/users/me/items/` requires the scope `items`. @@ -136,7 +136,7 @@ But when you import `Query`, `Path`, `Depends`, `Security` and others from `fast /// -## Use `SecurityScopes` +## Use `SecurityScopes` { #use-securityscopes } Now update the dependency `get_current_user`. @@ -152,7 +152,7 @@ This `SecurityScopes` class is similar to `Request` (`Request` was used to get t {* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} -## Use the `scopes` +## Use the `scopes` { #use-the-scopes } The parameter `security_scopes` will be of type `SecurityScopes`. @@ -166,7 +166,7 @@ In this exception, we include the scopes required (if any) as a string separated {* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} -## Verify the `username` and data shape +## Verify the `username` and data shape { #verify-the-username-and-data-shape } We verify that we get a `username`, and extract the scopes. @@ -182,7 +182,7 @@ We also verify that we have a user with that username, and if not, we raise that {* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:128] *} -## Verify the `scopes` +## Verify the `scopes` { #verify-the-scopes } We now verify that all the scopes required, by this dependency and all the dependants (including *path operations*), are included in the scopes provided in the token received, otherwise raise an `HTTPException`. @@ -190,7 +190,7 @@ For this, we use `security_scopes.scopes`, that contains a `list` with all these {* ../../docs_src/security/tutorial005_an_py310.py hl[129:135] *} -## Dependency tree and scopes +## Dependency tree and scopes { #dependency-tree-and-scopes } Let's review again this dependency tree and the scopes. @@ -223,7 +223,7 @@ All depending on the `scopes` declared in each *path operation* and each depende /// -## More details about `SecurityScopes` +## More details about `SecurityScopes` { #more-details-about-securityscopes } You can use `SecurityScopes` at any point, and in multiple places, it doesn't have to be at the "root" dependency. @@ -233,7 +233,7 @@ Because the `SecurityScopes` will have all the scopes declared by dependants, yo They will be checked independently for each *path operation*. -## Check it +## Check it { #check-it } If you open the API docs, you can authenticate and specify which scopes you want to authorize. @@ -245,7 +245,7 @@ And if you select the scope `me` but not the scope `items`, you will be able to That's what would happen to a third party application that tried to access one of these *path operations* with a token provided by a user, depending on how many permissions the user gave the application. -## About third party integrations +## About third party integrations { #about-third-party-integrations } In this example we are using the OAuth2 "password" flow. @@ -269,6 +269,6 @@ But in the end, they are implementing the same OAuth2 standard. **FastAPI** includes utilities for all these OAuth2 authentication flows in `fastapi.security.oauth2`. -## `Security` in decorator `dependencies` +## `Security` in decorator `dependencies` { #security-in-decorator-dependencies } The same way you can define a `list` of `Depends` in the decorator's `dependencies` parameter (as explained in [Dependencies in path operation decorators](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), you could also use `Security` with `scopes` there. diff --git a/docs/en/docs/advanced/settings.md b/docs/en/docs/advanced/settings.md index 1af19a045..a218c3d01 100644 --- a/docs/en/docs/advanced/settings.md +++ b/docs/en/docs/advanced/settings.md @@ -1,4 +1,4 @@ -# Settings and Environment Variables +# Settings and Environment Variables { #settings-and-environment-variables } In many cases your application could need some external settings or configurations, for example secret keys, database credentials, credentials for email services, etc. @@ -12,17 +12,17 @@ To understand environment variables you can read [Environment Variables](../envi /// -## Types and validation +## Types and validation { #types-and-validation } These environment variables can only handle text strings, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, as Linux, Windows, macOS). That means that any value read in Python from an environment variable will be a `str`, and any conversion to a different type or any validation has to be done in code. -## Pydantic `Settings` +## Pydantic `Settings` { #pydantic-settings } Fortunately, Pydantic provides a great utility to handle these settings coming from environment variables with Pydantic: Settings management. -### Install `pydantic-settings` +### Install `pydantic-settings` { #install-pydantic-settings } First, make sure you create your [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and then install the `pydantic-settings` package: @@ -52,7 +52,7 @@ In Pydantic v1 it came included with the main package. Now it is distributed as /// -### Create the `Settings` object +### Create the `Settings` object { #create-the-settings-object } Import `BaseSettings` from Pydantic and create a sub-class, very much like with a Pydantic model. @@ -88,13 +88,13 @@ Then, when you create an instance of that `Settings` class (in this case, in the Next it will convert and validate the data. So, when you use that `settings` object, you will have data of the types you declared (e.g. `items_per_user` will be an `int`). -### Use the `settings` +### Use the `settings` { #use-the-settings } Then you can use the new `settings` object in your application: {* ../../docs_src/settings/tutorial001.py hl[18:20] *} -### Run the server +### Run the server { #run-the-server } Next, you would run the server passing the configurations as environment variables, for example you could set an `ADMIN_EMAIL` and `APP_NAME` with: @@ -120,7 +120,7 @@ The `app_name` would be `"ChimichangApp"`. And the `items_per_user` would keep its default value of `50`. -## Settings in another module +## Settings in another module { #settings-in-another-module } You could put those settings in another module file as you saw in [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}. @@ -138,13 +138,13 @@ You would also need a file `__init__.py` as you saw in [Bigger Applications - Mu /// -## Settings in a dependency +## Settings in a dependency { #settings-in-a-dependency } In some occasions it might be useful to provide the settings from a dependency, instead of having a global object with `settings` that is used everywhere. This could be especially useful during testing, as it's very easy to override a dependency with your own custom settings. -### The config file +### The config file { #the-config-file } Coming from the previous example, your `config.py` file could look like: @@ -152,7 +152,7 @@ Coming from the previous example, your `config.py` file could look like: Notice that now we don't create a default instance `settings = Settings()`. -### The main app file +### The main app file { #the-main-app-file } Now we create a dependency that returns a new `config.Settings()`. @@ -170,7 +170,7 @@ And then we can require it from the *path operation function* as a dependency an {* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} -### Settings and testing +### Settings and testing { #settings-and-testing } Then it would be very easy to provide a different settings object during testing by creating a dependency override for `get_settings`: @@ -180,7 +180,7 @@ In the dependency override we set a new value for the `admin_email` when creatin Then we can test that it is used. -## Reading a `.env` file +## Reading a `.env` file { #reading-a-env-file } If you have many settings that possibly change a lot, maybe in different environments, it might be useful to put them on a file and then read them from it as if they were environment variables. @@ -202,7 +202,7 @@ For this to work, you need to `pip install python-dotenv`. /// -### The `.env` file +### The `.env` file { #the-env-file } You could have a `.env` file with: @@ -211,7 +211,7 @@ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" ``` -### Read settings from `.env` +### Read settings from `.env` { #read-settings-from-env } And then update your `config.py` with: @@ -247,7 +247,7 @@ In Pydantic version 1 the configuration was done in an internal class `Config`, Here we define the config `env_file` inside of your Pydantic `Settings` class, and set the value to the filename with the dotenv file we want to use. -### Creating the `Settings` only once with `lru_cache` +### Creating the `Settings` only once with `lru_cache` { #creating-the-settings-only-once-with-lru-cache } Reading a file from disk is normally a costly (slow) operation, so you probably want to do it only once and then reuse the same settings object, instead of reading it for each request. @@ -274,7 +274,7 @@ But as we are using the `@lru_cache` decorator on top, the `Settings` object wil Then for any subsequent call of `get_settings()` in the dependencies for the next requests, instead of executing the internal code of `get_settings()` and creating a new `Settings` object, it will return the same object that was returned on the first call, again and again. -#### `lru_cache` Technical Details +#### `lru_cache` Technical Details { #lru-cache-technical-details } `@lru_cache` modifies the function it decorates to return the same value that was returned the first time, instead of computing it again, executing the code of the function every time. @@ -337,7 +337,7 @@ That way, it behaves almost as if it was just a global variable. But as it uses `@lru_cache` is part of `functools` which is part of Python's standard library, you can read more about it in the Python docs for `@lru_cache`. -## Recap +## Recap { #recap } You can use Pydantic Settings to handle the settings or configurations for your application, with all the power of Pydantic models. diff --git a/docs/en/docs/advanced/sub-applications.md b/docs/en/docs/advanced/sub-applications.md index 48e329fc1..fbd0e1af3 100644 --- a/docs/en/docs/advanced/sub-applications.md +++ b/docs/en/docs/advanced/sub-applications.md @@ -1,18 +1,18 @@ -# Sub Applications - Mounts +# Sub Applications - Mounts { #sub-applications-mounts } If you need to have two independent FastAPI applications, with their own independent OpenAPI and their own docs UIs, you can have a main app and "mount" one (or more) sub-application(s). -## Mounting a **FastAPI** application +## Mounting a **FastAPI** application { #mounting-a-fastapi-application } "Mounting" means adding a completely "independent" application in a specific path, that then takes care of handling everything under that path, with the _path operations_ declared in that sub-application. -### Top-level application +### Top-level application { #top-level-application } First, create the main, top-level, **FastAPI** application, and its *path operations*: {* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *} -### Sub-application +### Sub-application { #sub-application } Then, create your sub-application, and its *path operations*. @@ -20,7 +20,7 @@ This sub-application is just another standard FastAPI application, but this is t {* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *} -### Mount the sub-application +### Mount the sub-application { #mount-the-sub-application } In your top-level application, `app`, mount the sub-application, `subapi`. @@ -28,7 +28,7 @@ In this case, it will be mounted at the path `/subapi`: {* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *} -### Check the automatic API docs +### Check the automatic API docs { #check-the-automatic-api-docs } Now, run the `fastapi` command with your file: @@ -56,7 +56,7 @@ You will see the automatic API docs for the sub-application, including only its If you try interacting with any of the two user interfaces, they will work correctly, because the browser will be able to talk to each specific app or sub-app. -### Technical Details: `root_path` +### Technical Details: `root_path` { #technical-details-root-path } When you mount a sub-application as described above, FastAPI will take care of communicating the mount path for the sub-application using a mechanism from the ASGI specification called a `root_path`. diff --git a/docs/en/docs/advanced/templates.md b/docs/en/docs/advanced/templates.md index d9b0ca6f1..f41c47fe8 100644 --- a/docs/en/docs/advanced/templates.md +++ b/docs/en/docs/advanced/templates.md @@ -1,4 +1,4 @@ -# Templates +# Templates { #templates } You can use any template engine you want with **FastAPI**. @@ -6,7 +6,7 @@ A common choice is Jinja2, the same one used by Flask and other tools. There are utilities to configure it easily that you can use directly in your **FastAPI** application (provided by Starlette). -## Install dependencies +## Install dependencies { #install-dependencies } Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `jinja2`: @@ -20,7 +20,7 @@ $ pip install jinja2 -## Using `Jinja2Templates` +## Using `Jinja2Templates` { #using-jinja2templates } * Import `Jinja2Templates`. * Create a `templates` object that you can reuse later. @@ -51,7 +51,7 @@ You could also use `from starlette.templating import Jinja2Templates`. /// -## Writing templates +## Writing templates { #writing-templates } Then you can write a template at `templates/item.html` with, for example: @@ -59,7 +59,7 @@ Then you can write a template at `templates/item.html` with, for example: {!../../docs_src/templates/templates/item.html!} ``` -### Template Context Values +### Template Context Values { #template-context-values } In the HTML that contains: @@ -83,7 +83,7 @@ For example, with an ID of `42`, this would render: Item ID: 42 ``` -### Template `url_for` Arguments +### Template `url_for` Arguments { #template-url-for-arguments } You can also use `url_for()` inside of the template, it takes as arguments the same arguments that would be used by your *path operation function*. @@ -105,7 +105,7 @@ For example, with an ID of `42`, this would render: ``` -## Templates and static files +## Templates and static files { #templates-and-static-files } You can also use `url_for()` inside of the template, and use it, for example, with the `StaticFiles` you mounted with the `name="static"`. @@ -121,6 +121,6 @@ In this example, it would link to a CSS file at `static/styles.css` with: And because you are using `StaticFiles`, that CSS file would be served automatically by your **FastAPI** application at the URL `/static/styles.css`. -## More details +## More details { #more-details } For more details, including how to test templates, check Starlette's docs on templates. diff --git a/docs/en/docs/advanced/testing-dependencies.md b/docs/en/docs/advanced/testing-dependencies.md index 17b4f9814..b52b47c96 100644 --- a/docs/en/docs/advanced/testing-dependencies.md +++ b/docs/en/docs/advanced/testing-dependencies.md @@ -1,6 +1,6 @@ -# Testing Dependencies with Overrides +# Testing Dependencies with Overrides { #testing-dependencies-with-overrides } -## Overriding dependencies during testing +## Overriding dependencies during testing { #overriding-dependencies-during-testing } There are some scenarios where you might want to override a dependency during testing. @@ -8,7 +8,7 @@ You don't want the original dependency to run (nor any of the sub-dependencies i Instead, you want to provide a different dependency that will be used only during tests (possibly only some specific tests), and will provide a value that can be used where the value of the original dependency was used. -### Use cases: external service +### Use cases: external service { #use-cases-external-service } An example could be that you have an external authentication provider that you need to call. @@ -20,7 +20,7 @@ You probably want to test the external provider once, but not necessarily call i In this case, you can override the dependency that calls that provider, and use a custom dependency that returns a mock user, only for your tests. -### Use the `app.dependency_overrides` attribute +### Use the `app.dependency_overrides` attribute { #use-the-app-dependency-overrides-attribute } For these cases, your **FastAPI** application has an attribute `app.dependency_overrides`, it is a simple `dict`. diff --git a/docs/en/docs/advanced/testing-events.md b/docs/en/docs/advanced/testing-events.md index 0c554c4ec..d0f2d1a79 100644 --- a/docs/en/docs/advanced/testing-events.md +++ b/docs/en/docs/advanced/testing-events.md @@ -1,4 +1,4 @@ -# Testing Events: startup - shutdown +# Testing Events: startup - shutdown { #testing-events-startup-shutdown } When you need your event handlers (`startup` and `shutdown`) to run in your tests, you can use the `TestClient` with a `with` statement: diff --git a/docs/en/docs/advanced/testing-websockets.md b/docs/en/docs/advanced/testing-websockets.md index 60dfdc343..22f9bb4a0 100644 --- a/docs/en/docs/advanced/testing-websockets.md +++ b/docs/en/docs/advanced/testing-websockets.md @@ -1,4 +1,4 @@ -# Testing WebSockets +# Testing WebSockets { #testing-websockets } You can use the same `TestClient` to test WebSockets. diff --git a/docs/en/docs/advanced/using-request-directly.md b/docs/en/docs/advanced/using-request-directly.md index 2f88c8f20..e412ad462 100644 --- a/docs/en/docs/advanced/using-request-directly.md +++ b/docs/en/docs/advanced/using-request-directly.md @@ -1,4 +1,4 @@ -# Using the Request Directly +# Using the Request Directly { #using-the-request-directly } Up to now, you have been declaring the parts of the request that you need with their types. @@ -13,7 +13,7 @@ And by doing so, **FastAPI** is validating that data, converting it and generati But there are situations where you might need to access the `Request` object directly. -## Details about the `Request` object +## Details about the `Request` object { #details-about-the-request-object } As **FastAPI** is actually **Starlette** underneath, with a layer of several tools on top, you can use Starlette's `Request` object directly when you need to. @@ -23,7 +23,7 @@ Although any other parameter declared normally (for example, the body with a Pyd But there are specific cases where it's useful to get the `Request` object. -## Use the `Request` object directly +## Use the `Request` object directly { #use-the-request-object-directly } Let's imagine you want to get the client's IP address/host inside of your *path operation function*. @@ -43,7 +43,7 @@ The same way, you can declare any other parameter as normally, and additionally, /// -## `Request` documentation +## `Request` documentation { #request-documentation } You can read more details about the `Request` object in the official Starlette documentation site. diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md index ee8e901df..4ba24637f 100644 --- a/docs/en/docs/advanced/websockets.md +++ b/docs/en/docs/advanced/websockets.md @@ -1,8 +1,8 @@ -# WebSockets +# WebSockets { #websockets } You can use WebSockets with **FastAPI**. -## Install `WebSockets` +## Install `WebSockets` { #install-websockets } Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `websockets`: @@ -16,9 +16,9 @@ $ pip install websockets -## WebSockets client +## WebSockets client { #websockets-client } -### In production +### In production { #in-production } In your production system, you probably have a frontend created with a modern framework like React, Vue.js or Angular. @@ -40,7 +40,7 @@ But it's the simplest way to focus on the server-side of WebSockets and have a w {* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *} -## Create a `websocket` +## Create a `websocket` { #create-a-websocket } In your **FastAPI** application, create a `websocket`: @@ -54,7 +54,7 @@ You could also use `from starlette.websockets import WebSocket`. /// -## Await for messages and send messages +## Await for messages and send messages { #await-for-messages-and-send-messages } In your WebSocket route you can `await` for messages and send messages. @@ -62,7 +62,7 @@ In your WebSocket route you can `await` for messages and send messages. You can receive and send binary, text, and JSON data. -## Try it +## Try it { #try-it } If your file is named `main.py`, run your application with: @@ -96,7 +96,7 @@ You can send (and receive) many messages: And all of them will use the same WebSocket connection. -## Using `Depends` and others +## Using `Depends` and others { #using-depends-and-others } In WebSocket endpoints you can import from `fastapi` and use: @@ -119,7 +119,7 @@ You can use a closing code from the -## Handling disconnections and multiple clients +## Handling disconnections and multiple clients { #handling-disconnections-and-multiple-clients } When a WebSocket connection is closed, the `await websocket.receive_text()` will raise a `WebSocketDisconnect` exception, which you can then catch and handle like in this example. @@ -178,7 +178,7 @@ If you need something easy to integrate with FastAPI but that is more robust, su /// -## More info +## More info { #more-info } To learn more about the options, check Starlette's documentation for: diff --git a/docs/en/docs/advanced/wsgi.md b/docs/en/docs/advanced/wsgi.md index 296eb1364..29fd2d359 100644 --- a/docs/en/docs/advanced/wsgi.md +++ b/docs/en/docs/advanced/wsgi.md @@ -1,10 +1,10 @@ -# Including WSGI - Flask, Django, others +# Including WSGI - Flask, Django, others { #including-wsgi-flask-django-others } You can mount WSGI applications as you saw with [Sub Applications - Mounts](sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank}. For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc. -## Using `WSGIMiddleware` +## Using `WSGIMiddleware` { #using-wsgimiddleware } You need to import `WSGIMiddleware`. @@ -14,7 +14,7 @@ And then mount that under a path. {* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *} -## Check it +## Check it { #check-it } Now, every request under the path `/v1/` will be handled by the Flask application. diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index 326f0dbe1..f0576bc47 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -1,8 +1,8 @@ -# Alternatives, Inspiration and Comparisons +# Alternatives, Inspiration and Comparisons { #alternatives-inspiration-and-comparisons } What inspired **FastAPI**, how it compares to alternatives and what it learned from them. -## Intro +## Intro { #intro } **FastAPI** wouldn't exist if not for the previous work of others. @@ -12,9 +12,9 @@ I have been avoiding the creation of a new framework for several years. First I But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints). -## Previous tools +## Previous tools { #previous-tools } -### Django +### Django { #django } It's the most popular Python framework and is widely trusted. It is used to build systems like Instagram. @@ -22,7 +22,7 @@ It's relatively tightly coupled with relational databases (like MySQL or Postgre It was created to generate the HTML in the backend, not to create APIs used by a modern frontend (like React, Vue.js and Angular) or by other systems (like IoT devices) communicating with it. -### Django REST Framework +### Django REST Framework { #django-rest-framework } Django REST framework was created to be a flexible toolkit for building Web APIs using Django underneath, to improve its API capabilities. @@ -42,7 +42,7 @@ Have an automatic API documentation web user interface. /// -### Flask +### Flask { #flask } Flask is a "microframework", it doesn't include database integrations nor many of the things that come by default in Django. @@ -64,7 +64,7 @@ Have a simple and easy to use routing system. /// -### Requests +### Requests { #requests } **FastAPI** is not actually an alternative to **Requests**. Their scope is very different. @@ -106,7 +106,7 @@ See the similarities in `requests.get(...)` and `@app.get(...)`. /// -### Swagger / OpenAPI +### Swagger / OpenAPI { #swagger-openapi } The main feature I wanted from Django REST Framework was the automatic API documentation. @@ -131,11 +131,11 @@ These two were chosen for being fairly popular and stable, but doing a quick sea /// -### Flask REST frameworks +### Flask REST frameworks { #flask-rest-frameworks } There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit. -### Marshmallow +### Marshmallow { #marshmallow } One of the main features needed by API systems is data "serialization" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc. @@ -153,7 +153,7 @@ Use code to define "schemas" that provide data types and validation, automatical /// -### Webargs +### Webargs { #webargs } Another big feature required by APIs is parsing data from incoming requests. @@ -175,7 +175,7 @@ Have automatic validation of incoming request data. /// -### APISpec +### APISpec { #apispec } Marshmallow and Webargs provide validation, parsing and serialization as plug-ins. @@ -205,7 +205,7 @@ Support the open standard for APIs, OpenAPI. /// -### Flask-apispec +### Flask-apispec { #flask-apispec } It's a Flask plug-in, that ties together Webargs, Marshmallow and APISpec. @@ -237,7 +237,7 @@ Generate the OpenAPI schema automatically, from the same code that defines seria /// -### NestJS (and Angular) +### NestJS (and Angular) { #nestjs-and-angular } This isn't even Python, NestJS is a JavaScript (TypeScript) NodeJS framework inspired by Angular. @@ -259,7 +259,7 @@ Have a powerful dependency injection system. Find a way to minimize code repetit /// -### Sanic +### Sanic { #sanic } It was one of the first extremely fast Python frameworks based on `asyncio`. It was made to be very similar to Flask. @@ -279,7 +279,7 @@ That's why **FastAPI** is based on Starlette, as it is the fastest framework ava /// -### Falcon +### Falcon { #falcon } Falcon is another high performance Python framework, it is designed to be minimal, and work as the foundation of other frameworks like Hug. @@ -297,7 +297,7 @@ Although in FastAPI it's optional, and is used mainly to set headers, cookies, a /// -### Molten +### Molten { #molten } I discovered Molten in the first stages of building **FastAPI**. And it has quite similar ideas: @@ -321,7 +321,7 @@ This actually inspired updating parts of Pydantic, to support the same validatio /// -### Hug +### Hug { #hug } Hug was one of the first frameworks to implement the declaration of API parameter types using Python type hints. This was a great idea that inspired other tools to do the same. @@ -351,7 +351,7 @@ Hug inspired **FastAPI** to declare a `response` parameter in functions to set h /// -### APIStar (<= 0.5) +### APIStar (<= 0.5) { #apistar-0-5 } Right before deciding to build **FastAPI** I found **APIStar** server. It had almost everything I was looking for and had a great design. @@ -399,9 +399,9 @@ I consider **FastAPI** a "spiritual successor" to APIStar, while improving and i /// -## Used by **FastAPI** +## Used by **FastAPI** { #used-by-fastapi } -### Pydantic +### Pydantic { #pydantic } Pydantic is a library to define data validation, serialization and documentation (using JSON Schema) based on Python type hints. @@ -417,7 +417,7 @@ Handle all the data validation, data serialization and automatic model documenta /// -### Starlette +### Starlette { #starlette } Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high-performance asyncio services. @@ -462,7 +462,7 @@ So, anything that you can do with Starlette, you can do it directly with **FastA /// -### Uvicorn +### Uvicorn { #uvicorn } Uvicorn is a lightning-fast ASGI server, built on uvloop and httptools. @@ -480,6 +480,6 @@ Check more details in the [Deployment](deployment/index.md){.internal-link targe /// -## Benchmarks and speed +## Benchmarks and speed { #benchmarks-and-speed } To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](benchmarks.md){.internal-link target=_blank}. diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md index 8207ec480..1d2be0bb6 100644 --- a/docs/en/docs/async.md +++ b/docs/en/docs/async.md @@ -1,8 +1,8 @@ -# Concurrency and async / await +# Concurrency and async / await { #concurrency-and-async-await } Details about the `async def` syntax for *path operation functions* and some background about asynchronous code, concurrency, and parallelism. -## In a hurry? +## In a hurry? { #in-a-hurry } TL;DR: @@ -54,7 +54,7 @@ Anyway, in any of the cases above, FastAPI will still work asynchronously and be But by following the steps above, it will be able to do some performance optimizations. -## Technical Details +## Technical Details { #technical-details } Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax. @@ -64,7 +64,7 @@ Let's see that phrase by parts in the sections below: * **`async` and `await`** * **Coroutines** -## Asynchronous Code +## Asynchronous Code { #asynchronous-code } Asynchronous code just means that the language 💬 has a way to tell the computer / program 🤖 that at some point in the code, it 🤖 will have to wait for *something else* to finish somewhere else. Let's say that *something else* is called "slow-file" 📝. @@ -93,7 +93,7 @@ Instead of that, by being an "asynchronous" system, once finished, the task can For "synchronous" (contrary to "asynchronous") they commonly also use the term "sequential", because the computer / program follows all the steps in sequence before switching to a different task, even if those steps involve waiting. -### Concurrency and Burgers +### Concurrency and Burgers { #concurrency-and-burgers } This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**. @@ -103,7 +103,7 @@ But the details between *concurrency* and *parallelism* are quite different. To see the difference, imagine the following story about burgers: -### Concurrent Burgers +### Concurrent Burgers { #concurrent-burgers } You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you. 😍 @@ -163,7 +163,7 @@ So you wait for your crush to finish the story (finish the current work ⏯ / ta Then you go to the counter 🔀, to the initial task that is now finished ⏯, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter ⏹. That in turn, creates a new task, of "eating burgers" 🔀 ⏯, but the previous one of "getting burgers" is finished ⏹. -### Parallel Burgers +### Parallel Burgers { #parallel-burgers } Now let's imagine these aren't "Concurrent Burgers", but "Parallel Burgers". @@ -233,7 +233,7 @@ And you have to wait 🕙 in the line for a long time or you lose your turn. You probably wouldn't want to take your crush 😍 with you to run errands at the bank 🏦. -### Burger Conclusion +### Burger Conclusion { #burger-conclusion } In this scenario of "fast food burgers with your crush", as there is a lot of waiting 🕙, it makes a lot more sense to have a concurrent system ⏸🔀⏯. @@ -253,7 +253,7 @@ And that's the same level of performance you get with **FastAPI**. And as you can have parallelism and asynchronicity at the same time, you get higher performance than most of the tested NodeJS frameworks and on par with Go, which is a compiled language closer to C (all thanks to Starlette). -### Is concurrency better than parallelism? +### Is concurrency better than parallelism? { #is-concurrency-better-than-parallelism } Nope! That's not the moral of the story. @@ -290,7 +290,7 @@ For example: * **Machine Learning**: it normally requires lots of "matrix" and "vector" multiplications. Think of a huge spreadsheet with numbers and multiplying all of them together at the same time. * **Deep Learning**: this is a sub-field of Machine Learning, so, the same applies. It's just that there is not a single spreadsheet of numbers to multiply, but a huge set of them, and in many cases, you use a special processor to build and / or use those models. -### Concurrency + Parallelism: Web + Machine Learning +### Concurrency + Parallelism: Web + Machine Learning { #concurrency-parallelism-web-machine-learning } With **FastAPI** you can take advantage of concurrency that is very common for web development (the same main attraction of NodeJS). @@ -300,7 +300,7 @@ That, plus the simple fact that Python is the main language for **Data Science** To see how to achieve this parallelism in production see the section about [Deployment](deployment/index.md){.internal-link target=_blank}. -## `async` and `await` +## `async` and `await` { #async-and-await } Modern versions of Python have a very intuitive way to define asynchronous code. This makes it look just like normal "sequential" code and do the "awaiting" for you at the right moments. @@ -349,7 +349,7 @@ async def read_burgers(): return burgers ``` -### More technical details +### More technical details { #more-technical-details } You might have noticed that `await` can only be used inside of functions defined with `async def`. @@ -361,7 +361,7 @@ If you are working with **FastAPI** you don't have to worry about that, because But if you want to use `async` / `await` without FastAPI, you can do it as well. -### Write your own async code +### Write your own async code { #write-your-own-async-code } Starlette (and **FastAPI**) are based on AnyIO, which makes it compatible with both Python's standard library asyncio and Trio. @@ -371,7 +371,7 @@ And even if you were not using FastAPI, you could also write your own async appl I created another library on top of AnyIO, as a thin layer on top, to improve a bit the type annotations and get better **autocompletion**, **inline errors**, etc. It also has a friendly introduction and tutorial to help you **understand** and write **your own async code**: Asyncer. It would be particularly useful if you need to **combine async code with regular** (blocking/synchronous) code. -### Other forms of asynchronous code +### Other forms of asynchronous code { #other-forms-of-asynchronous-code } This style of using `async` and `await` is relatively new in the language. @@ -385,13 +385,13 @@ In previous versions of Python, you could have used threads or callback hell. -## Coroutines +## Coroutines { #coroutines } **Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function, that it can start and that it will end at some point, but that it might be paused ⏸ internally too, whenever there is an `await` inside of it. But all this functionality of using asynchronous code with `async` and `await` is many times summarized as using "coroutines". It is comparable to the main key feature of Go, the "Goroutines". -## Conclusion +## Conclusion { #conclusion } Let's see the same phrase from above: @@ -401,7 +401,7 @@ That should make more sense now. ✨ All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance. -## Very Technical Details +## Very Technical Details { #very-technical-details } /// warning @@ -413,7 +413,7 @@ If you have quite some technical knowledge (coroutines, threads, blocking, etc.) /// -### Path operation functions +### Path operation functions { #path-operation-functions } When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server). @@ -421,15 +421,15 @@ If you are coming from another async framework that does not work in the way des Still, in both situations, chances are that **FastAPI** will [still be faster](index.md#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework. -### Dependencies +### Dependencies { #dependencies } The same applies for [dependencies](tutorial/dependencies/index.md){.internal-link target=_blank}. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool. -### Sub-dependencies +### Sub-dependencies { #sub-dependencies } You can have multiple dependencies and [sub-dependencies](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited". -### Other utility functions +### Other utility functions { #other-utility-functions } Any other utility function that you call directly can be created with normal `def` or `async def` and FastAPI won't affect the way you call it. diff --git a/docs/en/docs/benchmarks.md b/docs/en/docs/benchmarks.md index 62266c449..551f6316d 100644 --- a/docs/en/docs/benchmarks.md +++ b/docs/en/docs/benchmarks.md @@ -1,10 +1,10 @@ -# Benchmarks +# Benchmarks { #benchmarks } Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). But when checking benchmarks and comparisons you should keep the following in mind. -## Benchmarks and speed +## Benchmarks and speed { #benchmarks-and-speed } When you check the benchmarks, it is common to see several tools of different types compared as equivalent. diff --git a/docs/en/docs/deployment/cloud.md b/docs/en/docs/deployment/cloud.md index c6d408f8c..cb723dd13 100644 --- a/docs/en/docs/deployment/cloud.md +++ b/docs/en/docs/deployment/cloud.md @@ -1,10 +1,10 @@ -# Deploy FastAPI on Cloud Providers +# Deploy FastAPI on Cloud Providers { #deploy-fastapi-on-cloud-providers } You can use virtually **any cloud provider** to deploy your FastAPI application. In most of the cases, the main cloud providers have guides to deploy FastAPI with them. -## Cloud Providers - Sponsors +## Cloud Providers - Sponsors { #cloud-providers-sponsors } Some cloud providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**. diff --git a/docs/en/docs/deployment/concepts.md b/docs/en/docs/deployment/concepts.md index ed635a920..2174443f0 100644 --- a/docs/en/docs/deployment/concepts.md +++ b/docs/en/docs/deployment/concepts.md @@ -1,4 +1,4 @@ -# Deployments Concepts +# Deployments Concepts { #deployments-concepts } When deploying a **FastAPI** application, or actually, any type of web API, there are several concepts that you probably care about, and using them you can find the **most appropriate** way to **deploy your application**. @@ -23,7 +23,7 @@ In the next chapters, I'll give you more **concrete recipes** to deploy FastAPI But for now, let's check these important **conceptual ideas**. These concepts also apply to any other type of web API. 💡 -## Security - HTTPS +## Security - HTTPS { #security-https } In the [previous chapter about HTTPS](https.md){.internal-link target=_blank} we learned about how HTTPS provides encryption for your API. @@ -31,7 +31,7 @@ We also saw that HTTPS is normally provided by a component **external** to your And there has to be something in charge of **renewing the HTTPS certificates**, it could be the same component or it could be something different. -### Example Tools for HTTPS +### Example Tools for HTTPS { #example-tools-for-https } Some of the tools you could use as a TLS Termination Proxy are: @@ -55,11 +55,11 @@ I'll show you some concrete examples in the next chapters. Then the next concepts to consider are all about the program running your actual API (e.g. Uvicorn). -## Program and Process +## Program and Process { #program-and-process } We will talk a lot about the running "**process**", so it's useful to have clarity about what it means, and what's the difference with the word "**program**". -### What is a Program +### What is a Program { #what-is-a-program } The word **program** is commonly used to describe many things: @@ -67,7 +67,7 @@ The word **program** is commonly used to describe many things: * The **file** that can be **executed** by the operating system, for example: `python`, `python.exe` or `uvicorn`. * A particular program while it is **running** on the operating system, using the CPU, and storing things in memory. This is also called a **process**. -### What is a Process +### What is a Process { #what-is-a-process } The word **process** is normally used in a more specific way, only referring to the thing that is running in the operating system (like in the last point above): @@ -88,11 +88,11 @@ And, for example, you will probably see that there are multiple processes runnin Now that we know the difference between the terms **process** and **program**, let's continue talking about deployments. -## Running on Startup +## Running on Startup { #running-on-startup } In most cases, when you create a web API, you want it to be **always running**, uninterrupted, so that your clients can always access it. This is of course, unless you have a specific reason why you want it to run only in certain situations, but most of the time you want it constantly running and **available**. -### In a Remote Server +### In a Remote Server { #in-a-remote-server } When you set up a remote server (a cloud server, a virtual machine, etc.) the simplest thing you can do is use `fastapi run` (which uses Uvicorn) or something similar, manually, the same way you do when developing locally. @@ -102,15 +102,15 @@ But if your connection to the server is lost, the **running process** will proba And if the server is restarted (for example after updates, or migrations from the cloud provider) you probably **won't notice it**. And because of that, you won't even know that you have to restart the process manually. So, your API will just stay dead. 😱 -### Run Automatically on Startup +### Run Automatically on Startup { #run-automatically-on-startup } In general, you will probably want the server program (e.g. Uvicorn) to be started automatically on server startup, and without needing any **human intervention**, to have a process always running with your API (e.g. Uvicorn running your FastAPI app). -### Separate Program +### Separate Program { #separate-program } To achieve this, you will normally have a **separate program** that would make sure your application is run on startup. And in many cases, it would also make sure other components or applications are also run, for example, a database. -### Example Tools to Run at Startup +### Example Tools to Run at Startup { #example-tools-to-run-at-startup } Some examples of the tools that can do this job are: @@ -125,29 +125,29 @@ Some examples of the tools that can do this job are: I'll give you more concrete examples in the next chapters. -## Restarts +## Restarts { #restarts } Similar to making sure your application is run on startup, you probably also want to make sure it is **restarted** after failures. -### We Make Mistakes +### We Make Mistakes { #we-make-mistakes } We, as humans, make **mistakes**, all the time. Software almost *always* has **bugs** hidden in different places. 🐛 And we as developers keep improving the code as we find those bugs and as we implement new features (possibly adding new bugs too 😅). -### Small Errors Automatically Handled +### Small Errors Automatically Handled { #small-errors-automatically-handled } When building web APIs with FastAPI, if there's an error in our code, FastAPI will normally contain it to the single request that triggered the error. 🛡 The client will get a **500 Internal Server Error** for that request, but the application will continue working for the next requests instead of just crashing completely. -### Bigger Errors - Crashes +### Bigger Errors - Crashes { #bigger-errors-crashes } Nevertheless, there might be cases where we write some code that **crashes the entire application** making Uvicorn and Python crash. 💥 And still, you would probably not want the application to stay dead because there was an error in one place, you probably want it to **continue running** at least for the *path operations* that are not broken. -### Restart After Crash +### Restart After Crash { #restart-after-crash } But in those cases with really bad errors that crash the running **process**, you would want an external component that is in charge of **restarting** the process, at least a couple of times... @@ -161,7 +161,7 @@ So let's focus on the main cases, where it could crash entirely in some particul You would probably want to have the thing in charge of restarting your application as an **external component**, because by that point, the same application with Uvicorn and Python already crashed, so there's nothing in the same code of the same app that could do anything about it. -### Example Tools to Restart Automatically +### Example Tools to Restart Automatically { #example-tools-to-restart-automatically } In most cases, the same tool that is used to **run the program on startup** is also used to handle automatic **restarts**. @@ -176,19 +176,19 @@ For example, this could be handled by: * Handled internally by a cloud provider as part of their services * Others... -## Replication - Processes and Memory +## Replication - Processes and Memory { #replication-processes-and-memory } With a FastAPI application, using a server program like the `fastapi` command that runs Uvicorn, running it once in **one process** can serve multiple clients concurrently. But in many cases, you will want to run several worker processes at the same time. -### Multiple Processes - Workers +### Multiple Processes - Workers { #multiple-processes-workers } If you have more clients than what a single process can handle (for example if the virtual machine is not too big) and you have **multiple cores** in the server's CPU, then you could have **multiple processes** running with the same application at the same time, and distribute all the requests among them. When you run **multiple processes** of the same API program, they are commonly called **workers**. -### Worker Processes and Ports +### Worker Processes and Ports { #worker-processes-and-ports } Remember from the docs [About HTTPS](https.md){.internal-link target=_blank} that only one process can be listening on one combination of port and IP address in a server? @@ -196,19 +196,19 @@ This is still true. So, to be able to have **multiple processes** at the same time, there has to be a **single process listening on a port** that then transmits the communication to each worker process in some way. -### Memory per Process +### Memory per Process { #memory-per-process } Now, when the program loads things in memory, for example, a machine learning model in a variable, or the contents of a large file in a variable, all that **consumes a bit of the memory (RAM)** of the server. And multiple processes normally **don't share any memory**. This means that each running process has its own things, variables, and memory. And if you are consuming a large amount of memory in your code, **each process** will consume an equivalent amount of memory. -### Server Memory +### Server Memory { #server-memory } For example, if your code loads a Machine Learning model with **1 GB in size**, when you run one process with your API, it will consume at least 1 GB of RAM. And if you start **4 processes** (4 workers), each will consume 1 GB of RAM. So in total, your API will consume **4 GB of RAM**. And if your remote server or virtual machine only has 3 GB of RAM, trying to load more than 4 GB of RAM will cause problems. 🚨 -### Multiple Processes - An Example +### Multiple Processes - An Example { #multiple-processes-an-example } In this example, there's a **Manager Process** that starts and controls two **Worker Processes**. @@ -224,7 +224,7 @@ An interesting detail is that the percentage of the **CPU used** by each process If you have an API that does a comparable amount of computations every time and you have a lot of clients, then the **CPU utilization** will probably *also be stable* (instead of constantly going up and down quickly). -### Examples of Replication Tools and Strategies +### Examples of Replication Tools and Strategies { #examples-of-replication-tools-and-strategies } There can be several approaches to achieve this, and I'll tell you more about specific strategies in the next chapters, for example when talking about Docker and containers. @@ -247,7 +247,7 @@ I'll tell you more about container images, Docker, Kubernetes, etc. in a future /// -## Previous Steps Before Starting +## Previous Steps Before Starting { #previous-steps-before-starting } There are many cases where you want to perform some steps **before starting** your application. @@ -269,7 +269,7 @@ In that case, you wouldn't have to worry about any of this. 🤷 /// -### Examples of Previous Steps Strategies +### Examples of Previous Steps Strategies { #examples-of-previous-steps-strategies } This will **depend heavily** on the way you **deploy your system**, and it would probably be connected to the way you start programs, handling restarts, etc. @@ -285,7 +285,7 @@ I'll give you more concrete examples for doing this with containers in a future /// -## Resource Utilization +## Resource Utilization { #resource-utilization } Your server(s) is (are) a **resource**, you can consume or **utilize**, with your programs, the computation time on the CPUs, and the RAM memory available. @@ -305,7 +305,7 @@ You could put an **arbitrary number** to target, for example, something **betwee You can use simple tools like `htop` to see the CPU and RAM used in your server or the amount used by each process. Or you can use more complex monitoring tools, which may be distributed across servers, etc. -## Recap +## Recap { #recap } You have been reading here some of the main concepts that you would probably need to keep in mind when deciding how to deploy your application: diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index b106f7ac3..a1de2dc46 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -1,4 +1,4 @@ -# FastAPI in Containers - Docker +# FastAPI in Containers - Docker { #fastapi-in-containers-docker } When deploying FastAPI applications a common approach is to build a **Linux container image**. It's normally done using **Docker**. You can then deploy that container image in one of a few possible ways. @@ -32,7 +32,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] -## What is a Container +## What is a Container { #what-is-a-container } Containers (mainly Linux containers) are a very **lightweight** way to package applications including all their dependencies and necessary files while keeping them isolated from other containers (other applications or components) in the same system. @@ -42,7 +42,7 @@ This way, containers consume **little resources**, an amount comparable to runni Containers also have their own **isolated** running processes (commonly just one process), file system, and network, simplifying deployment, security, development, etc. -## What is a Container Image +## What is a Container Image { #what-is-a-container-image } A **container** is run from a **container image**. @@ -56,7 +56,7 @@ A container image is comparable to the **program** file and contents, e.g. `pyth And the **container** itself (in contrast to the **container image**) is the actual running instance of the image, comparable to a **process**. In fact, a container is running only when it has a **process running** (and normally it's only a single process). The container stops when there's no process running in it. -## Container Images +## Container Images { #container-images } Docker has been one of the main tools to create and manage **container images** and **containers**. @@ -79,7 +79,7 @@ So, you would run **multiple containers** with different things, like a database All the container management systems (like Docker or Kubernetes) have these networking features integrated into them. -## Containers and Processes +## Containers and Processes { #containers-and-processes } A **container image** normally includes in its metadata the default program or command that should be run when the **container** is started and the parameters to be passed to that program. Very similar to what would be if it was in the command line. @@ -91,7 +91,7 @@ A container normally has a **single process**, but it's also possible to start s But it's not possible to have a running container without **at least one running process**. If the main process stops, the container stops. -## Build a Docker Image for FastAPI +## Build a Docker Image for FastAPI { #build-a-docker-image-for-fastapi } Okay, let's build something now! 🚀 @@ -103,7 +103,7 @@ This is what you would want to do in **most cases**, for example: * When running on a **Raspberry Pi** * Using a cloud service that would run a container image for you, etc. -### Package Requirements +### Package Requirements { #package-requirements } You would normally have the **package requirements** for your application in some file. @@ -138,7 +138,7 @@ There are other formats and tools to define and install package dependencies. /// -### Create the **FastAPI** Code +### Create the **FastAPI** Code { #create-the-fastapi-code } * Create an `app` directory and enter it. * Create an empty file `__init__.py`. @@ -162,7 +162,7 @@ def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` -### Dockerfile +### Dockerfile { #dockerfile } Now in the same project directory create a file `Dockerfile` with: @@ -238,7 +238,7 @@ Make sure to **always** use the **exec form** of the `CMD` instruction, as expla /// -#### Use `CMD` - Exec Form +#### Use `CMD` - Exec Form { #use-cmd-exec-form } The `CMD` Docker instruction can be written using two forms: @@ -262,7 +262,7 @@ You can read more about it in the Why do my services take 10 seconds to recreate or stop?. -#### Directory Structure +#### Directory Structure { #directory-structure } You should now have a directory structure like: @@ -275,7 +275,7 @@ You should now have a directory structure like: └── requirements.txt ``` -#### Behind a TLS Termination Proxy +#### Behind a TLS Termination Proxy { #behind-a-tls-termination-proxy } If you are running your container behind a TLS Termination Proxy (load balancer) like Nginx or Traefik, add the option `--proxy-headers`, this will tell Uvicorn (through the FastAPI CLI) to trust the headers sent by that proxy telling it that the application is running behind HTTPS, etc. @@ -283,7 +283,7 @@ If you are running your container behind a TLS Termination Proxy (load balancer) CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] ``` -#### Docker Cache +#### Docker Cache { #docker-cache } There's an important trick in this `Dockerfile`, we first copy the **file with the dependencies alone**, not the rest of the code. Let me tell you why is that. @@ -315,7 +315,7 @@ Then, near the end of the `Dockerfile`, we copy all the code. As this is what ** COPY ./app /code/app ``` -### Build the Docker Image +### Build the Docker Image { #build-the-docker-image } Now that all the files are in place, let's build the container image. @@ -340,7 +340,7 @@ In this case, it's the same current directory (`.`). /// -### Start the Docker Container +### Start the Docker Container { #start-the-docker-container } * Run a container based on your image: @@ -352,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage -## Check it +## Check it { #check-it } You should be able to check it in your Docker container's URL, for example: http://192.168.99.100/items/5?q=somequery or http://127.0.0.1/items/5?q=somequery (or equivalent, using your Docker host). @@ -362,7 +362,7 @@ You will see something like: {"item_id": 5, "q": "somequery"} ``` -## Interactive API docs +## Interactive API docs { #interactive-api-docs } Now you can go to http://192.168.99.100/docs or http://127.0.0.1/docs (or equivalent, using your Docker host). @@ -370,7 +370,7 @@ You will see the automatic interactive API documentation (provided by http://192.168.99.100/redoc or http://127.0.0.1/redoc (or equivalent, using your Docker host). @@ -378,7 +378,7 @@ You will see the alternative automatic documentation (provided by cluster of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Uvicorn with workers) in each container. @@ -462,7 +462,7 @@ One of those distributed container management systems like Kubernetes normally h In those cases, you would probably want to build a **Docker image from scratch** as [explained above](#dockerfile), installing your dependencies, and running **a single Uvicorn process** instead of using multiple Uvicorn workers. -### Load Balancer +### Load Balancer { #load-balancer } When using containers, you would normally have some component **listening on the main port**. It could possibly be another container that is also a **TLS Termination Proxy** to handle **HTTPS** or some similar tool. @@ -476,7 +476,7 @@ The same **TLS Termination Proxy** component used for HTTPS would probably also And when working with containers, the same system you use to start and manage them would already have internal tools to transmit the **network communication** (e.g. HTTP requests) from that **load balancer** (that could also be a **TLS Termination Proxy**) to the container(s) with your app. -### One Load Balancer - Multiple Worker Containers +### One Load Balancer - Multiple Worker Containers { #one-load-balancer-multiple-worker-containers } When working with **Kubernetes** or similar distributed container management systems, using their internal networking mechanisms would allow the single **load balancer** that is listening on the main **port** to transmit communication (requests) to possibly **multiple containers** running your app. @@ -486,7 +486,7 @@ And the distributed container system with the **load balancer** would **distribu And normally this **load balancer** would be able to handle requests that go to *other* apps in your cluster (e.g. to a different domain, or under a different URL path prefix), and would transmit that communication to the right containers for *that other* application running in your cluster. -### One Process per Container +### One Process per Container { #one-process-per-container } In this type of scenario, you probably would want to have **a single (Uvicorn) process per container**, as you would already be handling replication at the cluster level. @@ -494,7 +494,7 @@ So, in this case, you **would not** want to have a multiple workers in the conta Having another process manager inside the container (as would be with multiple workers) would only add **unnecessary complexity** that you are most probably already taking care of with your cluster system. -### Containers with Multiple Processes and Special Cases +### Containers with Multiple Processes and Special Cases { #containers-with-multiple-processes-and-special-cases } Of course, there are **special cases** where you could want to have **a container** with several **Uvicorn worker processes** inside. @@ -519,11 +519,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] Here are some examples of when that could make sense: -#### A Simple App +#### A Simple App { #a-simple-app } You could want a process manager in the container if your application is **simple enough** that can run it on a **single server**, not a cluster. -#### Docker Compose +#### Docker Compose { #docker-compose } You could be deploying to a **single server** (not a cluster) with **Docker Compose**, so you wouldn't have an easy way to manage replication of containers (with Docker Compose) while preserving the shared network and **load balancing**. @@ -540,7 +540,7 @@ The main point is, **none** of these are **rules written in stone** that you hav * Memory * Previous steps before starting -## Memory +## Memory { #memory } If you run **a single process per container** you will have a more or less well-defined, stable, and limited amount of memory consumed by each of those containers (more than one if they are replicated). @@ -550,11 +550,11 @@ If your application is **simple**, this will probably **not be a problem**, and If you run **multiple processes per container** you will have to make sure that the number of processes started doesn't **consume more memory** than what is available. -## Previous Steps Before Starting and Containers +## Previous Steps Before Starting and Containers { #previous-steps-before-starting-and-containers } If you are using containers (e.g. Docker, Kubernetes), then there are two main approaches you can use. -### Multiple Containers +### Multiple Containers { #multiple-containers } If you have **multiple containers**, probably each one running a **single process** (for example, in a **Kubernetes** cluster), then you would probably want to have a **separate container** doing the work of the **previous steps** in a single container, running a single process, **before** running the replicated worker containers. @@ -566,11 +566,11 @@ If you are using Kubernetes, this would probably be an tiangolo/uvicorn-gunicorn-fastapi. But it is now deprecated. ⛔️ @@ -588,7 +588,7 @@ But now that Uvicorn (and the `fastapi` command) support using `--workers`, ther /// -## Deploy the Container Image +## Deploy the Container Image { #deploy-the-container-image } After having a Container (Docker) Image there are several ways to deploy it. @@ -600,11 +600,11 @@ For example: * With another tool like Nomad * With a cloud service that takes your container image and deploys it -## Docker Image with `uv` +## Docker Image with `uv` { #docker-image-with-uv } If you are using uv to install and manage your project, you can follow their uv Docker guide. -## Recap +## Recap { #recap } Using container systems (e.g. with **Docker** and **Kubernetes**) it becomes fairly straightforward to handle all the **deployment concepts**: diff --git a/docs/en/docs/deployment/https.md b/docs/en/docs/deployment/https.md index 8b4a08dbe..b52ed40c8 100644 --- a/docs/en/docs/deployment/https.md +++ b/docs/en/docs/deployment/https.md @@ -1,4 +1,4 @@ -# About HTTPS +# About HTTPS { #about-https } It is easy to assume that HTTPS is something that is just "enabled" or not. @@ -43,7 +43,7 @@ Some of the options you could use as a TLS Termination Proxy are: * Nginx * HAProxy -## Let's Encrypt +## Let's Encrypt { #lets-encrypt } Before Let's Encrypt, these **HTTPS certificates** were sold by trusted third parties. @@ -57,11 +57,11 @@ The domains are securely verified and the certificates are generated automatical The idea is to automate the acquisition and renewal of these certificates so that you can have **secure HTTPS, for free, forever**. -## HTTPS for Developers +## HTTPS for Developers { #https-for-developers } Here's an example of how an HTTPS API could look like, step by step, paying attention mainly to the ideas important for developers. -### Domain Name +### Domain Name { #domain-name } It would probably all start by you **acquiring** some **domain name**. Then, you would configure it in a DNS server (possibly your same cloud provider). @@ -77,7 +77,7 @@ This Domain Name part is way before HTTPS, but as everything depends on the doma /// -### DNS +### DNS { #dns } Now let's focus on all the actual HTTPS parts. @@ -87,7 +87,7 @@ The DNS servers would tell the browser to use some specific **IP address**. That -### TLS Handshake Start +### TLS Handshake Start { #tls-handshake-start } The browser would then communicate with that IP address on **port 443** (the HTTPS port). @@ -97,7 +97,7 @@ The first part of the communication is just to establish the connection between This interaction between the client and the server to establish the TLS connection is called the **TLS handshake**. -### TLS with SNI Extension +### TLS with SNI Extension { #tls-with-sni-extension } **Only one process** in the server can be listening on a specific **port** in a specific **IP address**. There could be other processes listening on other ports in the same IP address, but only one for each combination of IP address and port. @@ -127,7 +127,7 @@ Notice that the encryption of the communication happens at the **TCP level**, no /// -### HTTPS Request +### HTTPS Request { #https-request } Now that the client and server (specifically the browser and the TLS Termination Proxy) have an **encrypted TCP connection**, they can start the **HTTP communication**. @@ -135,19 +135,19 @@ So, the client sends an **HTTPS request**. This is just an HTTP request through -### Decrypt the Request +### Decrypt the Request { #decrypt-the-request } The TLS Termination Proxy would use the encryption agreed to **decrypt the request**, and would transmit the **plain (decrypted) HTTP request** to the process running the application (for example a process with Uvicorn running the FastAPI application). -### HTTP Response +### HTTP Response { #http-response } The application would process the request and send a **plain (unencrypted) HTTP response** to the TLS Termination Proxy. -### HTTPS Response +### HTTPS Response { #https-response } The TLS Termination Proxy would then **encrypt the response** using the cryptography agreed before (that started with the certificate for `someapp.example.com`), and send it back to the browser. @@ -157,7 +157,7 @@ Next, the browser would verify that the response is valid and encrypted with the The client (browser) will know that the response comes from the correct server because it is using the cryptography they agreed using the **HTTPS certificate** before. -### Multiple Applications +### Multiple Applications { #multiple-applications } In the same server (or servers), there could be **multiple applications**, for example, other API programs or a database. @@ -167,7 +167,7 @@ Only one process can be handling the specific IP and port (the TLS Termination P That way, the TLS Termination Proxy could handle HTTPS and certificates for **multiple domains**, for multiple applications, and then transmit the requests to the right application in each case. -### Certificate Renewal +### Certificate Renewal { #certificate-renewal } At some point in the future, each certificate would **expire** (about 3 months after acquiring it). @@ -190,7 +190,7 @@ To do that, and to accommodate different application needs, there are several wa All this renewal process, while still serving the app, is one of the main reasons why you would want to have a **separate system to handle HTTPS** with a TLS Termination Proxy instead of just using the TLS certificates with the application server directly (e.g. Uvicorn). -## Recap +## Recap { #recap } Having **HTTPS** is very important, and quite **critical** in most cases. Most of the effort you as a developer have to put around HTTPS is just about **understanding these concepts** and how they work. diff --git a/docs/en/docs/deployment/index.md b/docs/en/docs/deployment/index.md index b43bd050a..2364791a7 100644 --- a/docs/en/docs/deployment/index.md +++ b/docs/en/docs/deployment/index.md @@ -1,8 +1,8 @@ -# Deployment +# Deployment { #deployment } Deploying a **FastAPI** application is relatively easy. -## What Does Deployment Mean +## What Does Deployment Mean { #what-does-deployment-mean } To **deploy** an application means to perform the necessary steps to make it **available to the users**. @@ -10,7 +10,7 @@ For a **web API**, it normally involves putting it in a **remote machine**, with This is in contrast to the **development** stages, where you are constantly changing the code, breaking it and fixing it, stopping and restarting the development server, etc. -## Deployment Strategies +## Deployment Strategies { #deployment-strategies } There are several ways to do it depending on your specific use case and the tools that you use. diff --git a/docs/en/docs/deployment/manually.md b/docs/en/docs/deployment/manually.md index 19ba98075..8bb3945bc 100644 --- a/docs/en/docs/deployment/manually.md +++ b/docs/en/docs/deployment/manually.md @@ -1,6 +1,6 @@ -# Run a Server Manually +# Run a Server Manually { #run-a-server-manually } -## Use the `fastapi run` Command +## Use the `fastapi run` Command { #use-the-fastapi-run-command } In short, use `fastapi run` to serve your FastAPI application: @@ -42,7 +42,7 @@ That would work for most of the cases. 😎 You could use that command for example to start your **FastAPI** app in a container, in a server, etc. -## ASGI Servers +## ASGI Servers { #asgi-servers } Let's go a little deeper into the details. @@ -58,7 +58,7 @@ There are several alternatives, including: * Granian: A Rust HTTP server for Python applications. * NGINX Unit: NGINX Unit is a lightweight and versatile web application runtime. -## Server Machine and Server Program +## Server Machine and Server Program { #server-machine-and-server-program } There's a small detail about names to keep in mind. 💡 @@ -68,7 +68,7 @@ Just keep in mind that when you read "server" in general, it could refer to one When referring to the remote machine, it's common to call it **server**, but also **machine**, **VM** (virtual machine), **node**. Those all refer to some type of remote machine, normally running Linux, where you run programs. -## Install the Server Program +## Install the Server Program { #install-the-server-program } When you install FastAPI, it comes with a production server, Uvicorn, and you can start it with the `fastapi run` command. @@ -100,7 +100,7 @@ When you install FastAPI with something like `pip install "fastapi[standard]"` y /// -## Run the Server Program +## Run the Server Program { #run-the-server-program } If you installed an ASGI server manually, you would normally need to pass an import string in a special format for it to import your FastAPI application: @@ -141,7 +141,7 @@ It helps a lot during **development**, but you **shouldn't** use it in **product /// -## Deployment Concepts +## Deployment Concepts { #deployment-concepts } These examples run the server program (e.g Uvicorn), starting **a single process**, listening on all the IPs (`0.0.0.0`) on a predefined port (e.g. `80`). diff --git a/docs/en/docs/deployment/server-workers.md b/docs/en/docs/deployment/server-workers.md index 5d6b0d00a..0351e8b5e 100644 --- a/docs/en/docs/deployment/server-workers.md +++ b/docs/en/docs/deployment/server-workers.md @@ -1,4 +1,4 @@ -# Server Workers - Uvicorn with Workers +# Server Workers - Uvicorn with Workers { #server-workers-uvicorn-with-workers } Let's check back those deployment concepts from before: @@ -25,7 +25,7 @@ In particular, when running on **Kubernetes** you will probably **not** want to /// -## Multiple Workers +## Multiple Workers { #multiple-workers } You can start multiple workers with the `--workers` command line option: @@ -111,7 +111,7 @@ The only new option here is `--workers` telling Uvicorn to start 4 worker proces You can also see that it shows the **PID** of each process, `27365` for the parent process (this is the **process manager**) and one for each worker process: `27368`, `27369`, `27370`, and `27367`. -## Deployment Concepts +## Deployment Concepts { #deployment-concepts } Here you saw how to use multiple **workers** to **parallelize** the execution of the application, take advantage of **multiple cores** in the CPU, and be able to serve **more requests**. @@ -124,13 +124,13 @@ From the list of deployment concepts from above, using workers would mainly help * **Memory** * **Previous steps before starting** -## Containers and Docker +## Containers and Docker { #containers-and-docker } In the next chapter about [FastAPI in Containers - Docker](docker.md){.internal-link target=_blank} I'll explain some strategies you could use to handle the other **deployment concepts**. I'll show you how to **build your own image from scratch** to run a single Uvicorn process. It is a simple process and is probably what you would want to do when using a distributed container management system like **Kubernetes**. -## Recap +## Recap { #recap } You can use multiple worker processes with the `--workers` CLI option with the `fastapi` or `uvicorn` commands to take advantage of **multi-core CPUs**, to run **multiple processes in parallel**. diff --git a/docs/en/docs/deployment/versions.md b/docs/en/docs/deployment/versions.md index 23f49cf99..15b449184 100644 --- a/docs/en/docs/deployment/versions.md +++ b/docs/en/docs/deployment/versions.md @@ -1,4 +1,4 @@ -# About FastAPI versions +# About FastAPI versions { #about-fastapi-versions } **FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly. @@ -8,7 +8,7 @@ That's why the current versions are still `0.x.x`, this reflects that each versi You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code. -## Pin your `fastapi` version +## Pin your `fastapi` version { #pin-your-fastapi-version } The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application. @@ -32,11 +32,11 @@ that would mean that you would use the versions `0.112.0` or above, but less tha If you use any other tool to manage your installations, like `uv`, Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages. -## Available versions +## Available versions { #available-versions } You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](../release-notes.md){.internal-link target=_blank}. -## About versions +## About versions { #about-versions } Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes. @@ -62,7 +62,7 @@ The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR vers /// -## Upgrading the FastAPI versions +## Upgrading the FastAPI versions { #upgrading-the-fastapi-versions } You should add tests for your app. @@ -72,7 +72,7 @@ After you have tests, then you can upgrade the **FastAPI** version to a more rec If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version. -## About Starlette +## About Starlette { #about-starlette } You shouldn't pin the version of `starlette`. @@ -80,7 +80,7 @@ Different versions of **FastAPI** will use a specific newer version of Starlette So, you can just let **FastAPI** use the correct Starlette version. -## About Pydantic +## About Pydantic { #about-pydantic } Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI. diff --git a/docs/en/docs/environment-variables.md b/docs/en/docs/environment-variables.md index 43dd06add..1dbd93570 100644 --- a/docs/en/docs/environment-variables.md +++ b/docs/en/docs/environment-variables.md @@ -1,4 +1,4 @@ -# Environment Variables +# Environment Variables { #environment-variables } /// tip @@ -10,7 +10,7 @@ An environment variable (also known as "**env var**") is a variable that lives * Environment variables could be useful for handling application **settings**, as part of the **installation** of Python, etc. -## Create and Use Env Vars +## Create and Use Env Vars { #create-and-use-env-vars } You can **create** and use environment variables in the **shell (terminal)**, without needing Python: @@ -50,7 +50,7 @@ Hello Wade Wilson //// -## Read env vars in Python +## Read env vars in Python { #read-env-vars-in-python } You could also create environment variables **outside** of Python, in the terminal (or with any other method), and then **read them in Python**. @@ -157,7 +157,7 @@ You can read more about it at Uvicorn, a high-performance, production-ready, ASGI server. 😎 -## `fastapi dev` +## `fastapi dev` { #fastapi-dev } Running `fastapi dev` initiates development mode. By default, **auto-reload** is enabled, automatically reloading the server when you make changes to your code. This is resource-intensive and could be less stable than when it's disabled. You should only use it for development. It also listens on the IP address `127.0.0.1`, which is the IP for your machine to communicate with itself alone (`localhost`). -## `fastapi run` +## `fastapi run` { #fastapi-run } Executing `fastapi run` starts FastAPI in production mode by default. diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index 9c38a4bd2..681caac35 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -1,17 +1,17 @@ -# Features +# Features { #features } -## FastAPI features +## FastAPI features { #fastapi-features } **FastAPI** gives you the following: -### Based on open standards +### Based on open standards { #based-on-open-standards } * OpenAPI for API creation, including declarations of path operations, parameters, request bodies, security, etc. * Automatic data model documentation with JSON Schema (as OpenAPI itself is based on JSON Schema). * Designed around these standards, after a meticulous study. Instead of an afterthought layer on top. * This also allows using automatic **client code generation** in many languages. -### Automatic docs +### Automatic docs { #automatic-docs } Interactive API documentation and exploration web user interfaces. As the framework is based on OpenAPI, there are multiple options, 2 included by default. @@ -23,7 +23,7 @@ Interactive API documentation and exploration web user interfaces. As the framew ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### Just Modern Python +### Just Modern Python { #just-modern-python } It's all based on standard **Python type** declarations (thanks to Pydantic). No new syntax to learn. Just standard modern Python. @@ -71,7 +71,7 @@ Pass the keys and values of the `second_user_data` dict directly as key-value ar /// -### Editor support +### Editor support { #editor-support } All the framework was designed to be easy and intuitive to use, all the decisions were tested on multiple editors even before starting development, to ensure the best development experience. @@ -95,13 +95,13 @@ You will get completion in code you might even consider impossible before. As fo No more typing the wrong key names, coming back and forth between docs, or scrolling up and down to find if you finally used `username` or `user_name`. -### Short +### Short { #short } It has sensible **defaults** for everything, with optional configurations everywhere. All the parameters can be fine-tuned to do what you need and to define the API you need. But by default, it all **"just works"**. -### Validation +### Validation { #validation } * Validation for most (or all?) Python **data types**, including: * JSON objects (`dict`). @@ -117,7 +117,7 @@ But by default, it all **"just works"**. All the validation is handled by the well-established and robust **Pydantic**. -### Security and authentication +### Security and authentication { #security-and-authentication } Security and authentication integrated. Without any compromise with databases or data models. @@ -134,7 +134,7 @@ Plus all the security features from Starlette (including **session cookies**). All built as reusable tools and components that are easy to integrate with your systems, data stores, relational and NoSQL databases, etc. -### Dependency Injection +### Dependency Injection { #dependency-injection } FastAPI includes an extremely easy to use, but extremely powerful Dependency Injection system. @@ -145,19 +145,19 @@ FastAPI includes an extremely easy to use, but extremely powerful Pydantic. So, any additional Pydantic code you have, will also work. diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index 35d2e7b84..0b9ac4f0b 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -1,4 +1,4 @@ -# Help FastAPI - Get Help +# Help FastAPI - Get Help { #help-fastapi-get-help } Do you like **FastAPI**? @@ -10,7 +10,7 @@ There are very simple ways to help (several involve just one or two clicks). And there are several ways to get help too. -## Subscribe to the newsletter +## Subscribe to the newsletter { #subscribe-to-the-newsletter } You can subscribe to the (infrequent) [**FastAPI and friends** newsletter](newsletter.md){.internal-link target=_blank} to stay updated about: @@ -20,17 +20,17 @@ You can subscribe to the (infrequent) [**FastAPI and friends** newsletter](newsl * Breaking changes 🚨 * Tips and tricks ✅ -## Follow FastAPI on Twitter +## Follow FastAPI on Twitter { #follow-fastapi-on-twitter } Follow @fastapi on **Twitter** to get the latest news about **FastAPI**. 🐦 -## Star **FastAPI** in GitHub +## Star **FastAPI** in GitHub { #star-fastapi-in-github } You can "star" FastAPI in GitHub (clicking the star button at the top right): https://github.com/fastapi/fastapi. ⭐️ By adding a star, other users will be able to find it more easily and see that it has been already useful for others. -## Watch the GitHub repository for releases +## Watch the GitHub repository for releases { #watch-the-github-repository-for-releases } You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): https://github.com/fastapi/fastapi. 👀 @@ -38,7 +38,7 @@ There you can select "Releases only". By doing it, you will receive notifications (in your email) whenever there's a new release (a new version) of **FastAPI** with bug fixes and new features. -## Connect with the author +## Connect with the author { #connect-with-the-author } You can connect with me (Sebastián Ramírez / `tiangolo`), the author. @@ -57,19 +57,19 @@ You can: * Read other ideas, articles, and read about tools I have created. * Follow me to read when I publish something new. -## Tweet about **FastAPI** +## Tweet about **FastAPI** { #tweet-about-fastapi } Tweet about **FastAPI** and let me and others know why you like it. 🎉 I love to hear about how **FastAPI** is being used, what you have liked in it, in which project/company are you using it, etc. -## Vote for FastAPI +## Vote for FastAPI { #vote-for-fastapi } * Vote for **FastAPI** in Slant. * Vote for **FastAPI** in AlternativeTo. * Say you use **FastAPI** on StackShare. -## Help others with questions in GitHub +## Help others with questions in GitHub { #help-others-with-questions-in-github } You can try and help others with their questions in: @@ -88,7 +88,7 @@ The idea is for the **FastAPI** community to be kind and welcoming. At the same Here's how to help others with questions (in discussions or issues): -### Understand the question +### Understand the question { #understand-the-question } * Check if you can understand what is the **purpose** and use case of the person asking. @@ -98,7 +98,7 @@ Here's how to help others with questions (in discussions or issues): * If you can't understand the question, ask for more **details**. -### Reproduce the problem +### Reproduce the problem { #reproduce-the-problem } For most of the cases and most of the questions there's something related to the person's **original code**. @@ -108,13 +108,13 @@ In many cases they will only copy a fragment of the code, but that's not enough * If you are feeling too generous, you can try to **create an example** like that yourself, just based on the description of the problem. Just keep in mind that this might take a lot of time and it might be better to ask them to clarify the problem first. -### Suggest solutions +### Suggest solutions { #suggest-solutions } * After being able to understand the question, you can give them a possible **answer**. * In many cases, it's better to understand their **underlying problem or use case**, because there might be a better way to solve it than what they are trying to do. -### Ask to close +### Ask to close { #ask-to-close } If they reply, there's a high chance you would have solved their problem, congrats, **you're a hero**! 🦸 @@ -123,7 +123,7 @@ If they reply, there's a high chance you would have solved their problem, congra * In GitHub Discussions: mark the comment as the **answer**. * In GitHub Issues: **close** the issue. -## Watch the GitHub repository +## Watch the GitHub repository { #watch-the-github-repository } You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): https://github.com/fastapi/fastapi. 👀 @@ -131,7 +131,7 @@ If you select "Watching" instead of "Releases only" you will receive notificatio Then you can try and help them solve those questions. -## Ask Questions +## Ask Questions { #ask-questions } You can create a new question in the GitHub repository, for example to: @@ -140,7 +140,7 @@ You can Discord chat server 👥 and hang out with others in the FastAPI community. @@ -237,7 +237,7 @@ Use the chat only for other general conversations. /// -### Don't use the chat for questions +### Don't use the chat for questions { #dont-use-the-chat-for-questions } Keep in mind that as chats allow more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers. @@ -247,7 +247,7 @@ Conversations in the chat systems are also not as easily searchable as in GitHub On the other side, there are thousands of users in the chat systems, so there's a high chance you'll find someone to talk to there, almost all the time. 😄 -## Sponsor the author +## Sponsor the author { #sponsor-the-author } If your **product/company** depends on or is related to **FastAPI** and you want to reach its users, you can sponsor the author (me) through GitHub sponsors. Depending on the tier, you could get some extra benefits, like a badge in the docs. 🎁 diff --git a/docs/en/docs/history-design-future.md b/docs/en/docs/history-design-future.md index b4a744d64..2182c415c 100644 --- a/docs/en/docs/history-design-future.md +++ b/docs/en/docs/history-design-future.md @@ -1,4 +1,4 @@ -# History, Design and Future +# History, Design and Future { #history-design-and-future } Some time ago, a **FastAPI** user asked: @@ -6,7 +6,7 @@ Some time ago, **Pydantic** for its advantages. @@ -60,11 +60,11 @@ Then I contributed to it, to make it fully compliant with JSON Schema, to suppor During the development, I also contributed to **Starlette**, the other key requirement. -## Development +## Development { #development } By the time I started creating **FastAPI** itself, most of the pieces were already in place, the design was defined, the requirements and tools were ready, and the knowledge about the standards and specifications was clear and fresh. -## Future +## Future { #future } By this point, it's already clear that **FastAPI** with its ideas is being useful for many people. diff --git a/docs/en/docs/how-to/conditional-openapi.md b/docs/en/docs/how-to/conditional-openapi.md index bd6cad9a8..833123e6a 100644 --- a/docs/en/docs/how-to/conditional-openapi.md +++ b/docs/en/docs/how-to/conditional-openapi.md @@ -1,8 +1,8 @@ -# Conditional OpenAPI +# Conditional OpenAPI { #conditional-openapi } If you needed to, you could use settings and environment variables to configure OpenAPI conditionally depending on the environment, and even disable it entirely. -## About security, APIs, and docs +## About security, APIs, and docs { #about-security-apis-and-docs } Hiding your documentation user interfaces in production *shouldn't* be the way to protect your API. @@ -23,7 +23,7 @@ If you want to secure your API, there are several better things you can do, for Nevertheless, you might have a very specific use case where you really need to disable the API docs for some environment (e.g. for production) or depending on configurations from environment variables. -## Conditional OpenAPI from settings and env vars +## Conditional OpenAPI from settings and env vars { #conditional-openapi-from-settings-and-env-vars } You can easily use the same Pydantic settings to configure your generated OpenAPI and the docs UIs. diff --git a/docs/en/docs/how-to/configure-swagger-ui.md b/docs/en/docs/how-to/configure-swagger-ui.md index a8a8de48f..2d7b99f8f 100644 --- a/docs/en/docs/how-to/configure-swagger-ui.md +++ b/docs/en/docs/how-to/configure-swagger-ui.md @@ -1,4 +1,4 @@ -# Configure Swagger UI +# Configure Swagger UI { #configure-swagger-ui } You can configure some extra Swagger UI parameters. @@ -8,7 +8,7 @@ To configure them, pass the `swagger_ui_parameters` argument when creating the ` FastAPI converts the configurations to **JSON** to make them compatible with JavaScript, as that's what Swagger UI needs. -## Disable Syntax Highlighting +## Disable Syntax Highlighting { #disable-syntax-highlighting } For example, you could disable syntax highlighting in Swagger UI. @@ -24,7 +24,7 @@ But you can disable it by setting `syntaxHighlight` to `False`: -## Change the Theme +## Change the Theme { #change-the-theme } The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle): @@ -34,7 +34,7 @@ That configuration would change the syntax highlighting color theme: -## Change Default Swagger UI Parameters +## Change Default Swagger UI Parameters { #change-default-swagger-ui-parameters } FastAPI includes some default configuration parameters appropriate for most of the use cases. @@ -48,11 +48,11 @@ For example, to disable `deepLinking` you could pass these settings to `swagger_ {* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *} -## Other Swagger UI Parameters +## Other Swagger UI Parameters { #other-swagger-ui-parameters } To see all the other possible configurations you can use, read the official docs for Swagger UI parameters. -## JavaScript-only settings +## JavaScript-only settings { #javascript-only-settings } Swagger UI also allows other configurations to be **JavaScript-only** objects (for example, JavaScript functions). diff --git a/docs/en/docs/how-to/custom-docs-ui-assets.md b/docs/en/docs/how-to/custom-docs-ui-assets.md index 9d2238e4f..b38c4ec02 100644 --- a/docs/en/docs/how-to/custom-docs-ui-assets.md +++ b/docs/en/docs/how-to/custom-docs-ui-assets.md @@ -1,4 +1,4 @@ -# Custom Docs UI Static Assets (Self-Hosting) +# Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } The API docs use **Swagger UI** and **ReDoc**, and each of those need some JavaScript and CSS files. @@ -6,13 +6,13 @@ By default, those files are served from a CDN, for example you want to use `https://unpkg.com/`. This could be useful if for example you live in a country that restricts some URLs. -### Disable the automatic docs +### Disable the automatic docs { #disable-the-automatic-docs } The first step is to disable the automatic docs, as by default, those use the default CDN. @@ -20,7 +20,7 @@ To disable them, set their URLs to `None` when creating your `FastAPI` app: {* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *} -### Include the custom docs +### Include the custom docs { #include-the-custom-docs } Now you can create the *path operations* for the custom docs. @@ -46,23 +46,23 @@ Swagger UI will handle it behind the scenes for you, but it needs this "redirect /// -### Create a *path operation* to test it +### Create a *path operation* to test it { #create-a-path-operation-to-test-it } Now, to be able to test that everything works, create a *path operation*: {* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} -### Test it +### Test it { #test-it } Now, you should be able to go to your docs at http://127.0.0.1:8000/docs, and reload the page, it will load those assets from the new CDN. -## Self-hosting JavaScript and CSS for docs +## Self-hosting JavaScript and CSS for docs { #self-hosting-javascript-and-css-for-docs } Self-hosting the JavaScript and CSS could be useful if, for example, you need your app to keep working even while offline, without open Internet access, or in a local network. Here you'll see how to serve those files yourself, in the same FastAPI app, and configure the docs to use them. -### Project file structure +### Project file structure { #project-file-structure } Let's say your project file structure looks like this: @@ -85,7 +85,7 @@ Your new file structure could look like this: └── static/ ``` -### Download the files +### Download the files { #download-the-files } Download the static files needed for the docs and put them on that `static/` directory. @@ -113,14 +113,14 @@ After that, your file structure could look like: └── swagger-ui.css ``` -### Serve the static files +### Serve the static files { #serve-the-static-files } * Import `StaticFiles`. * "Mount" a `StaticFiles()` instance in a specific path. {* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *} -### Test the static files +### Test the static files { #test-the-static-files } Start your application and go to http://127.0.0.1:8000/static/redoc.standalone.js. @@ -138,7 +138,7 @@ That confirms that you are being able to serve static files from your app, and t Now we can configure the app to use those static files for the docs. -### Disable the automatic docs for static files +### Disable the automatic docs for static files { #disable-the-automatic-docs-for-static-files } The same as when using a custom CDN, the first step is to disable the automatic docs, as those use the CDN by default. @@ -146,7 +146,7 @@ To disable them, set their URLs to `None` when creating your `FastAPI` app: {* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *} -### Include the custom docs for static files +### Include the custom docs for static files { #include-the-custom-docs-for-static-files } And the same way as with a custom CDN, now you can create the *path operations* for the custom docs. @@ -172,13 +172,13 @@ Swagger UI will handle it behind the scenes for you, but it needs this "redirect /// -### Create a *path operation* to test static files +### Create a *path operation* to test static files { #create-a-path-operation-to-test-static-files } Now, to be able to test that everything works, create a *path operation*: {* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} -### Test Static Files UI +### Test Static Files UI { #test-static-files-ui } Now, you should be able to disconnect your WiFi, go to your docs at http://127.0.0.1:8000/docs, and reload the page. diff --git a/docs/en/docs/how-to/custom-request-and-route.md b/docs/en/docs/how-to/custom-request-and-route.md index 9b4160d75..6df24a080 100644 --- a/docs/en/docs/how-to/custom-request-and-route.md +++ b/docs/en/docs/how-to/custom-request-and-route.md @@ -1,4 +1,4 @@ -# Custom Request and APIRoute class +# Custom Request and APIRoute class { #custom-request-and-apiroute-class } In some cases, you may want to override the logic used by the `Request` and `APIRoute` classes. @@ -14,7 +14,7 @@ If you are just starting with **FastAPI** you might want to skip this section. /// -## Use cases +## Use cases { #use-cases } Some use cases include: @@ -22,13 +22,13 @@ Some use cases include: * Decompressing gzip-compressed request bodies. * Automatically logging all request bodies. -## Handling custom request body encodings +## Handling custom request body encodings { #handling-custom-request-body-encodings } Let's see how to make use of a custom `Request` subclass to decompress gzip requests. And an `APIRoute` subclass to use that custom request class. -### Create a custom `GzipRequest` class +### Create a custom `GzipRequest` class { #create-a-custom-gziprequest-class } /// tip @@ -44,7 +44,7 @@ That way, the same route class can handle gzip compressed or uncompressed reques {* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *} -### Create a custom `GzipRoute` class +### Create a custom `GzipRoute` class { #create-a-custom-gziproute-class } Next, we create a custom subclass of `fastapi.routing.APIRoute` that will make use of the `GzipRequest`. @@ -78,7 +78,7 @@ After that, all of the processing logic is the same. But because of our changes in `GzipRequest.body`, the request body will be automatically decompressed when it is loaded by **FastAPI** when needed. -## Accessing the request body in an exception handler +## Accessing the request body in an exception handler { #accessing-the-request-body-in-an-exception-handler } /// tip @@ -98,7 +98,7 @@ If an exception occurs, the`Request` instance will still be in scope, so we can {* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *} -## Custom `APIRoute` class in a router +## Custom `APIRoute` class in a router { #custom-apiroute-class-in-a-router } You can also set the `route_class` parameter of an `APIRouter`: diff --git a/docs/en/docs/how-to/extending-openapi.md b/docs/en/docs/how-to/extending-openapi.md index 26c742c20..5e672665e 100644 --- a/docs/en/docs/how-to/extending-openapi.md +++ b/docs/en/docs/how-to/extending-openapi.md @@ -1,10 +1,10 @@ -# Extending OpenAPI +# Extending OpenAPI { #extending-openapi } There are some cases where you might need to modify the generated OpenAPI schema. In this section you will see how. -## The normal process +## The normal process { #the-normal-process } The normal (default) process, is as follows. @@ -33,31 +33,31 @@ The parameter `summary` is available in OpenAPI 3.1.0 and above, supported by Fa /// -## Overriding the defaults +## Overriding the defaults { #overriding-the-defaults } Using the information above, you can use the same utility function to generate the OpenAPI schema and override each part that you need. For example, let's add ReDoc's OpenAPI extension to include a custom logo. -### Normal **FastAPI** +### Normal **FastAPI** { #normal-fastapi } First, write all your **FastAPI** application as normally: {* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *} -### Generate the OpenAPI schema +### Generate the OpenAPI schema { #generate-the-openapi-schema } Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function: {* ../../docs_src/extending_openapi/tutorial001.py hl[2,15:21] *} -### Modify the OpenAPI schema +### Modify the OpenAPI schema { #modify-the-openapi-schema } Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema: {* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *} -### Cache the OpenAPI schema +### Cache the OpenAPI schema { #cache-the-openapi-schema } You can use the property `.openapi_schema` as a "cache", to store your generated schema. @@ -67,13 +67,13 @@ It will be generated only once, and then the same cached schema will be used for {* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *} -### Override the method +### Override the method { #override-the-method } Now you can replace the `.openapi()` method with your new function. {* ../../docs_src/extending_openapi/tutorial001.py hl[29] *} -### Check it +### Check it { #check-it } Once you go to http://127.0.0.1:8000/redoc you will see that you are using your custom logo (in this example, **FastAPI**'s logo): diff --git a/docs/en/docs/how-to/general.md b/docs/en/docs/how-to/general.md index 04367c6b7..934719260 100644 --- a/docs/en/docs/how-to/general.md +++ b/docs/en/docs/how-to/general.md @@ -1,39 +1,39 @@ -# General - How To - Recipes +# General - How To - Recipes { #general-how-to-recipes } Here are several pointers to other places in the docs, for general or frequent questions. -## Filter Data - Security +## Filter Data - Security { #filter-data-security } To ensure that you don't return more data than you should, read the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md){.internal-link target=_blank}. -## Documentation Tags - OpenAPI +## Documentation Tags - OpenAPI { #documentation-tags-openapi } To add tags to your *path operations*, and group them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. -## Documentation Summary and Description - OpenAPI +## Documentation Summary and Description - OpenAPI { #documentation-summary-and-description-openapi } To add a summary and description to your *path operations*, and show them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}. -## Documentation Response description - OpenAPI +## Documentation Response description - OpenAPI { #documentation-response-description-openapi } To define the description of the response, shown in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}. -## Documentation Deprecate a *Path Operation* - OpenAPI +## Documentation Deprecate a *Path Operation* - OpenAPI { #documentation-deprecate-a-path-operation-openapi } To deprecate a *path operation*, and show it in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}. -## Convert any Data to JSON-compatible +## Convert any Data to JSON-compatible { #convert-any-data-to-json-compatible } To convert any data to JSON-compatible, read the docs for [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}. -## OpenAPI Metadata - Docs +## OpenAPI Metadata - Docs { #openapi-metadata-docs } To add metadata to your OpenAPI schema, including a license, version, contact, etc, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md){.internal-link target=_blank}. -## OpenAPI Custom URL +## OpenAPI Custom URL { #openapi-custom-url } To customize the OpenAPI URL (or remove it), read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. -## OpenAPI Docs URLs +## OpenAPI Docs URLs { #openapi-docs-urls } To update the URLs used for the automatically generated docs user interfaces, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. diff --git a/docs/en/docs/how-to/graphql.md b/docs/en/docs/how-to/graphql.md index 361010736..99b024d39 100644 --- a/docs/en/docs/how-to/graphql.md +++ b/docs/en/docs/how-to/graphql.md @@ -1,4 +1,4 @@ -# GraphQL +# GraphQL { #graphql } As **FastAPI** is based on the **ASGI** standard, it's very easy to integrate any **GraphQL** library also compatible with ASGI. @@ -14,7 +14,7 @@ Make sure you evaluate if the **benefits** for your use case compensate the **dr /// -## GraphQL Libraries +## GraphQL Libraries { #graphql-libraries } Here are some of the **GraphQL** libraries that have **ASGI** support. You could use them with **FastAPI**: @@ -27,7 +27,7 @@ Here are some of the **GraphQL** libraries that have **ASGI** support. You could * Graphene * With starlette-graphene3 -## GraphQL with Strawberry +## GraphQL with Strawberry { #graphql-with-strawberry } If you need or want to work with **GraphQL**, **Strawberry** is the **recommended** library as it has the design closest to **FastAPI's** design, it's all based on **type annotations**. @@ -41,7 +41,7 @@ You can learn more about Strawberry in the Strawberry with FastAPI. -## Older `GraphQLApp` from Starlette +## Older `GraphQLApp` from Starlette { #older-graphqlapp-from-starlette } Previous versions of Starlette included a `GraphQLApp` class to integrate with Graphene. @@ -53,7 +53,7 @@ If you need GraphQL, I still would recommend you check out official GraphQL documentation. diff --git a/docs/en/docs/how-to/index.md b/docs/en/docs/how-to/index.md index 730dce5d5..5a8ce08de 100644 --- a/docs/en/docs/how-to/index.md +++ b/docs/en/docs/how-to/index.md @@ -1,4 +1,4 @@ -# How To - Recipes +# How To - Recipes { #how-to-recipes } Here you will see different recipes or "how to" guides for **several topics**. diff --git a/docs/en/docs/how-to/separate-openapi-schemas.md b/docs/en/docs/how-to/separate-openapi-schemas.md index 9a27638fe..3c78a56d3 100644 --- a/docs/en/docs/how-to/separate-openapi-schemas.md +++ b/docs/en/docs/how-to/separate-openapi-schemas.md @@ -1,4 +1,4 @@ -# Separate OpenAPI Schemas for Input and Output or Not +# Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not } When using **Pydantic v2**, the generated OpenAPI is a bit more exact and **correct** than before. 😎 @@ -6,13 +6,13 @@ In fact, in some cases, it will even have **two JSON Schemas** in OpenAPI for th Let's see how that works and how to change it if you need to do that. -## Pydantic Models for Input and Output +## Pydantic Models for Input and Output { #pydantic-models-for-input-and-output } Let's say you have a Pydantic model with default values, like this one: {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} -### Model for Input +### Model for Input { #model-for-input } If you use this model as an input like here: @@ -20,7 +20,7 @@ If you use this model as an input like here: ...then the `description` field will **not be required**. Because it has a default value of `None`. -### Input Model in Docs +### Input Model in Docs { #input-model-in-docs } You can confirm that in the docs, the `description` field doesn't have a **red asterisk**, it's not marked as required: @@ -28,7 +28,7 @@ You can confirm that in the docs, the `description` field doesn't have a **red a -### Model for Output +### Model for Output { #model-for-output } But if you use the same model as an output, like here: @@ -36,7 +36,7 @@ But if you use the same model as an output, like here: ...then because `description` has a default value, if you **don't return anything** for that field, it will still have that **default value**. -### Model for Output Response Data +### Model for Output Response Data { #model-for-output-response-data } If you interact with the docs and check the response, even though the code didn't add anything in one of the `description` fields, the JSON response contains the default value (`null`): @@ -55,7 +55,7 @@ Because of that, the JSON Schema for a model can be different depending on if it * for **input** the `description` will **not be required** * for **output** it will be **required** (and possibly `None`, or in JSON terms, `null`) -### Model for Output in Docs +### Model for Output in Docs { #model-for-output-in-docs } You can check the output model in the docs too, **both** `name` and `description` are marked as **required** with a **red asterisk**: @@ -63,7 +63,7 @@ You can check the output model in the docs too, **both** `name` and `description -### Model for Input and Output in Docs +### Model for Input and Output in Docs { #model-for-input-and-output-in-docs } And if you check all the available Schemas (JSON Schemas) in OpenAPI, you will see that there are two, one `Item-Input` and one `Item-Output`. @@ -77,7 +77,7 @@ But for `Item-Output`, `description` is **required**, it has a red asterisk. With this feature from **Pydantic v2**, your API documentation is more **precise**, and if you have autogenerated clients and SDKs, they will be more precise too, with a better **developer experience** and consistency. 🎉 -## Do not Separate Schemas +## Do not Separate Schemas { #do-not-separate-schemas } Now, there are some cases where you might want to have the **same schema for input and output**. @@ -93,7 +93,7 @@ Support for `separate_input_output_schemas` was added in FastAPI `0.102.0`. 🤓 {* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} -### Same Schema for Input and Output Models in Docs +### Same Schema for Input and Output Models in Docs { #same-schema-for-input-and-output-models-in-docs } And now there will be one single schema for input and output for the model, only `Item`, and it will have `description` as **not required**: diff --git a/docs/en/docs/how-to/testing-database.md b/docs/en/docs/how-to/testing-database.md index d0ed15bca..400fdcfc6 100644 --- a/docs/en/docs/how-to/testing-database.md +++ b/docs/en/docs/how-to/testing-database.md @@ -1,4 +1,4 @@ -# Testing a Database +# Testing a Database { #testing-a-database } You can study about databases, SQL, and SQLModel in the SQLModel docs. 🤓 diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 938882d7d..db22ea0f9 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -1,4 +1,4 @@ -# FastAPI +# FastAPI { #fastapi } \n\n", content) match_start = re.search(r"", content) match_end = re.search(r"", content) From ee46b851bc9ab472de6232c39a4e35fa19c42a52 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 11:44:16 +0000 Subject: [PATCH 392/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index bcebdf98a..2383121a8 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). +### Internal + +* 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). + ## 0.116.2 ### Upgrades From a95e91e46e230db27a75f39639a1f255a8b177ae Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 20 Sep 2025 21:05:51 +0900 Subject: [PATCH 393/455] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20mypy=20to?= =?UTF-8?q?=201.14.1=20(#12970)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem Co-authored-by: svlandeg Co-authored-by: svlandeg --- fastapi/encoders.py | 1 + fastapi/routing.py | 1 + requirements-tests.txt | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 451ea0760..0ad548b94 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -241,6 +241,7 @@ def jsonable_encoder( sqlalchemy_safe=sqlalchemy_safe, ) if dataclasses.is_dataclass(obj): + assert not isinstance(obj, type) obj_dict = dataclasses.asdict(obj) return jsonable_encoder( obj_dict, diff --git a/fastapi/routing.py b/fastapi/routing.py index 54c75a027..5418ad982 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -120,6 +120,7 @@ def _prepare_response_content( for k, v in res.items() } elif dataclasses.is_dataclass(res): + assert not isinstance(res, type) return dataclasses.asdict(res) return res diff --git a/requirements-tests.txt b/requirements-tests.txt index 7c1fd12f7..e87a42162 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -2,7 +2,7 @@ -r requirements-docs-tests.txt pytest >=7.1.3,<9.0.0 coverage[toml] >= 6.5.0,< 8.0 -mypy ==1.8.0 +mypy ==1.14.1 dirty-equals ==0.9.0 sqlmodel==0.0.24 flask >=1.1.2,<4.0.0 From ccfca4cb06148b8ccbb716ec4feafe5fda6bcaa6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 12:06:14 +0000 Subject: [PATCH 394/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2383121a8..99ae4918c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). +### Upgrades + +* ⬆️ Update mypy to 1.14.1. PR [#12970](https://github.com/fastapi/fastapi/pull/12970) by [@tamird](https://github.com/tamird). + ### Internal * 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). From 4c9c3b59426f53dcac8bb30640acd895657655bc Mon Sep 17 00:00:00 2001 From: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Date: Sat, 20 Sep 2025 14:22:04 +0200 Subject: [PATCH 395/455] =?UTF-8?q?=F0=9F=94=A8=20Update=20translations=20?= =?UTF-8?q?script=20(#13968)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nils Lindemann Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- scripts/translate.py | 681 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 646 insertions(+), 35 deletions(-) diff --git a/scripts/translate.py b/scripts/translate.py index 2fdc18ca0..ede101e8f 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -1,8 +1,10 @@ import secrets import subprocess +from collections.abc import Iterable from functools import lru_cache +from os import sep as pathsep from pathlib import Path -from typing import Annotated, Iterable +from typing import Annotated import git import typer @@ -12,7 +14,7 @@ from pydantic_ai import Agent from rich import print non_translated_sections = ( - "reference/", + f"reference{pathsep}", "release-notes.md", "fastapi-people.md", "external-links.md", @@ -24,45 +26,647 @@ non_translated_sections = ( general_prompt = """ -For technical terms in English that don't have a common translation term use the original term in English. +### About literal text in this prompt -If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content. +1) In the following instructions (after I say: `The above rules are in effect now`) the two characters `«` and `»` will be used to surround LITERAL TEXT, which is text or characters you shall interpret literally. The `«` and the `»` are not part of the literal text, they are the meta characters denoting it. -For code snippets or fragments, surrounded by backticks (`), don't translate the content, keep the original in English. For example, `list`, `dict`, keep them as is. +2) Furthermore, text surrounded by `«««` and `»»»` is a BLOCK OF LITERAL TEXT which spans multiple lines. To get its content, dedent all lines of the block until the `«««` and `»»»` are at column zero, then remove the newline (`\n`) after the `«««` and the newline before the `»»»`. The `«««` and the `»»»` are not part of the literal text block, they are the meta characters denoting it. -The content is written in markdown, write the translation in markdown as well. Don't add triple backticks (`) around the generated translation content. +3) If you see backticks or any other quotes inside literal text – inside `«` and `»` – or inside blocks of literal text – inside `«««` and `»»»` – then interpret them as literal characters, do NOT interpret them as meta characters. -When there's an example of code, the console or a terminal, normally surrounded by triple backticks and a keyword like "console" or "bash" (e.g. ```console), do not translate the content, keep the original in English. +The above rules are in effect now. -The original content will be surrounded by triple percentage signs (%) and you should translate it to the target language. Do not include the triple percentage signs in the translation. + +### Definitions of terms used in this prompt + +"backtick" + + The character «`» + Unicode U+0060 (GRAVE ACCENT) + +"single backtick" + + A single backtick – «`» + +"triple backticks" + + Three backticks in a row – «```» + +"neutral double quote" + + The character «"» + Unicode U+0022 (QUOTATION MARK) + +"neutral single quote" + + The character «'» + Unicode U+0027 (APOSTROPHE) + +"English double typographic quotes" + + The characters «“» and «”» + Unicode U+201C (LEFT DOUBLE QUOTATION MARK) and Unicode U+201D (RIGHT DOUBLE QUOTATION MARK) + +"English single typographic quotes" + + The characters «‘» and «’» + Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and Unicode U+2019 (RIGHT SINGLE QUOTATION MARK) + +"code snippet" + + Also called "inline code". Text in a Markdown document which is surrounded by single backticks. A paragraph in a Markdown document can have a more than one code snippet. + + Example: + + ««« + `i am a code snippet` + »»» + + Example: + + ««« + `first code snippet` `second code snippet` `third code snippet` + »»» + +"code block" + + Text in a Markdown document which is surrounded by triple backticks. Spreads multiple lines. + + Example: + + ««« + ``` + Hello + World + ``` + »»» + + Example: + + ««« + ```python + print("hello World") + ``` + »»» + +"HTML element" + + a HTML opening tag – e.g. «
» – and a HTML closing tag – e.g. «
» – surrounding text or other HTML elements. + + +### Your task + +Translate an English text – the original content – to a target language. + +The original content is written in Markdown, write the translation in Markdown as well. + +The original content will be surrounded by triple percentage signs («%%%»). Do not include the triple percentage signs in the translation. + + +### Technical terms in English + +For technical terms in English that don't have a common translation term, use the original term in English. + + +### Content of code snippets + +Do not translate the content of code snippets, keep the original in English. For example, «`list`», «`dict`», keep them as is. + + +### Content of code blocks + +Do not translate the content of code blocks, except for comments in the language which the code block uses. + +Examples: + + Source (English) – The code block is a bash code example with one comment: + + ««« + ```bash + # Print greeting + echo "Hello, World!" + ``` + »»» + + Result (German): + + ««« + ```bash + # Gruß ausgeben + echo "Hello, World!" + ``` + »»» + + Source (English) – The code block is a console example containing HTML tags. No comments, so nothing to change here: + + ««« + ```console + $ fastapi run main.py + FastAPI Starting server + Searching for package file structure + ``` + »»» + + Result (German): + + ««« + ```console + $ fastapi run main.py + FastAPI Starting server + Searching for package file structure + ``` + »»» + + Source (English) – The code block is a console example containing 5 comments: + + ««« + ```console + // Go to the home directory + $ cd + // Create a directory for all your code projects + $ mkdir code + // Enter into that code directory + $ cd code + // Create a directory for this project + $ mkdir awesome-project + // Enter into that project directory + $ cd awesome-project + ``` + »»» + + Result (German): + + ««« + ```console + // Gehe zum Home-Verzeichnis + $ cd + // Erstelle ein Verzeichnis für alle Ihre Code-Projekte + $ mkdir code + // Gehe in dieses Code-Verzeichnis + $ cd code + // Erstelle ein Verzeichnis für dieses Projekt + $ mkdir awesome-project + // Gehe in dieses Projektverzeichnis + $ cd awesome-project + ``` + »»» + +If there is an existing translation and its Mermaid diagram is in sync with the Mermaid diagram in the English source, except a few translated words, then use the Mermaid diagram of the existing translation. The human editor of the translation translated these words in the Mermaid diagram. Keep these translations, do not revert them back to the English source. + +Example: + + Source (English): + + ««« + ```mermaid + flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end + ``` + »»» + + Existing translation (German) – has three translations: + + ««« + ```mermaid + flowchart LR + subgraph global[globale Umgebung] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) -->|benötigt| harry-1 + end + ``` + »»» + + Result (German) – you change nothing: + + ««« + ```mermaid + flowchart LR + subgraph global[globale Umgebung] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) -->|benötigt| harry-1 + end + ``` + »»» + + +### Special blocks There are special blocks of notes, tips and others that look like: -/// note + ««« + /// note + »»» To translate it, keep the same line and add the translation after a vertical bar. For example, if you were translating to Spanish, you would write: -/// note | Nota + ««« + /// note | Nota + »»» Some examples in Spanish: -Source: + Source: -/// tip + ««« + /// tip + »»» -Result: + Result: -/// tip | Consejo + ««« + /// tip | Consejo + »»» -Source: + Source: -/// details | Preview + ««« + /// details | Preview + »»» -Result: + Result: + + ««« + /// details | Vista previa + »»» + + +### Tab blocks + +There are special blocks surrounded by four slashes («////»). They mark text, which will be rendered as part of a tab in the final document. The scheme is: + + //// tab | {tab title} + {tab content, may span many lines} + //// + +Keep everything before the vertical bar («|») as is, including the vertical bar. Translate the tab title. Translate the tab content, applying the rules you know. Keep the four block closing slashes as is. + +Examples: + + Source (English): + + ««« + //// tab | Python 3.8+ non-Annotated + Hello + //// + »»» + + Result (German): + + ««« + //// tab | Python 3.8+ nicht annotiert + Hallo + //// + »»» + + Source (English) – Here there is nothing to translate in the tab title: + + ««« + //// tab | Linux, macOS, Windows Bash + Hello again + //// + »»» + + Result (German): + + ««« + //// tab | Linux, macOS, Windows Bash + Hallo wieder + //// + »»» + + +### Headings + +Every Markdown heading in the English text (all levels) ends with a part inside curly brackets. This part denotes the hash of this heading, which is used in links to this heading. In translations, translate the heading, but do not translate this hash part, so that links do not break. + +Examples of how to translate a heading: + + Source (English): + + ««« + ## Alternative API docs { #alternative-api-docs } + »»» + + Result (Spanish): + + ««« + ## Documentación de la API alternativa { #alternative-api-docs } + »»» + + Source (English): + + ««« + ### Example { #example } + »»» + + Result (German): + + ««« + ### Beispiel { #example } + »»» + + +### Links + +Use the following rules for links (apply both to Markdown-style links ([text](url)) and to HTML-style tags): + +1) For relative URLs, only translate link text. Do not translate the URL or its parts + +Example: + + Source (English): + + ««« + [One of the fastest Python frameworks available](#performance) + »»» + + Result (German): + + ««« + [Eines der schnellsten verfügbaren Python-Frameworks](#performance) + »»» + +2) For absolute URLs which DO NOT start EXACTLY with «https://fastapi.tiangolo.com», only translate link text and leave the URL unchanged. + +Example: + + Source (English): + + ««« + SQLModel docs + »»» + + Result (German): + + ««« + SQLModel-Dokumentation + »»» + +3) For absolute URLs which DO start EXACTLY with «https://fastapi.tiangolo.com», only translate link text and change the URL by adding language code («https://fastapi.tiangolo.com/{language_code}[rest part of the url]»). + +Example: + + Source (English): + + ««« + Documentation + »»» + + Result (Spanish): + + ««« + Documentación + »»» + +3.1) Do not add language codes for URLs that point to static assets (e.g., images, CSS, JavaScript). + +Example: + + Source (English): + + ««« + Something + »»» + + Result (Spanish): + + ««« + Algo + »»» + +4) For internal links, only translate link text. + +Example: + + Source (English): + + ««« + [Create Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank} + »»» + + Result (German): + + ««« + [Pull Requests erzeugen](help-fastapi.md#create-a-pull-request){.internal-link target=_blank} + »»» + +5) Do not translate anchor fragments in links (the part after «#»), as they must remain the same to work correctly. + +5.1) If an existing translation has a link with an anchor fragment different to the anchor fragment in the English source, then this is an error. Fix this by using the anchor fragment of the English source. + +Example: + + Source (English): + + ««« + [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank} + »»» + + Existing wrong translation (German) – notice the wrongly translated anchor fragment: + + ««« + [Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#einzelne-werte-im-body){.internal-link target=_blank}. + »»» + + Result (German) – you fix the anchor fragment: + + ««« + [Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. + »»» + +5.2) Do not add anchor fragments at will, even if this makes sense. If the English source has no anchor, don't add one. + +Example: + + Source (English): + + ««« + Create a [virtual environment](../virtual-environments.md){.internal-link target=_blank} + »»» + + Wrong translation (German) – Anchor added to the URL. + + ««« + Erstelle eine [virtuelle Umgebung](../virtual-environments.md#create-a-virtual-environment){.internal-link target=_blank} + »»» + + Good translation (German) – URL stays like in the English source. + + ««« + Erstelle eine [Virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} + »»» + + +### HTML abbr elements + +Translate HTML abbr elements («text») as follows: + +1) If the text surrounded by the abbr element is an abbreviation (the text may be surrounded by further HTML or Markdown markup or quotes, for example «text» or «`text`» or «"text"», ignore that further markup when deciding if the text is an abbreviation), and if the description (the text inside the title attribute) contains the full phrase for this abbreviation, then append a dash («–») to the full phrase, followed by the translation of the full phrase. + +Conversion scheme: + + Source (English): + + {abbreviation} + + Result: + + {abbreviation} + +Examples: + + Source (English): + + ««« + IoT + CPU + TL;DR: + »»» + + Result (German): + + ««« + IoT + CPU + TL;DR: + »»» + +1.1) If the language to which you translate mostly uses the letters of the ASCII char set (for example Spanish, French, German, but not Russian, Chinese) and if the translation of the full phrase is identical to, or starts with the same letters as the original full phrase, then only give the translation of the full phrase. + +Conversion scheme: + + Source (English): + + {abbreviation} + + Result: + + {abbreviation} + +Examples: + + Source (English): + + ««« + JWT + Enum + ASGI + »»» + + Result (German): + + ««« + JWT + Enum + ASGI + »»» + +2) If the description is not a full phrase for an abbreviation which the abbr element surrounds, but some other information, then just translate the description. + +Conversion scheme: + + Source (English): + + {text} + + Result: + + {translation of text} + +Examples: + + Source (English): + + ««« + path + linter + parsing + 0.95.0 + at the time of writing this + »»» + + Result (German): + + ««« + Pfad + Linter + Parsen + 0.95.0 + zum Zeitpunkt als das hier geschrieben wurde + »»» + + +3) If the text surrounded by the abbr element is an abbreviation and the description contains both the full phrase for that abbreviation, and other information, separated by a colon («:»), then append a dash («–») and the translation of the full phrase to the original full phrase and translate the other information. + +Conversion scheme: + + Source (English): + + {abbreviation} + + Result: + + {abbreviation} + +Examples: + + Source (English): + + ««« + I/O + CDN + IDE + »»» + + Result (German): + + ««« + I/O + CDN + IDE + »»» + +3.1) Like in rule 2.1, you can leave the original full phrase away, if the translated full phrase is identical or starts with the same letters as the original full phrase. + +Conversion scheme: + + Source (English): + + {abbreviation} + + Result: + + {abbreviation} + +Example: + + Source (English): + + ««« + ORM + »»» + + Result (German): + + ««« + ORM + »»» + +4) If there is an existing translation, and it has ADDITIONAL abbr elements in a sentence, and these additional abbr elements do not exist in the related sentence in the English text, then KEEP those additional abbr elements in the translation. Do not remove them. Except when you remove the whole sentence from the translation, because the whole sentence was removed from the English text, then also remove the abbr element. The reasoning for this rule is, that such additional abbr elements are manually added by the human editor of the translation, in order to translate or explain an English word to the human readers of the translation. These additional abbr elements would not make sense in the English text, but they do make sense in the translation. So keep them in the translation, even though they are not part of the English text. This rule only applies to abbr elements. + +5) Apply above rules also when there is an existing translation! Make sure that all title attributes in abbr elements get properly translated or updated, using the schemes given above. However, leave the ADDITIONAL abbr's from rule 4 alone. Do not change their formatting or content. -/// details | Vista previa """ app = typer.Typer() @@ -70,7 +674,7 @@ app = typer.Typer() @lru_cache def get_langs() -> dict[str, str]: - return yaml.safe_load(Path("docs/language_names.yml").read_text()) + return yaml.safe_load(Path("docs/language_names.yml").read_text(encoding="utf-8")) def generate_lang_path(*, lang: str, path: Path) -> Path: @@ -99,13 +703,16 @@ def translate_page( language: Annotated[str, typer.Option(envvar="LANGUAGE")], en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], ) -> None: + assert language != "en", ( + "`en` is the source language, choose another language as translation target" + ) langs = get_langs() language_name = langs[language] lang_path = Path(f"docs/{language}") lang_path.mkdir(exist_ok=True) lang_prompt_path = lang_path / "llm-prompt.md" assert lang_prompt_path.exists(), f"Prompt file not found: {lang_prompt_path}" - lang_prompt_content = lang_prompt_path.read_text() + lang_prompt_content = lang_prompt_path.read_text(encoding="utf-8") en_docs_path = Path("docs/en/docs") assert str(en_path).startswith(str(en_docs_path)), ( @@ -113,13 +720,13 @@ def translate_page( ) out_path = generate_lang_path(lang=language, path=en_path) out_path.parent.mkdir(parents=True, exist_ok=True) - original_content = en_path.read_text() + original_content = en_path.read_text(encoding="utf-8") old_translation: str | None = None if out_path.exists(): print(f"Found existing translation: {out_path}") - old_translation = out_path.read_text() + old_translation = out_path.read_text(encoding="utf-8") print(f"Translating {en_path} to {language} ({language_name})") - agent = Agent("openai:gpt-4o") + agent = Agent("openai:gpt-5") prompt_segments = [ general_prompt, @@ -128,16 +735,19 @@ def translate_page( if old_translation: prompt_segments.extend( [ - "There's an existing previous translation for this content that is probably outdated with old content or old instructions.", + "There is an existing previous translation for the original English content, that may be outdated.", "Update the translation only where necessary:", - "- If the original English content has changed, reflect that in the translation.", + "- If the original English content has added parts, also add these parts to the translation.", + "- If the original English content has removed parts, also remove them from the translation, unless you were instructed earlier to not do that in specific cases.", + "- If parts of the original English content have changed, also change those parts in the translation.", "- If the previous translation violates current instructions, update it.", - "- Otherwise, preserve the original translation **line-by-line** as-is.", + "- Otherwise, preserve the original translation LINE-BY-LINE, AS-IS.", "Do not:", - "- Rephrase or rewrite correct lines just to improve the style.", - "- Add or remove line breaks unless the English source changed.", - "- Change formatting or whitespace unless absolutely required.", - "Only change what must be changed. The goal is to minimize diffs for easier review.", + "- rephrase or rewrite correct lines just to improve the style.", + "- add or remove line breaks, unless the original English content changed.", + "- change formatting or whitespace unless absolutely required.", + "Only change what must be changed. The goal is to minimize diffs for easier human review.", + "UNLESS you were instructed earlier to behave different, there MUST NOT be whole sentences or partial sentences in the updated translation, which are not in the original English content, and there MUST NOT be whole sentences or partial sentences in the original English content, which are not in the updated translation. Remember: the updated translation shall be IN SYNC with the original English content.", "Previous translation:", f"%%%\n{old_translation}%%%", ] @@ -152,9 +762,9 @@ def translate_page( prompt = "\n\n".join(prompt_segments) print(f"Running agent for {out_path}") result = agent.run_sync(prompt) - out_content = f"{result.data.strip()}\n" + out_content = f"{result.output.strip()}\n" print(f"Saving translation to {out_path}") - out_path.write_text(out_content) + out_path.write_text(out_content, encoding="utf-8", newline="\n") def iter_all_en_paths() -> Iterable[Path]: @@ -182,10 +792,11 @@ def iter_all_en_paths() -> Iterable[Path]: def iter_en_paths_to_translate() -> Iterable[Path]: + en_docs_root = Path("docs/en/docs/") for path in iter_all_en_paths(): - if str(path).replace("docs/en/docs/", "").startswith(non_translated_sections): - continue - yield path + relpath = path.relative_to(en_docs_root) + if not str(relpath).startswith(non_translated_sections): + yield path @app.command() From 111431295c9cd6a8ea272658eb5ea6bc9d7f9f77 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 12:22:28 +0000 Subject: [PATCH 396/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 99ae4918c..5f26a01a0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Internal +* 🔨 Update translations script. PR [#13968](https://github.com/fastapi/fastapi/pull/13968) by [@YuriiMotov](https://github.com/YuriiMotov). * 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). ## 0.116.2 From f10ed69b9743a4db06d98b691abd25c8342c7909 Mon Sep 17 00:00:00 2001 From: Nils-Hero Lindemann Date: Sat, 20 Sep 2025 14:55:29 +0200 Subject: [PATCH 397/455] =?UTF-8?q?=E2=9C=85=20Add=20LLM=20test=20file=20(?= =?UTF-8?q?#14049)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/de/docs/_llm-test.md | 503 ++++++++++++++++++++++++++++++++++++++ docs/en/docs/_llm-test.md | 503 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 1006 insertions(+) create mode 100644 docs/de/docs/_llm-test.md create mode 100644 docs/en/docs/_llm-test.md diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md new file mode 100644 index 000000000..4a5e5392c --- /dev/null +++ b/docs/de/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM-Testdatei { #llm-test-file } + +Dieses Dokument testet, ob das LLM, das die Dokumentation übersetzt, den `general_prompt` in `scripts/translate.py` und den sprachspezifischen Prompt in `docs/{language code}/llm-prompt.md` versteht. Der sprachspezifische Prompt wird an `general_prompt` angehängt. + +Hier hinzugefügte Tests werden von allen Erstellern sprachspezifischer Prompts gesehen. + +So verwenden: + +* Einen sprachspezifischen Prompt haben – `docs/{language code}/llm-prompt.md`. +* Eine frische Übersetzung dieses Dokuments in die gewünschte Zielsprache durchführen (siehe z. B. das Kommando `translate-page` der `translate.py`). Dadurch wird die Übersetzung unter `docs/{language code}/docs/_llm-test.md` erstellt. +* Prüfen Sie, ob in der Übersetzung alles in Ordnung ist. +* Verbessern Sie bei Bedarf Ihren sprachsspezifischen Prompt, den allgemeinen Prompt oder das englische Dokument. +* Beheben Sie anschließend manuell die verbleibenden Probleme in der Übersetzung, sodass es eine gute Übersetzung ist. +* Übersetzen Sie erneut, nachdem die gute Übersetzung vorliegt. Das ideale Ergebnis wäre, dass das LLM an der Übersetzung keine Änderungen mehr vornimmt. Das bedeutet, dass der allgemeine Prompt und Ihr sprachsspezifischer Prompt so gut sind, wie sie sein können (Es wird manchmal ein paar scheinbar zufällige Änderungen machen, der Grund ist, dass LLMs keine deterministischen Algorithmen sind). + +Die Tests: + +## Codeschnipsel { #code-snippets} + +//// tab | Test + +Dies ist ein Codeschnipsel: `foo`. Und dies ist ein weiteres Codeschnipsel: `bar`. Und noch eins: `baz quux`. + +//// + +//// tab | Info + +Der Inhalt von Codeschnipseln sollte unverändert bleiben. + +Siehe Abschnitt `### Content of code snippets` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Anführungszeichen { #quotes } + +//// tab | Test + +Gestern schrieb mein Freund: „Wenn man unkorrekt korrekt schreibt, hat man es unkorrekt geschrieben“. Worauf ich antwortete: „Korrekt, aber ‚unkorrekt‘ ist unkorrekterweise nicht ‚„unkorrekt“‘“. + +/// note | Hinweis + +Das LLM wird dies wahrscheinlich falsch übersetzen. Interessant ist nur, ob es die korrigierte Übersetzung bei einer erneuten Übersetzung beibehält. + +/// + +//// + +//// tab | Info + +Der Prompt-Designer kann entscheiden, ob neutrale Anführungszeichen in typografische Anführungszeichen umgewandelt werden sollen. Es ist in Ordnung, sie unverändert zu lassen. + +Siehe zum Beispiel den Abschnitt `### Quotes` in `docs/de/llm-prompt.md`. + +//// + +## Anführungszeichen in Codeschnipseln { #quotes-in-code-snippets} + +//// tab | Test + +`pip install "foo[bar]"` + +Beispiele für Stringliterale in Codeschnipseln: `"this"`, `'that'`. + +Ein schwieriges Beispiel für Stringliterale in Codeschnipseln: `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Info + +... Allerdings müssen Anführungszeichen in Codeschnipseln unverändert bleiben. + +//// + +## Codeblöcke { #code-blocks } + +//// tab | Test + +Ein Bash-Codebeispiel ... + +```bash +# Eine Begrüßung an das Universum ausgeben +echo "Hello universe" +``` + +... und ein Konsolen-Codebeispiel ... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +... und noch ein Konsolen-Codebeispiel ... + +```console +// Ein Verzeichnis „Code“ erstellen +$ mkdir code +// In dieses Verzeichnis wechseln +$ cd code +``` + +... und ein Python-Codebeispiel ... + +```Python +wont_work() # Das wird nicht funktionieren 😱 +works(foo="bar") # Das funktioniert 🎉 +``` + +... und das war's. + +//// + +//// tab | Info + +Code in Codeblöcken sollte nicht verändert werden, mit Ausnahme von Kommentaren. + +Siehe Abschnitt `### Content of code blocks` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Tabs und farbige Boxen { #tabs-and-colored-boxes } + +//// tab | Test + +/// info | Info +Etwas Text +/// + +/// note | Hinweis +Etwas Text +/// + +/// note | Technische Details +Etwas Text +/// + +/// check | Testen +Etwas Text +/// + +/// tip | Tipp +Etwas Text +/// + +/// warning | Achtung +Etwas Text +/// + +/// danger | Gefahr +Etwas Text +/// + +//// + +//// tab | Info + +Tabs und `Info`/`Note`/`Warning`/usw. Blöcke sollten die Übersetzung ihres Titels nach einem vertikalen Strich (`|`) erhalten. + +Siehe die Abschnitte `### Special blocks` und `### Tab blocks` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Web- und interne Links { #web-and-internal-links } + +//// tab | Test + +Der Linktext sollte übersetzt werden, die Linkadresse sollte unverändert bleiben: + +* [Link zur Überschrift oben](#code-snippets) +* [Interner Link](index.md#installation){.internal-link target=_blank} +* Externer Link +* Link zu einem Stil +* Link zu einem Skript +* Link zu einem Bild + +Der Linktext sollte übersetzt werden, die Linkadresse sollte auf die Übersetzung zeigen: + +* FastAPI-Link + +//// + +//// tab | Info + +Links sollten übersetzt werden, aber ihre Adresse soll unverändert bleiben. Eine Ausnahme sind absolute Links zu Seiten der FastAPI-Dokumentation. In diesem Fall sollte auf die Übersetzung verlinkt werden. + +Siehe Abschnitt `### Links` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## HTML „abbr“-Elemente { #html-abbr-elements } + +//// tab | Test + +Hier einige Dinge, die in HTML-„abbr“-Elemente gepackt sind (einige sind erfunden): + +### Das abbr gibt eine vollständige Phrase { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### Das abbr gibt eine Erklärung { #the-abbr-gives-an-explanation } + +* Cluster +* Deep Learning + +### Das abbr gibt eine vollständige Phrase und eine Erklärung { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Info + +„title“-Attribute von „abbr“-Elementen werden nach bestimmten Anweisungen übersetzt. + +Übersetzungen können eigene „abbr“-Elemente hinzufügen, die das LLM nicht entfernen soll. Z. B. um englische Wörter zu erklären. + +Siehe Abschnitt `### HTML abbr elements` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Überschriften { #headings } + +//// tab | Test + +### Eine Webapp entwickeln – ein Tutorial { #develop-a-webapp-a-tutorial } + +Hallo. + +### Typhinweise und -annotationen { #type-hints-and-annotations } + +Hallo wieder. + +### Super- und Subklassen { #super-and-subclasses } + +Hallo wieder. + +//// + +//// tab | Info + +Die einzige strenge Regel für Überschriften ist, dass das LLM den Hash-Teil in geschweiften Klammern unverändert lässt, damit Links nicht kaputtgehen. + +Siehe Abschnitt `### Headings` im allgemeinen Prompt in `scripts/translate.py`. + +Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. + +//// + +## In der Dokumentation verwendete Begriffe { #terms-used-in-the-docs } + +//// tab | Test + +* Sie +* Ihr + +* z. B. +* usw. + +* `foo` vom Typ `int` +* `bar` vom Typ `str` +* `baz` vom Typ `list` + +* das Tutorial – Benutzerhandbuch +* das Handbuch für fortgeschrittene Benutzer +* die SQLModel-Dokumentation +* die API-Dokumentation +* die automatische Dokumentation + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic-Authentifizierung +* HTTP Digest +* ISO-Format +* der JSON-Schema-Standard +* das JSON-Schema +* die Schema-Definition +* Password Flow +* Mobile + +* deprecatet +* designt +* ungültig +* on the fly +* Standard +* Default +* Groß-/Klein­schrei­bung ist relevant +* Groß-/Klein­schrei­bung ist nicht relevant + +* die Anwendung bereitstellen +* die Seite ausliefern + +* die App +* die Anwendung + +* der Request +* die Response +* die Error-Response + +* die Pfadoperation +* der Pfadoperation-Dekorator +* die Pfadoperation-Funktion + +* der Body +* der Requestbody +* der Responsebody +* der JSON-Body +* der Formularbody +* der Dateibody +* der Funktionskörper + +* der Parameter +* der Body-Parameter +* der Pfad-Parameter +* der Query-Parameter +* der Cookie-Parameter +* der Header-Parameter +* der Formular-Parameter +* der Funktionsparameter + +* das Event +* das Startup-Event +* das Hochfahren des Servers +* das Shutdown-Event +* das Lifespan-Event + +* der Handler +* der Eventhandler +* der Exceptionhandler +* handhaben + +* das Modell +* das Pydantic-Modell +* das Datenmodell +* das Datenbankmodell +* das Formularmodell +* das Modellobjekt + +* die Klasse +* die Basisklasse +* die Elternklasse +* die Subklasse +* die Kindklasse +* die Geschwisterklasse +* die Klassenmethode + +* der Header +* die Header +* der Autorisierungsheader +* der `Authorization`-Header +* der Forwarded-Header + +* das Dependency-Injection-System +* die Dependency +* das Dependable +* der Dependant + +* I/O-lastig +* CPU-lastig +* Nebenläufigkeit +* Parallelität +* Multiprocessing + +* die Umgebungsvariable +* die Umgebungsvariable +* der `PATH` +* die `PATH`-Umgebungsvariable + +* die Authentifizierung +* der Authentifizierungsanbieter +* die Autorisierung +* das Anmeldeformular +* der Autorisierungsanbieter +* der Benutzer authentisiert sich +* das System authentifiziert den Benutzer + +* Das CLI +* Das Kommandozeileninterface + +* der Server +* der Client + +* der Cloudanbieter +* der Clouddienst + +* die Entwicklung +* die Entwicklungsphasen + +* das Dict +* das Dictionary +* die Enumeration +* das Enum +* das Enum-Member + +* der Encoder +* der Decoder +* kodieren +* dekodieren + +* die Exception +* werfen + +* der Ausdruck +* die Anweisung + +* das Frontend +* das Backend + +* die GitHub-Diskussion +* das GitHub-Issue + +* die Leistung +* die Leistungsoptimierung + +* der Rückgabetyp +* der Rückgabewert + +* die Sicherheit +* das Sicherheitsschema + +* der Task +* der Hintergrundtask +* die Taskfunktion + +* das Template +* die Template-Engine + +* die Typannotation +* der Typhinweis + +* der Serverworker +* der Uvicorn-Worker +* der Gunicorn-Worker +* der Workerprozess +* die Workerklasse +* die Workload + +* das Deployment +* bereitstellen + +* das SDK +* das Software Development Kit + +* der `APIRouter` +* die `requirements.txt` +* das Bearer-Token +* der Breaking Change +* der Bug +* der Button +* das Callable +* der Code +* der Commit +* der Contextmanager +* die Coroutine +* die Datenbank-Session +* die Festplatte +* die Domain +* die Engine +* das Fake-X +* die HTTP-GET-Methode +* das Item +* die Bibliothek +* der Lifespan +* der Lock +* die Middleware +* die Mobile-Anwendung +* das Modul +* das Mounten +* das Netzwerk +* das Origin +* Die Überschreibung +* die Payload +* der Prozessor +* die Property +* der Proxy +* der Pull Request +* die Query +* der RAM +* der entfernte Rechner +* der Statuscode +* der String +* der Tag +* das Webframework +* die Wildcard +* zurückgeben +* validieren + +//// + +//// tab | Info + +Dies ist eine nicht vollständige und nicht normative Liste von (meist) technischen Begriffen, die in der Dokumentation vorkommen. Sie kann dem Prompt-Designer helfen herauszufinden, bei welchen Begriffen das LLM Unterstützung braucht. Zum Beispiel, wenn es eine gute Übersetzung immer wieder auf eine suboptimale Übersetzung zurücksetzt. Oder wenn es Probleme hat, einen Begriff in Ihrer Sprache zu konjugieren/deklinieren. + +Siehe z. B. den Abschnitt `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. + +//// diff --git a/docs/en/docs/_llm-test.md b/docs/en/docs/_llm-test.md new file mode 100644 index 000000000..e72450b91 --- /dev/null +++ b/docs/en/docs/_llm-test.md @@ -0,0 +1,503 @@ +# LLM test file { #llm-test-file } + +This document tests if the LLM, which translates the documentation, understands the `general_prompt` in `scripts/translate.py` and the language specific prompt in `docs/{language code}/llm-prompt.md`. The language specific prompt is appended to `general_prompt`. + +Tests added here will be seen by all designers of language specific prompts. + +Use as follows: + +* Have a language specific prompt – `docs/{language code}/llm-prompt.md`. +* Do a fresh translation of this document into your desired target language (see e.g. the `translate-page` command of the `translate.py`). This will create the translation under `docs/{language code}/docs/_llm-test.md`. +* Check if things are okay in the translation. +* If necessary, improve your language specific prompt, the general prompt, or the English document. +* Then manually fix the remaining issues in the translation, so that it is a good translation. +* Retranslate, having the good translation in place. The ideal result would be that the LLM makes no changes anymore to the translation. That means that the general prompt and your language specific prompt are as good as they can be (It will sometimes make a few seemingly random changes, the reason is that LLMs are not deterministic algorithms). + +The tests: + +## Code snippets { #code-snippets} + +//// tab | Test + +This is a code snippet: `foo`. And this is another code snippet: `bar`. And another one: `baz quux`. + +//// + +//// tab | Info + +Content of code snippets should be left as is. + +See section `### Content of code snippets` in the general prompt in `scripts/translate.py`. + +//// + +## Quotes { #quotes } + +//// tab | Test + +Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". + +/// note + +The LLM will probably translate this wrong. Interesting is only if it keeps the fixed translation when retranslating. + +/// + +//// + +//// tab | Info + +The prompt designer may choose if they want to convert neutral quotes to typographic quotes. It is okay to leave them as is. + +See for example section `### Quotes` in `docs/de/llm-prompt.md`. + +//// + +## Quotes in code snippets { #quotes-in-code-snippets} + +//// tab | Test + +`pip install "foo[bar]"` + +Examples for string literals in code snippets: `"this"`, `'that'`. + +A difficult example for string literals in code snippets: `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Info + +... However, quotes inside code snippets must stay as is. + +//// + +## code blocks { #code-blocks } + +//// tab | Test + +A Bash code example... + +```bash +# Print a greeting to the universe +echo "Hello universe" +``` + +...and a console code example... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...and another console code example... + +```console +// Create a directory "Code" +$ mkdir code +// Switch into that directory +$ cd code +``` + +...and a Python code example... + +```Python +wont_work() # This won't work 😱 +works(foo="bar") # This works 🎉 +``` + +...and that's it. + +//// + +//// tab | Info + +Code in code blocks should not be modified, with the exception of comments. + +See section `### Content of code blocks` in the general prompt in `scripts/translate.py`. + +//// + +## Tabs and colored boxes { #tabs-and-colored-boxes } + +//// tab | Test + +/// info +Some text +/// + +/// note +Some text +/// + +/// note | Technical details +Some text +/// + +/// check +Some text +/// + +/// tip +Some text +/// + +/// warning +Some text +/// + +/// danger +Some text +/// + +//// + +//// tab | Info + +Tabs and `Info`/`Note`/`Warning`/etc. blocks should have the translation of their title added after a vertical bar (`|`). + +See sections `### Special blocks` and `### Tab blocks` in the general prompt in `scripts/translate.py`. + +//// + +## Web- and internal links { #web-and-internal-links } + +//// tab | Test + +The link text should get translated, the link address should remain unchaged: + +* [Link to heading above](#code-snippets) +* [Internal link](index.md#installation){.internal-link target=_blank} +* External link +* Link to a style +* Link to a script +* Link to an image + +The link text should get translated, the link address should point to the translation: + +* FastAPI link + +//// + +//// tab | Info + +Links should be translated, but their address shall remain unchanged. An exception are absolute links to pages of the FastAPI documentation. In that case it should link to the translation. + +See section `### Links` in the general prompt in `scripts/translate.py`. + +//// + +## HTML "abbr" elements { #html-abbr-elements } + +//// tab | Test + +Here some things wrapped in HTML "abbr" elements (Some are invented): + +### The abbr gives a full phrase { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### The abbr gives an explanation { #the-abbr-gives-an-explanation } + +* cluster +* Deep Learning + +### The abbr gives a full phrase and an explanation { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Info + +"title" attributes of "abbr" elements are translated following some specific instructions. + +Translations can add their own "abbr" elements which the LLM should not remove. E.g. to explain English words. + +See section `### HTML abbr elements` in the general prompt in `scripts/translate.py`. + +//// + +## Headings { #headings } + +//// tab | Test + +### Develop a webapp - a tutorial { #develop-a-webapp-a-tutorial } + +Hello. + +### Type hints and -annotations { #type-hints-and-annotations } + +Hello again. + +### Super- and subclasses { #super-and-subclasses } + +Hello again. + +//// + +//// tab | Info + +The only hard rule for headings is that the LLM leaves the hash part inside curly brackets unchanged, which ensures that links do not break. + +See section `### Headings` in the general prompt in `scripts/translate.py`. + +For some language specific instructions, see e.g. section `### Headings` in `docs/de/llm-prompt.md`. + +//// + +## Terms used in the docs { #terms-used-in-the-docs } + +//// tab | Test + +* you +* your + +* e.g. +* etc. + +* `foo` as an `int` +* `bar` as a `str` +* `baz` as a `list` + +* the Tutorial - User guide +* the Advanced User Guide +* the SQLModel docs +* the API docs +* the automatic docs + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic authentication +* HTTP Digest +* ISO format +* the JSON Schema standard +* the JSON schema +* the schema definition +* Password Flow +* Mobile + +* deprecated +* designed +* invalid +* on the fly +* standard +* default +* case-sensitive +* case-insensitive + +* to serve the application +* to serve the page + +* the app +* the application + +* the request +* the response +* the error response + +* the path operation +* the path operation decorator +* the path operation function + +* the body +* the request body +* the response body +* the JSON body +* the form body +* the file body +* the function body + +* the parameter +* the body parameter +* the path parameter +* the query parameter +* the cookie parameter +* the header parameter +* the form parameter +* the function parameter + +* the event +* the startup event +* the startup of the server +* the shutdown event +* the lifespan event + +* the handler +* the event handler +* the exception handler +* to handle + +* the model +* the Pydantic model +* the data model +* the database model +* the form model +* the model object + +* the class +* the base class +* the parent class +* the subclass +* the child class +* the sibling class +* the class method + +* the header +* the headers +* the authorization header +* the `Authorization` header +* the forwarded header + +* the dependency injection system +* the dependency +* the dependable +* the dependant + +* I/O bound +* CPU bound +* concurrency +* parallelism +* multiprocessing + +* the env var +* the environment variable +* the `PATH` +* the `PATH` variable + +* the authentication +* the authentication provider +* the authorization +* the authorization form +* the authorization provider +* the user authenticates +* the system authenticates the user + +* the CLI +* the command line interface + +* the server +* the client + +* the cloud provider +* the cloud service + +* the development +* the development stages + +* the dict +* the dictionary +* the enumeration +* the enum +* the enum member + +* the encoder +* the decoder +* to encode +* to decode + +* the exception +* to raise + +* the expression +* the statement + +* the frontend +* the backend + +* the GitHub discussion +* the GitHub issue + +* the performance +* the performance optimization + +* the return type +* the return value + +* the security +* the security scheme + +* the task +* the background task +* the task function + +* the template +* the template engine + +* the type annotation +* the type hint + +* the server worker +* the Uvicorn worker +* the Gunicorn Worker +* the worker process +* the worker class +* the workload + +* the deployment +* to deploy + +* the SDK +* the software development kit + +* the `APIRouter` +* the `requirements.txt` +* the Bearer Token +* the breaking change +* the bug +* the button +* the callable +* the code +* the commit +* the context manager +* the coroutine +* the database session +* the disk +* the domain +* the engine +* the fake X +* the HTTP GET method +* the item +* the library +* the lifespan +* the lock +* the middleware +* the mobile application +* the module +* the mounting +* the network +* the origin +* the override +* the payload +* the processor +* the property +* the proxy +* the pull request +* the query +* the RAM +* the remote machine +* the status code +* the string +* the tag +* the web framework +* the wildcard +* to return +* to validate + +//// + +//// tab | Info + +This is a not complete and not normative list of (mostly) technical terms seen in the docs. It may be helpful for the prompt designer to figure out for which terms the LLM needs a helping hand. For example when it keeps reverting a good translation to a suboptimal translation. Or when it has problems conjugating/declinating a term in your language. + +See e.g. section `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. + +//// From 9d7388d9f15632eee6d98faf93b19f1e9ff27ce9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 12:55:53 +0000 Subject: [PATCH 398/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5f26a01a0..1fd2537f2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Internal +* ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). * 🔨 Update translations script. PR [#13968](https://github.com/fastapi/fastapi/pull/13968) by [@YuriiMotov](https://github.com/YuriiMotov). * 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). From 7095a110563b476dbc3a02501d5ec73b6b52efd7 Mon Sep 17 00:00:00 2001 From: Nils-Hero Lindemann Date: Sat, 20 Sep 2025 14:58:04 +0200 Subject: [PATCH 399/455] =?UTF-8?q?=F0=9F=93=9D=20Fix=20and=20Improve=20En?= =?UTF-8?q?glish=20Documentation=20(#14048)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/en/docs/advanced/async-tests.md | 2 +- docs/en/docs/advanced/custom-response.md | 2 +- docs/en/docs/advanced/response-headers.md | 2 +- docs/en/docs/advanced/websockets.md | 4 ++-- docs/en/docs/deployment/docker.md | 2 +- docs/en/docs/features.md | 2 +- docs/en/docs/how-to/custom-docs-ui-assets.md | 2 +- docs/en/docs/tutorial/body-multiple-params.md | 2 +- docs/en/docs/tutorial/debugging.md | 2 +- docs/en/docs/tutorial/middleware.md | 2 +- docs/en/docs/tutorial/path-params-numeric-validations.md | 2 +- docs/en/docs/tutorial/query-params-str-validations.md | 4 ---- docs/en/docs/tutorial/sql-databases.md | 2 +- 13 files changed, 13 insertions(+), 17 deletions(-) diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md index 7b6f08371..e920e22c3 100644 --- a/docs/en/docs/advanced/async-tests.md +++ b/docs/en/docs/advanced/async-tests.md @@ -94,6 +94,6 @@ As the testing function is now asynchronous, you can now also call (and `await`) /// tip -If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using MongoDB's MotorClient), remember to instantiate objects that need an event loop only within async functions, e.g. an `'@app.on_event("startup")` callback. +If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using MongoDB's MotorClient), remember to instantiate objects that need an event loop only within async functions, e.g. an `@app.on_event("startup")` callback. /// diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md index 5473d939c..0f3d8b701 100644 --- a/docs/en/docs/advanced/custom-response.md +++ b/docs/en/docs/advanced/custom-response.md @@ -221,7 +221,7 @@ Takes an async generator or a normal generator/iterator and streams the response #### Using `StreamingResponse` with file-like objects { #using-streamingresponse-with-file-like-objects } -If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object. +If you have a file-like object (e.g. the object returned by `open()`), you can create a generator function to iterate over that file-like object. That way, you don't have to read it all first in memory, and you can pass that generator function to the `StreamingResponse`, and return it. diff --git a/docs/en/docs/advanced/response-headers.md b/docs/en/docs/advanced/response-headers.md index 98747eabd..19c9ff2ad 100644 --- a/docs/en/docs/advanced/response-headers.md +++ b/docs/en/docs/advanced/response-headers.md @@ -36,6 +36,6 @@ And as the `Response` can be used frequently to set headers and cookies, **FastA ## Custom Headers { #custom-headers } -Keep in mind that custom proprietary headers can be added using the 'X-' prefix. +Keep in mind that custom proprietary headers can be added using the `X-` prefix. But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), using the parameter `expose_headers` documented in Starlette's CORS docs. diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md index 4ba24637f..917dd79bd 100644 --- a/docs/en/docs/advanced/websockets.md +++ b/docs/en/docs/advanced/websockets.md @@ -2,9 +2,9 @@ You can use WebSockets with **FastAPI**. -## Install `WebSockets` { #install-websockets } +## Install `websockets` { #install-websockets } -Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `websockets`: +Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and install `websockets` (a Python library that makes it easy to use the "WebSocket" protocol):
diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md index a1de2dc46..6b71f7360 100644 --- a/docs/en/docs/deployment/docker.md +++ b/docs/en/docs/deployment/docker.md @@ -490,7 +490,7 @@ And normally this **load balancer** would be able to handle requests that go to In this type of scenario, you probably would want to have **a single (Uvicorn) process per container**, as you would already be handling replication at the cluster level. -So, in this case, you **would not** want to have a multiple workers in the container, for example with the `--workers` command line option.You would want to have just a **single Uvicorn process** per container (but probably multiple containers). +So, in this case, you **would not** want to have a multiple workers in the container, for example with the `--workers` command line option. You would want to have just a **single Uvicorn process** per container (but probably multiple containers). Having another process manager inside the container (as would be with multiple workers) would only add **unnecessary complexity** that you are most probably already taking care of with your cluster system. diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index 681caac35..d44d7a6ac 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -190,7 +190,7 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on * **No brainfuck**: * No new schema definition micro-language to learn. * If you know Python types you know how to use Pydantic. -* Plays nicely with your **IDE/linter/brain**: +* Plays nicely with your **IDE/linter/brain**: * Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data. * Validate **complex structures**: * Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc. diff --git a/docs/en/docs/how-to/custom-docs-ui-assets.md b/docs/en/docs/how-to/custom-docs-ui-assets.md index b38c4ec02..91228c8c9 100644 --- a/docs/en/docs/how-to/custom-docs-ui-assets.md +++ b/docs/en/docs/how-to/custom-docs-ui-assets.md @@ -89,7 +89,7 @@ Your new file structure could look like this: Download the static files needed for the docs and put them on that `static/` directory. -You can probably right-click each link and select an option similar to `Save link as...`. +You can probably right-click each link and select an option similar to "Save link as...". **Swagger UI** uses the files: diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md index ab6d7461a..ed23c8149 100644 --- a/docs/en/docs/tutorial/body-multiple-params.md +++ b/docs/en/docs/tutorial/body-multiple-params.md @@ -119,7 +119,7 @@ For example: /// info -`Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later. +`Body` also has all the same extra validation and metadata parameters as `Query`, `Path` and others you will see later. /// diff --git a/docs/en/docs/tutorial/debugging.md b/docs/en/docs/tutorial/debugging.md index a096763f0..08b440084 100644 --- a/docs/en/docs/tutorial/debugging.md +++ b/docs/en/docs/tutorial/debugging.md @@ -62,7 +62,7 @@ from myapp import app # Some more code ``` -in that case, the automatically created variable inside of `myapp.py` will not have the variable `__name__` with a value of `"__main__"`. +in that case, the automatically created variable `__name__` inside of `myapp.py` will not have the value `"__main__"`. So, the line: diff --git a/docs/en/docs/tutorial/middleware.md b/docs/en/docs/tutorial/middleware.md index 9bfbf47c9..bc0519c67 100644 --- a/docs/en/docs/tutorial/middleware.md +++ b/docs/en/docs/tutorial/middleware.md @@ -35,7 +35,7 @@ The middleware function receives: /// tip -Keep in mind that custom proprietary headers can be added using the 'X-' prefix. +Keep in mind that custom proprietary headers can be added using the `X-` prefix. But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in Starlette's CORS docs. diff --git a/docs/en/docs/tutorial/path-params-numeric-validations.md b/docs/en/docs/tutorial/path-params-numeric-validations.md index 435606bbf..ef1caea42 100644 --- a/docs/en/docs/tutorial/path-params-numeric-validations.md +++ b/docs/en/docs/tutorial/path-params-numeric-validations.md @@ -2,7 +2,7 @@ In the same way that you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`. -## Import Path { #import-path } +## Import `Path` { #import-path } First, import `Path` from `fastapi`, and import `Annotated`: diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md index a55b4cfb0..adf08a924 100644 --- a/docs/en/docs/tutorial/query-params-str-validations.md +++ b/docs/en/docs/tutorial/query-params-str-validations.md @@ -250,14 +250,10 @@ q: str | None = None But we are now declaring it with `Query`, for example like: -//// tab | Annotated - ```Python q: Annotated[str | None, Query(min_length=3)] = None ``` -//// - So, when you need to declare a value as required while using `Query`, you can simply not declare a default value: {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} diff --git a/docs/en/docs/tutorial/sql-databases.md b/docs/en/docs/tutorial/sql-databases.md index 79538e566..cfa1c9073 100644 --- a/docs/en/docs/tutorial/sql-databases.md +++ b/docs/en/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ Here we'll see an example using "ORMs"), FastAPI doesn't force you to use anything. 😎 +You could use any other SQL or NoSQL database library you want (in some cases called "ORMs"), FastAPI doesn't force you to use anything. 😎 /// From 4c175319f5ddfa60fb9b0673586f619ae9573e01 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 12:58:37 +0000 Subject: [PATCH 400/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1fd2537f2..2cf52b730 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,10 @@ hide: * ⬆️ Update mypy to 1.14.1. PR [#12970](https://github.com/fastapi/fastapi/pull/12970) by [@tamird](https://github.com/tamird). +### Docs + +* 📝 Fix and Improve English Documentation. PR [#14048](https://github.com/fastapi/fastapi/pull/14048) by [@nilslindemann](https://github.com/nilslindemann). + ### Internal * ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). From 9b1234d7d03082ca49fc048bbc53bbe3d679ec34 Mon Sep 17 00:00:00 2001 From: Nils-Hero Lindemann Date: Sat, 20 Sep 2025 17:10:09 +0200 Subject: [PATCH 401/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20prompts=20and?= =?UTF-8?q?=20German=20translation=20(#14015)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- docs/de/docs/about/index.md | 2 +- docs/de/docs/advanced/additional-responses.md | 24 +- .../docs/advanced/additional-status-codes.md | 12 +- .../de/docs/advanced/advanced-dependencies.md | 16 +- docs/de/docs/advanced/async-tests.md | 26 +- docs/de/docs/advanced/behind-a-proxy.md | 163 +++- docs/de/docs/advanced/custom-response.md | 85 +- docs/de/docs/advanced/dataclasses.md | 30 +- docs/de/docs/advanced/events.md | 54 +- docs/de/docs/advanced/generate-clients.md | 199 ++--- docs/de/docs/advanced/index.md | 23 +- docs/de/docs/advanced/middleware.md | 26 +- docs/de/docs/advanced/openapi-callbacks.md | 30 +- docs/de/docs/advanced/openapi-webhooks.md | 38 +- .../path-operation-advanced-configuration.md | 46 +- .../advanced/response-change-status-code.md | 18 +- docs/de/docs/advanced/response-cookies.md | 12 +- docs/de/docs/advanced/response-directly.md | 16 +- docs/de/docs/advanced/response-headers.md | 16 +- .../docs/advanced/security/http-basic-auth.md | 25 +- docs/de/docs/advanced/security/index.md | 8 +- .../docs/advanced/security/oauth2-scopes.md | 54 +- docs/de/docs/advanced/settings.md | 178 +--- docs/de/docs/advanced/sub-applications.md | 24 +- docs/de/docs/advanced/templates.md | 30 +- docs/de/docs/advanced/testing-dependencies.md | 15 +- docs/de/docs/advanced/testing-events.md | 11 +- docs/de/docs/advanced/testing-websockets.md | 4 +- .../docs/advanced/using-request-directly.md | 12 +- docs/de/docs/advanced/websockets.md | 36 +- docs/de/docs/advanced/wsgi.md | 12 +- docs/de/docs/alternatives.md | 82 +- docs/de/docs/async.md | 104 +-- docs/de/docs/benchmarks.md | 30 +- docs/de/docs/deployment/cloud.md | 17 +- docs/de/docs/deployment/concepts.md | 78 +- docs/de/docs/deployment/docker.md | 385 +++----- docs/de/docs/deployment/https.md | 72 +- docs/de/docs/deployment/index.md | 10 +- docs/de/docs/deployment/manually.md | 178 ++-- docs/de/docs/deployment/server-workers.md | 162 ++-- docs/de/docs/deployment/versions.md | 35 +- docs/de/docs/environment-variables.md | 298 +++++++ docs/de/docs/fastapi-cli.md | 75 ++ docs/de/docs/features.md | 83 +- docs/de/docs/help-fastapi.md | 178 ++-- docs/de/docs/history-design-future.md | 20 +- docs/de/docs/how-to/conditional-openapi.md | 12 +- docs/de/docs/how-to/configure-swagger-ui.md | 20 +- docs/de/docs/how-to/custom-docs-ui-assets.md | 50 +- .../docs/how-to/custom-request-and-route.md | 24 +- docs/de/docs/how-to/extending-openapi.md | 32 +- docs/de/docs/how-to/general.md | 32 +- docs/de/docs/how-to/graphql.md | 26 +- docs/de/docs/how-to/index.md | 2 +- .../docs/how-to/separate-openapi-schemas.md | 28 +- docs/de/docs/how-to/testing-database.md | 7 + docs/de/docs/index.md | 271 +++--- docs/de/docs/learn/index.md | 4 +- docs/de/docs/project-generation.md | 102 +-- docs/de/docs/python-types.md | 78 +- docs/de/docs/resources/index.md | 2 +- docs/de/docs/tutorial/background-tasks.md | 26 +- docs/de/docs/tutorial/bigger-applications.md | 63 +- docs/de/docs/tutorial/body-fields.md | 24 +- docs/de/docs/tutorial/body-multiple-params.md | 48 +- docs/de/docs/tutorial/body-nested-models.md | 66 +- docs/de/docs/tutorial/body-updates.md | 38 +- docs/de/docs/tutorial/body.md | 105 ++- docs/de/docs/tutorial/cookie-param-models.md | 76 ++ docs/de/docs/tutorial/cookie-params.md | 24 +- docs/de/docs/tutorial/cors.md | 88 ++ docs/de/docs/tutorial/debugging.md | 113 +++ .../dependencies/classes-as-dependencies.md | 16 +- ...pendencies-in-path-operation-decorators.md | 22 +- .../dependencies/dependencies-with-yield.md | 72 +- .../dependencies/global-dependencies.md | 8 +- docs/de/docs/tutorial/dependencies/index.md | 48 +- .../tutorial/dependencies/sub-dependencies.md | 22 +- docs/de/docs/tutorial/encoder.md | 6 +- docs/de/docs/tutorial/extra-data-types.md | 16 +- docs/de/docs/tutorial/extra-models.md | 125 +-- docs/de/docs/tutorial/first-steps.md | 156 ++-- docs/de/docs/tutorial/handling-errors.md | 144 +-- docs/de/docs/tutorial/header-param-models.md | 72 ++ docs/de/docs/tutorial/header-params.md | 56 +- docs/de/docs/tutorial/index.md | 92 +- docs/de/docs/tutorial/metadata.md | 62 +- docs/de/docs/tutorial/middleware.md | 49 +- .../tutorial/path-operation-configuration.md | 48 +- .../path-params-numeric-validations.md | 131 ++- docs/de/docs/tutorial/path-params.md | 76 +- docs/de/docs/tutorial/query-param-models.md | 68 ++ .../tutorial/query-params-str-validations.md | 384 ++++---- docs/de/docs/tutorial/query-params.md | 36 +- docs/de/docs/tutorial/request-files.md | 64 +- docs/de/docs/tutorial/request-form-models.md | 78 ++ .../docs/tutorial/request-forms-and-files.md | 22 +- docs/de/docs/tutorial/request-forms.md | 34 +- docs/de/docs/tutorial/response-model.md | 93 +- docs/de/docs/tutorial/response-status-code.md | 64 +- docs/de/docs/tutorial/schema-extra-example.md | 54 +- docs/de/docs/tutorial/security/first-steps.md | 52 +- .../tutorial/security/get-current-user.md | 22 +- docs/de/docs/tutorial/security/index.md | 18 +- docs/de/docs/tutorial/security/oauth2-jwt.md | 70 +- .../docs/tutorial/security/simple-oauth2.md | 48 +- docs/de/docs/tutorial/sql-databases.md | 357 ++++++++ docs/de/docs/tutorial/static-files.md | 12 +- docs/de/docs/tutorial/testing.md | 38 +- docs/de/docs/virtual-environments.md | 842 ++++++++++++++++++ docs/de/llm-prompt.md | 338 +++++++ 112 files changed, 5303 insertions(+), 3025 deletions(-) create mode 100644 docs/de/docs/environment-variables.md create mode 100644 docs/de/docs/fastapi-cli.md create mode 100644 docs/de/docs/how-to/testing-database.md create mode 100644 docs/de/docs/tutorial/cookie-param-models.md create mode 100644 docs/de/docs/tutorial/cors.md create mode 100644 docs/de/docs/tutorial/debugging.md create mode 100644 docs/de/docs/tutorial/header-param-models.md create mode 100644 docs/de/docs/tutorial/query-param-models.md create mode 100644 docs/de/docs/tutorial/request-form-models.md create mode 100644 docs/de/docs/tutorial/sql-databases.md create mode 100644 docs/de/docs/virtual-environments.md create mode 100644 docs/de/llm-prompt.md diff --git a/docs/de/docs/about/index.md b/docs/de/docs/about/index.md index 4c309e02a..5e9c6b6a0 100644 --- a/docs/de/docs/about/index.md +++ b/docs/de/docs/about/index.md @@ -1,3 +1,3 @@ -# Über +# Über { #about } Über FastAPI, sein Design, seine Inspiration und mehr. 🤓 diff --git a/docs/de/docs/advanced/additional-responses.md b/docs/de/docs/advanced/additional-responses.md index bf38d9795..218dd6c4f 100644 --- a/docs/de/docs/advanced/additional-responses.md +++ b/docs/de/docs/advanced/additional-responses.md @@ -1,4 +1,4 @@ -# Zusätzliche Responses in OpenAPI +# Zusätzliche Responses in OpenAPI { #additional-responses-in-openapi } /// warning | Achtung @@ -8,17 +8,17 @@ Wenn Sie mit **FastAPI** beginnen, benötigen Sie dies möglicherweise nicht. /// -Sie können zusätzliche Responses mit zusätzlichen Statuscodes, Medientypen, Beschreibungen, usw. deklarieren. +Sie können zusätzliche Responses mit zusätzlichen Statuscodes, Medientypen, Beschreibungen, usw. deklarieren. Diese zusätzlichen Responses werden in das OpenAPI-Schema aufgenommen, sodass sie auch in der API-Dokumentation erscheinen. Für diese zusätzlichen Responses müssen Sie jedoch sicherstellen, dass Sie eine `Response`, wie etwa `JSONResponse`, direkt zurückgeben, mit Ihrem Statuscode und Inhalt. -## Zusätzliche Response mit `model` +## Zusätzliche Response mit `model` { #additional-response-with-model } Sie können Ihren *Pfadoperation-Dekoratoren* einen Parameter `responses` übergeben. -Der nimmt ein `dict` entgegen, die Schlüssel sind Statuscodes für jede Response, wie etwa `200`, und die Werte sind andere `dict`s mit den Informationen für jede Response. +Der nimmt ein `dict` entgegen, die Schlüssel sind Statuscodes für jede Response, wie etwa `200`, und die Werte sind andere `dict`s mit den Informationen für jede Response. Jedes dieser Response-`dict`s kann einen Schlüssel `model` haben, welcher ein Pydantic-Modell enthält, genau wie `response_model`. @@ -34,7 +34,7 @@ Beachten Sie, dass Sie die `JSONResponse` direkt zurückgeben müssen. /// -/// info +/// info | Info Der `model`-Schlüssel ist nicht Teil von OpenAPI. @@ -169,7 +169,7 @@ Die Schemas werden von einer anderen Stelle innerhalb des OpenAPI-Schemas refere } ``` -## Zusätzliche Medientypen für die Haupt-Response +## Zusätzliche Medientypen für die Haupt-Response { #additional-media-types-for-the-main-response } Sie können denselben `responses`-Parameter verwenden, um verschiedene Medientypen für dieselbe Haupt-Response hinzuzufügen. @@ -183,7 +183,7 @@ Beachten Sie, dass Sie das Bild direkt mit einer `FileResponse` zurückgeben mü /// -/// info +/// info | Info Sofern Sie in Ihrem Parameter `responses` nicht explizit einen anderen Medientyp angeben, geht FastAPI davon aus, dass die Response denselben Medientyp wie die Haupt-Response-Klasse hat (Standardmäßig `application/json`). @@ -191,7 +191,7 @@ Wenn Sie jedoch eine benutzerdefinierte Response-Klasse mit `None` als Medientyp /// -## Informationen kombinieren +## Informationen kombinieren { #combining-information } Sie können auch Response-Informationen von mehreren Stellen kombinieren, einschließlich der Parameter `response_model`, `status_code` und `responses`. @@ -209,7 +209,7 @@ Es wird alles kombiniert und in Ihre OpenAPI eingebunden und in der API-Dokument -## Vordefinierte und benutzerdefinierte Responses kombinieren +## Vordefinierte und benutzerdefinierte Responses kombinieren { #combine-predefined-responses-and-custom-ones } Möglicherweise möchten Sie einige vordefinierte Responses haben, die für viele *Pfadoperationen* gelten, Sie möchten diese jedoch mit benutzerdefinierten Responses kombinieren, die für jede *Pfadoperation* erforderlich sind. @@ -239,9 +239,9 @@ Zum Beispiel: {* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *} -## Weitere Informationen zu OpenAPI-Responses +## Weitere Informationen zu OpenAPI-Responses { #more-information-about-openapi-responses } Um zu sehen, was genau Sie in die Responses aufnehmen können, können Sie die folgenden Abschnitte in der OpenAPI-Spezifikation überprüfen: -* OpenAPI Responses Object, enthält das `Response Object`. -* OpenAPI Response Object, Sie können alles davon direkt in jede Response innerhalb Ihres `responses`-Parameter einfügen. Einschließlich `description`, `headers`, `content` (darin deklarieren Sie verschiedene Medientypen und JSON-Schemas) und `links`. +* OpenAPI Responses Object, enthält das `Response Object`. +* OpenAPI Response Object, Sie können alles davon direkt in jede Response innerhalb Ihres `responses`-Parameter einfügen. Einschließlich `description`, `headers`, `content` (darin deklarieren Sie verschiedene Medientypen und JSON-Schemas) und `links`. diff --git a/docs/de/docs/advanced/additional-status-codes.md b/docs/de/docs/advanced/additional-status-codes.md index b07bb90ab..f948e1862 100644 --- a/docs/de/docs/advanced/additional-status-codes.md +++ b/docs/de/docs/advanced/additional-status-codes.md @@ -1,16 +1,16 @@ -# Zusätzliche Statuscodes +# Zusätzliche Statuscodes { #additional-status-codes } -Standardmäßig liefert **FastAPI** die Rückgabewerte (Responses) als `JSONResponse` zurück und fügt den Inhalt der jeweiligen *Pfadoperation* in das `JSONResponse` Objekt ein. +Standardmäßig liefert **FastAPI** die Responses als `JSONResponse` zurück und fügt den Inhalt, den Sie aus Ihrer *Pfadoperation* zurückgeben, in diese `JSONResponse` ein. Es wird der Default-Statuscode oder derjenige verwendet, den Sie in Ihrer *Pfadoperation* festgelegt haben. -## Zusätzliche Statuscodes +## Zusätzliche Statuscodes { #additional-status-codes_1 } Wenn Sie neben dem Hauptstatuscode weitere Statuscodes zurückgeben möchten, können Sie dies tun, indem Sie direkt eine `Response` zurückgeben, wie etwa eine `JSONResponse`, und den zusätzlichen Statuscode direkt festlegen. Angenommen, Sie möchten eine *Pfadoperation* haben, die das Aktualisieren von Artikeln ermöglicht und bei Erfolg den HTTP-Statuscode 200 „OK“ zurückgibt. -Sie möchten aber auch, dass sie neue Artikel akzeptiert. Und wenn die Elemente vorher nicht vorhanden waren, werden diese Elemente erstellt und der HTTP-Statuscode 201 „Created“ zurückgegeben. +Sie möchten aber auch, dass sie neue Artikel akzeptiert. Und wenn die Artikel vorher nicht vorhanden waren, werden diese Artikel erstellt und der HTTP-Statuscode 201 „Created“ zurückgegeben. Um dies zu erreichen, importieren Sie `JSONResponse`, und geben Sie Ihren Inhalt direkt zurück, indem Sie den gewünschten `status_code` setzen: @@ -30,11 +30,11 @@ Stellen Sie sicher, dass sie die gewünschten Daten enthält und dass die Werte Sie können auch `from starlette.responses import JSONResponse` verwenden. -**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `status`. +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Dasselbe gilt für `status`. /// -## OpenAPI- und API-Dokumentation +## OpenAPI- und API-Dokumentation { #openapi-and-api-docs } Wenn Sie zusätzliche Statuscodes und Responses direkt zurückgeben, werden diese nicht in das OpenAPI-Schema (die API-Dokumentation) aufgenommen, da FastAPI keine Möglichkeit hat, im Voraus zu wissen, was Sie zurückgeben werden. diff --git a/docs/de/docs/advanced/advanced-dependencies.md b/docs/de/docs/advanced/advanced-dependencies.md index 56eb7d454..a153665cc 100644 --- a/docs/de/docs/advanced/advanced-dependencies.md +++ b/docs/de/docs/advanced/advanced-dependencies.md @@ -1,6 +1,6 @@ -# Fortgeschrittene Abhängigkeiten +# Fortgeschrittene Abhängigkeiten { #advanced-dependencies } -## Parametrisierte Abhängigkeiten +## Parametrisierte Abhängigkeiten { #parameterized-dependencies } Alle Abhängigkeiten, die wir bisher gesehen haben, waren festgelegte Funktionen oder Klassen. @@ -10,9 +10,9 @@ Stellen wir uns vor, wir möchten eine Abhängigkeit haben, die prüft, ob ein Q Aber wir wollen diesen vordefinierten Inhalt per Parameter festlegen können. -## Eine „aufrufbare“ Instanz +## Eine „aufrufbare“ Instanz { #a-callable-instance } -In Python gibt es eine Möglichkeit, eine Instanz einer Klasse „aufrufbar“ („callable“) zu machen. +In Python gibt es eine Möglichkeit, eine Instanz einer Klasse „aufrufbar“ zu machen. Nicht die Klasse selbst (die bereits aufrufbar ist), sondern eine Instanz dieser Klasse. @@ -22,15 +22,15 @@ Dazu deklarieren wir eine Methode `__call__`: In diesem Fall ist dieses `__call__` das, was **FastAPI** verwendet, um nach zusätzlichen Parametern und Unterabhängigkeiten zu suchen, und das ist es auch, was später aufgerufen wird, um einen Wert an den Parameter in Ihrer *Pfadoperation-Funktion* zu übergeben. -## Die Instanz parametrisieren +## Die Instanz parametrisieren { #parameterize-the-instance } -Und jetzt können wir `__init__` verwenden, um die Parameter der Instanz zu deklarieren, die wir zum `Parametrisieren` der Abhängigkeit verwenden können: +Und jetzt können wir `__init__` verwenden, um die Parameter der Instanz zu deklarieren, die wir zum „Parametrisieren“ der Abhängigkeit verwenden können: {* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *} In diesem Fall wird **FastAPI** `__init__` nie berühren oder sich darum kümmern, wir werden es direkt in unserem Code verwenden. -## Eine Instanz erstellen +## Eine Instanz erstellen { #create-an-instance } Wir könnten eine Instanz dieser Klasse erstellen mit: @@ -38,7 +38,7 @@ Wir könnten eine Instanz dieser Klasse erstellen mit: Und auf diese Weise können wir unsere Abhängigkeit „parametrisieren“, die jetzt `"bar"` enthält, als das Attribut `checker.fixed_content`. -## Die Instanz als Abhängigkeit verwenden +## Die Instanz als Abhängigkeit verwenden { #use-the-instance-as-a-dependency } Dann könnten wir diesen `checker` in einem `Depends(checker)` anstelle von `Depends(FixedContentQueryChecker)` verwenden, da die Abhängigkeit die Instanz `checker` und nicht die Klasse selbst ist. diff --git a/docs/de/docs/advanced/async-tests.md b/docs/de/docs/advanced/async-tests.md index b82aadf00..ad8245205 100644 --- a/docs/de/docs/advanced/async-tests.md +++ b/docs/de/docs/advanced/async-tests.md @@ -1,24 +1,24 @@ -# Asynchrone Tests +# Asynchrone Tests { #async-tests } -Sie haben bereits gesehen, wie Sie Ihre **FastAPI**-Anwendungen mit dem bereitgestellten `TestClient` testen. Bisher haben Sie nur gesehen, wie man synchrone Tests schreibt, ohne `async`hrone Funktionen zu verwenden. +Sie haben bereits gesehen, wie Sie Ihre **FastAPI**-Anwendungen mit dem bereitgestellten `TestClient` testen. Bisher haben Sie nur gesehen, wie man synchrone Tests schreibt, ohne `async`-Funktionen zu verwenden. -Die Möglichkeit, in Ihren Tests asynchrone Funktionen zu verwenden, könnte beispielsweise nützlich sein, wenn Sie Ihre Datenbank asynchron abfragen. Stellen Sie sich vor, Sie möchten das Senden von Requests an Ihre FastAPI-Anwendung testen und dann überprüfen, ob Ihr Backend die richtigen Daten erfolgreich in die Datenbank geschrieben hat, während Sie eine asynchrone Datenbankbibliothek verwenden. +Die Möglichkeit, in Ihren Tests asynchrone Funktionen zu verwenden, könnte beispielsweise nützlich sein, wenn Sie Ihre Datenbank asynchron abfragen. Stellen Sie sich vor, Sie möchten das Senden von Requests an Ihre FastAPI-Anwendung testen und dann überprüfen, ob Ihr Backend die richtigen Daten erfolgreich in die Datenbank geschrieben hat, während Sie eine asynchrone Datenbankbibliothek verwenden. Schauen wir uns an, wie wir das machen können. -## pytest.mark.anyio +## pytest.mark.anyio { #pytest-mark-anyio } Wenn wir in unseren Tests asynchrone Funktionen aufrufen möchten, müssen unsere Testfunktionen asynchron sein. AnyIO stellt hierfür ein nettes Plugin zur Verfügung, mit dem wir festlegen können, dass einige Testfunktionen asynchron aufgerufen werden sollen. -## HTTPX +## HTTPX { #httpx } -Auch wenn Ihre **FastAPI**-Anwendung normale `def`-Funktionen anstelle von `async def` verwendet, handelt es sich darunter immer noch um eine `async`hrone Anwendung. +Auch wenn Ihre **FastAPI**-Anwendung normale `def`-Funktionen anstelle von `async def` verwendet, handelt es sich darunter immer noch um eine `async`-Anwendung. -Der `TestClient` macht unter der Haube magisches, um die asynchrone FastAPI-Anwendung in Ihren normalen `def`-Testfunktionen, mithilfe von Standard-Pytest aufzurufen. Aber diese Magie funktioniert nicht mehr, wenn wir sie in asynchronen Funktionen verwenden. Durch die asynchrone Ausführung unserer Tests können wir den `TestClient` nicht mehr in unseren Testfunktionen verwenden. +Der `TestClient` betreibt unter der Haube etwas Magie, um die asynchrone FastAPI-Anwendung in Ihren normalen `def`-Testfunktionen, mithilfe von Standard-Pytest aufzurufen. Aber diese Magie funktioniert nicht mehr, wenn wir sie in asynchronen Funktionen verwenden. Durch die asynchrone Ausführung unserer Tests können wir den `TestClient` nicht mehr in unseren Testfunktionen verwenden. -Der `TestClient` basiert auf HTTPX und glücklicherweise können wir ihn direkt verwenden, um die API zu testen. +Der `TestClient` basiert auf HTTPX und glücklicherweise können wir es direkt verwenden, um die API zu testen. -## Beispiel +## Beispiel { #example } Betrachten wir als einfaches Beispiel eine Dateistruktur ähnlich der in [Größere Anwendungen](../tutorial/bigger-applications.md){.internal-link target=_blank} und [Testen](../tutorial/testing.md){.internal-link target=_blank}: @@ -38,7 +38,7 @@ Die Datei `test_main.py` hätte die Tests für `main.py`, das könnte jetzt so a {* ../../docs_src/async_tests/test_main.py *} -## Es ausführen +## Es ausführen { #run-it } Sie können Ihre Tests wie gewohnt ausführen mit: @@ -52,7 +52,7 @@ $ pytest
-## Details +## Im Detail { #in-detail } Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynchron aufgerufen werden soll: @@ -88,9 +88,9 @@ Falls Ihre Anwendung auf Lifespan-Events angewiesen ist, der `AsyncClient` löst /// -## Andere asynchrone Funktionsaufrufe +## Andere asynchrone Funktionsaufrufe { #other-asynchronous-function-calls } -Da die Testfunktion jetzt asynchron ist, können Sie in Ihren Tests neben dem Senden von Requests an Ihre FastAPI-Anwendung jetzt auch andere `async`hrone Funktionen aufrufen (und `await`en), genau so, wie Sie diese an anderer Stelle in Ihrem Code aufrufen würden. +Da die Testfunktion jetzt asynchron ist, können Sie in Ihren Tests neben dem Senden von Requests an Ihre FastAPI-Anwendung jetzt auch andere `async`-Funktionen aufrufen (und `await`en), genau so, wie Sie diese an anderer Stelle in Ihrem Code aufrufen würden. /// tip | Tipp diff --git a/docs/de/docs/advanced/behind-a-proxy.md b/docs/de/docs/advanced/behind-a-proxy.md index 9e2282280..036916cbe 100644 --- a/docs/de/docs/advanced/behind-a-proxy.md +++ b/docs/de/docs/advanced/behind-a-proxy.md @@ -1,17 +1,114 @@ -# Hinter einem Proxy +# Hinter einem Proxy { #behind-a-proxy } -In manchen Situationen müssen Sie möglicherweise einen **Proxy**-Server wie Traefik oder Nginx verwenden, mit einer Konfiguration, die ein zusätzliches Pfadpräfix hinzufügt, das von Ihrer Anwendung nicht gesehen wird. +In vielen Situationen würden Sie einen **Proxy** wie Traefik oder Nginx vor Ihrer FastAPI-App verwenden. -In diesen Fällen können Sie `root_path` verwenden, um Ihre Anwendung zu konfigurieren. +Diese Proxys könnten HTTPS-Zertifikate und andere Dinge handhaben. -Der `root_path` („Wurzelpfad“) ist ein Mechanismus, der von der ASGI-Spezifikation bereitgestellt wird (auf der FastAPI via Starlette aufbaut). +## Proxy-Forwarded-Header { #proxy-forwarded-headers } + +Ein **Proxy** vor Ihrer Anwendung würde normalerweise einige Header on-the-fly setzen, bevor er die Requests an den **Server** sendet, um den Server wissen zu lassen, dass der Request vom Proxy **weitergeleitet** wurde, einschließlich der ursprünglichen (öffentlichen) URL, inklusive der Domain, dass HTTPS verwendet wird, usw. + +Das **Server**-Programm (z. B. **Uvicorn** via **FastAPI CLI**) ist in der Lage, diese Header zu interpretieren und diese Information dann an Ihre Anwendung weiterzugeben. + +Aber aus Sicherheitsgründen, da der Server nicht weiß, dass er hinter einem vertrauenswürdigen Proxy läuft, wird er diese Header nicht interpretieren. + +/// note | Technische Details + +Die Proxy-Header sind: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +### Proxy-Forwarded-Header aktivieren { #enable-proxy-forwarded-headers } + +Sie können FastAPI CLI mit der *CLI-Option* `--forwarded-allow-ips` starten und die IP-Adressen übergeben, denen vertraut werden soll, um diese Forwarded-Header zu lesen. + +Wenn Sie es auf `--forwarded-allow-ips="*"` setzen, würde es allen eingehenden IPs vertrauen. + +Wenn Ihr **Server** hinter einem vertrauenswürdigen **Proxy** sitzt und nur der Proxy mit ihm spricht, würde dies dazu führen, dass er die IP dieses **Proxys** akzeptiert, was auch immer sie ist. + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Weiterleitungen mit HTTPS { #redirects-with-https } + +Angenommen, Sie definieren eine *Pfadoperation* `/items/`: + +{* ../../docs_src/behind_a_proxy/tutorial001_01.py hl[6] *} + +Wenn der Client versucht, zu `/items` zu gehen, würde er standardmäßig zu `/items/` umgeleitet. + +Aber bevor Sie die *CLI-Option* `--forwarded-allow-ips` setzen, könnte er zu `http://localhost:8000/items/` umleiten. + +Aber möglicherweise wird Ihre Anwendung unter `https://mysuperapp.com` gehostet, und die Weiterleitung sollte zu `https://mysuperapp.com/items/` erfolgen. + +Durch Setzen von `--proxy-headers` kann FastAPI jetzt an den richtigen Ort umleiten. 😎 + +``` +https://mysuperapp.com/items/ +``` + +/// tip | Tipp + +Wenn Sie mehr über HTTPS erfahren möchten, lesen Sie den Leitfaden [Über HTTPS](../deployment/https.md){.internal-link target=_blank}. + +/// + +### Wie Proxy-Forwarded-Header funktionieren + +Hier ist eine visuelle Darstellung, wie der **Proxy** weitergeleitete Header zwischen dem Client und dem **Anwendungsserver** hinzufügt: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Loadbalancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS-Request
Host: mysuperapp.com
Pfad: /items + + Note over Proxy: Proxy fügt Forwarded-Header hinzu + + Proxy->>Server: HTTP-Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Pfad: /items + + Note over Server: Server interpretiert die Header
(wenn --forwarded-allow-ips gesetzt ist) + + Server->>Proxy: HTTP-Response
mit correkten HTTPS-URLs + + Proxy->>Client: HTTPS-Response +``` + +Der **Proxy** fängt den ursprünglichen Client-Request ab und fügt die speziellen *Forwarded*-Header (`X-Forwarded-*`) hinzu, bevor er den Request an den **Anwendungsserver** weitergibt. + +Diese Header bewahren Informationen über den ursprünglichen Request, die sonst verloren gingen: + +* **X-Forwarded-For**: Die ursprüngliche IP-Adresse des Clients +* **X-Forwarded-Proto**: Das ursprüngliche Protokoll (`https`) +* **X-Forwarded-Host**: Der ursprüngliche Host (`mysuperapp.com`) + +Wenn **FastAPI CLI** mit `--forwarded-allow-ips` konfiguriert ist, vertraut es diesen Headern und verwendet sie, z. B. um die korrekten URLs in Weiterleitungen zu erzeugen. + +## Proxy mit einem abgetrennten Pfadpräfix { #proxy-with-a-stripped-path-prefix } + +Sie könnten einen Proxy haben, der Ihrer Anwendung ein Pfadpräfix hinzufügt. + +In diesen Fällen können Sie `root_path` verwenden, um Ihre Anwendung zu konfigurieren. + +Der `root_path` ist ein Mechanismus, der von der ASGI-Spezifikation bereitgestellt wird (auf der FastAPI via Starlette aufbaut). Der `root_path` wird verwendet, um diese speziellen Fälle zu handhaben. Und er wird auch intern beim Mounten von Unteranwendungen verwendet. -## Proxy mit einem abgetrennten Pfadpräfix - Ein Proxy mit einem abgetrennten Pfadpräfix bedeutet in diesem Fall, dass Sie einen Pfad unter `/app` in Ihrem Code deklarieren könnten, dann aber, eine Ebene darüber, den Proxy hinzufügen, der Ihre **FastAPI**-Anwendung unter einem Pfad wie `/api/v1` platziert. In diesem Fall würde der ursprüngliche Pfad `/app` tatsächlich unter `/api/v1/app` bereitgestellt. @@ -20,13 +117,13 @@ Auch wenn Ihr gesamter Code unter der Annahme geschrieben ist, dass es nur `/app {* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *} -Und der Proxy würde das **Pfadpräfix** on-the-fly **"entfernen**", bevor er die Anfrage an Uvicorn übermittelt, dafür sorgend, dass Ihre Anwendung davon überzeugt ist, dass sie unter `/app` bereitgestellt wird, sodass Sie nicht Ihren gesamten Code dahingehend aktualisieren müssen, das Präfix `/api/v1` zu verwenden. +Und der Proxy würde das **Pfadpräfix** on-the-fly **„entfernen“**, bevor er den Request an den Anwendungsserver (wahrscheinlich Uvicorn via FastAPI CLI) übermittelt, dafür sorgend, dass Ihre Anwendung davon überzeugt ist, dass sie unter `/app` bereitgestellt wird, sodass Sie nicht Ihren gesamten Code dahingehend aktualisieren müssen, das Präfix `/api/v1` zu verwenden. Bis hierher würde alles wie gewohnt funktionieren. Wenn Sie dann jedoch die Benutzeroberfläche der integrierten Dokumentation (das Frontend) öffnen, wird angenommen, dass sich das OpenAPI-Schema unter `/openapi.json` anstelle von `/api/v1/openapi.json` befindet. -Das Frontend (das im Browser läuft) würde also versuchen, `/openapi.json` zu erreichen und wäre nicht in der Lage, das OpenAPI-Schema abzurufen. +Also würde das Frontend (das im Browser läuft) versuchen, `/openapi.json` zu erreichen und wäre nicht in der Lage, das OpenAPI-Schema abzurufen. Da wir für unsere Anwendung einen Proxy mit dem Pfadpräfix `/api/v1` haben, muss das Frontend das OpenAPI-Schema unter `/api/v1/openapi.json` abrufen. @@ -64,16 +161,16 @@ Die Benutzeroberfläche der Dokumentation würde benötigen, dass das OpenAPI-Sc } ``` -In diesem Beispiel könnte der „Proxy“ etwa **Traefik** sein. Und der Server wäre so etwas wie **Uvicorn**, auf dem Ihre FastAPI-Anwendung ausgeführt wird. +In diesem Beispiel könnte der „Proxy“ etwa **Traefik** sein. Und der Server wäre etwas wie FastAPI CLI mit **Uvicorn**, auf dem Ihre FastAPI-Anwendung ausgeführt wird. -### Bereitstellung des `root_path` +### Bereitstellung des `root_path` { #providing-the-root-path } Um dies zu erreichen, können Sie die Kommandozeilenoption `--root-path` wie folgt verwenden:
```console -$ uvicorn main:app --root-path /api/v1 +$ 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) ``` @@ -90,9 +187,9 @@ Und die Kommandozeilenoption `--root-path` stellt diesen `root_path` bereit. /// -### Überprüfen des aktuellen `root_path` +### Testen des aktuellen `root_path` { #checking-the-current-root-path } -Sie können den aktuellen `root_path` abrufen, der von Ihrer Anwendung für jede Anfrage verwendet wird. Er ist Teil des `scope`-Dictionarys (das ist Teil der ASGI-Spezifikation). +Sie können den aktuellen `root_path` abrufen, der von Ihrer Anwendung für jeden Request verwendet wird. Er ist Teil des `scope`-Dictionarys (das ist Teil der ASGI-Spezifikation). Hier fügen wir ihn, nur zu Demonstrationszwecken, in die Nachricht ein. @@ -103,14 +200,14 @@ Wenn Sie Uvicorn dann starten mit:
```console -$ uvicorn main:app --root-path /api/v1 +$ 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) ```
-wäre die Response etwa: +wäre die Response etwa: ```JSON { @@ -119,19 +216,19 @@ wäre die Response etwa: } ``` -### Festlegen des `root_path` in der FastAPI-Anwendung +### Festlegen des `root_path` in der FastAPI-Anwendung { #setting-the-root-path-in-the-fastapi-app } -Falls Sie keine Möglichkeit haben, eine Kommandozeilenoption wie `--root-path` oder ähnlich zu übergeben, können Sie als Alternative beim Erstellen Ihrer FastAPI-Anwendung den Parameter `root_path` setzen: +Falls Sie keine Möglichkeit haben, eine Kommandozeilenoption wie `--root-path` oder ähnlich zu übergeben, können Sie, alternativ dazu, beim Erstellen Ihrer FastAPI-Anwendung den Parameter `root_path` setzen: {* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *} Die Übergabe des `root_path` an `FastAPI` wäre das Äquivalent zur Übergabe der `--root-path`-Kommandozeilenoption an Uvicorn oder Hypercorn. -### Über `root_path` +### Über `root_path` { #about-root-path } -Beachten Sie, dass der Server (Uvicorn) diesen `root_path` für nichts anderes außer die Weitergabe an die Anwendung verwendet. +Beachten Sie, dass der Server (Uvicorn) diesen `root_path` für nichts anderes verwendet als für die Weitergabe an die Anwendung. -Aber wenn Sie mit Ihrem Browser auf http://127.0.0.1:8000/app gehen, sehen Sie die normale Antwort: +Aber wenn Sie mit Ihrem Browser auf http://127.0.0.1:8000/app gehen, sehen Sie die normale Response: ```JSON { @@ -144,17 +241,17 @@ Es wird also nicht erwartet, dass unter `http://127.0.0.1:8000/api/v1/app` darau Uvicorn erwartet, dass der Proxy unter `http://127.0.0.1:8000/app` auf Uvicorn zugreift, und dann liegt es in der Verantwortung des Proxys, das zusätzliche `/api/v1`-Präfix darüber hinzuzufügen. -## Über Proxys mit einem abgetrennten Pfadpräfix +## Über Proxys mit einem abgetrennten Pfadpräfix { #about-proxies-with-a-stripped-path-prefix } -Bedenken Sie, dass ein Proxy mit abgetrennten Pfadpräfix nur eine von vielen Konfigurationsmöglichkeiten ist. +Bedenken Sie, dass ein Proxy mit abgetrenntem Pfadpräfix nur eine von vielen Konfigurationsmöglichkeiten ist. Wahrscheinlich wird in vielen Fällen die Standardeinstellung sein, dass der Proxy kein abgetrenntes Pfadpräfix hat. -In einem solchen Fall (ohne ein abgetrenntes Pfadpräfix) würde der Proxy auf etwas wie `https://myawesomeapp.com` lauschen, und wenn der Browser dann zu `https://myawesomeapp.com/api/v1/` wechselt, und Ihr Server (z. B. Uvicorn) auf `http://127.0.0.1:8000` lauscht, würde der Proxy (ohne ein abgetrenntes Pfadpräfix) über denselben Pfad auf Uvicorn zugreifen: `http://127.0.0.1:8000/api/v1/app`. +In einem solchen Fall (ohne ein abgetrenntes Pfadpräfix) würde der Proxy auf etwas wie `https://myawesomeapp.com` lauschen, und wenn der Browser dann zu `https://myawesomeapp.com/api/v1/app` wechselt, und Ihr Server (z. B. Uvicorn) auf `http://127.0.0.1:8000` lauscht, würde der Proxy (ohne ein abgetrenntes Pfadpräfix) über denselben Pfad auf Uvicorn zugreifen: `http://127.0.0.1:8000/api/v1/app`. -## Lokal testen mit Traefik +## Lokal testen mit Traefik { #testing-locally-with-traefik } -Sie können das Experiment mit einem abgetrennten Pfadpräfix ganz einfach lokal ausführen, indem Sie Traefik verwenden. +Sie können das Experiment mit einem abgetrennten Pfadpräfix einfach lokal ausführen, indem Sie Traefik verwenden. Laden Sie Traefik herunter, es ist eine einzelne Binärdatei, Sie können die komprimierte Datei extrahieren und sie direkt vom Terminal aus ausführen. @@ -205,7 +302,7 @@ Erstellen Sie nun die andere Datei `routes.toml`: Diese Datei konfiguriert Traefik, das Pfadpräfix `/api/v1` zu verwenden. -Und dann leitet Traefik seine Anfragen an Ihren Uvicorn weiter, der unter `http://127.0.0.1:8000` läuft. +Und dann leitet Traefik seine Requests an Ihren Uvicorn weiter, der unter `http://127.0.0.1:8000` läuft. Starten Sie nun Traefik: @@ -224,14 +321,14 @@ Und jetzt starten Sie Ihre Anwendung mit Uvicorn, indem Sie die Option `--root-p
```console -$ uvicorn main:app --root-path /api/v1 +$ 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) ```
-### Die Responses betrachten +### Die Responses testen { #check-the-responses } Wenn Sie nun zur URL mit dem Port für Uvicorn gehen: http://127.0.0.1:8000/app, sehen Sie die normale Response: @@ -267,7 +364,7 @@ Und die von Uvicorn direkt bereitgestellte Version ohne Pfadpräfix (`http://127 Dies demonstriert, wie der Proxy (Traefik) das Pfadpräfix verwendet und wie der Server (Uvicorn) den `root_path` aus der Option `--root-path` verwendet. -### Es in der Dokumentationsoberfläche betrachten +### Es in der Dokumentationsoberfläche testen { #check-the-docs-ui } Jetzt folgt der spaßige Teil. ✨ @@ -287,7 +384,7 @@ Genau so, wie wir es wollten. ✔️ Dies liegt daran, dass FastAPI diesen `root_path` verwendet, um den Default-`server` in OpenAPI mit der von `root_path` bereitgestellten URL zu erstellen. -## Zusätzliche Server +## Zusätzliche Server { #additional-servers } /// warning | Achtung @@ -297,7 +394,7 @@ Dies ist ein fortgeschrittener Anwendungsfall. Überspringen Sie das gerne. Standardmäßig erstellt **FastAPI** einen `server` im OpenAPI-Schema mit der URL für den `root_path`. -Sie können aber auch andere alternative `server` bereitstellen, beispielsweise wenn Sie möchten, dass *dieselbe* Dokumentationsoberfläche mit einer Staging- und Produktionsumgebung interagiert. +Sie können aber auch andere alternative `servers` bereitstellen, beispielsweise wenn Sie möchten, dass *dieselbe* Dokumentationsoberfläche mit einer Staging- und Produktionsumgebung interagiert. Wenn Sie eine benutzerdefinierte Liste von Servern (`servers`) übergeben und es einen `root_path` gibt (da Ihre API hinter einem Proxy läuft), fügt **FastAPI** einen „Server“ mit diesem `root_path` am Anfang der Liste ein. @@ -346,7 +443,7 @@ Die Dokumentationsoberfläche interagiert mit dem von Ihnen ausgewählten Server /// -### Den automatischen Server von `root_path` deaktivieren +### Den automatischen Server von `root_path` deaktivieren { #disable-automatic-server-from-root-path } Wenn Sie nicht möchten, dass **FastAPI** einen automatischen Server inkludiert, welcher `root_path` verwendet, können Sie den Parameter `root_path_in_servers=False` verwenden: @@ -354,7 +451,7 @@ Wenn Sie nicht möchten, dass **FastAPI** einen automatischen Server inkludiert, Dann wird er nicht in das OpenAPI-Schema aufgenommen. -## Mounten einer Unteranwendung +## Mounten einer Unteranwendung { #mounting-a-sub-application } Wenn Sie gleichzeitig eine Unteranwendung mounten (wie beschrieben in [Unteranwendungen – Mounts](sub-applications.md){.internal-link target=_blank}) und einen Proxy mit `root_path` verwenden wollen, können Sie das normal tun, wie Sie es erwarten würden. diff --git a/docs/de/docs/advanced/custom-response.md b/docs/de/docs/advanced/custom-response.md index 43cb55e04..8714086e5 100644 --- a/docs/de/docs/advanced/custom-response.md +++ b/docs/de/docs/advanced/custom-response.md @@ -1,12 +1,12 @@ -# Benutzerdefinierte Response – HTML, Stream, Datei, andere +# Benutzerdefinierte Response – HTML, Stream, Datei, andere { #custom-response-html-stream-file-others } -Standardmäßig gibt **FastAPI** die Responses mittels `JSONResponse` zurück. +Standardmäßig gibt **FastAPI** die Responses mittels `JSONResponse` zurück. -Sie können das überschreiben, indem Sie direkt eine `Response` zurückgeben, wie in [Eine Response direkt zurückgeben](response-directly.md){.internal-link target=_blank} gezeigt. +Sie können dies überschreiben, indem Sie direkt eine `Response` zurückgeben, wie in [Eine Response direkt zurückgeben](response-directly.md){.internal-link target=_blank} gezeigt. -Wenn Sie jedoch direkt eine `Response` zurückgeben, werden die Daten nicht automatisch konvertiert und die Dokumentation wird nicht automatisch generiert (zum Beispiel wird der spezifische „Medientyp“, der im HTTP-Header `Content-Type` angegeben ist, nicht Teil der generierten OpenAPI). +Wenn Sie jedoch direkt eine `Response` (oder eine Unterklasse wie `JSONResponse`) zurückgeben, werden die Daten nicht automatisch konvertiert (selbst wenn Sie ein `response_model` deklariert haben), und die Dokumentation wird nicht automatisch generiert (zum Beispiel wird der spezifische „Medientyp“, der im HTTP-Header `Content-Type` angegeben ist, nicht Teil der generierten OpenAPI). -Sie können aber auch die `Response`, die Sie verwenden möchten, im *Pfadoperation-Dekorator* deklarieren. +Sie können jedoch auch die `Response`, die Sie verwenden möchten (z. B. jede `Response`-Unterklasse), im *Pfadoperation-Dekorator* mit dem `response_class`-Parameter deklarieren. Der Inhalt, den Sie von Ihrer *Pfadoperation-Funktion* zurückgeben, wird in diese `Response` eingefügt. @@ -18,13 +18,13 @@ Wenn Sie eine Response-Klasse ohne Medientyp verwenden, erwartet FastAPI, dass I /// -## `ORJSONResponse` verwenden +## `ORJSONResponse` verwenden { #use-orjsonresponse } -Um beispielsweise noch etwas Leistung herauszuholen, können Sie `orjson` installieren und verwenden, und die Response als `ORJSONResponse` deklarieren. +Um beispielsweise noch etwas Leistung herauszuholen, können Sie `orjson` installieren und die Response als `ORJSONResponse` setzen. -Importieren Sie die `Response`-Klasse (-Unterklasse), die Sie verwenden möchten, und deklarieren Sie sie im *Pfadoperation-Dekorator*. +Importieren Sie die `Response`-Klasse (Unterklasse), die Sie verwenden möchten, und deklarieren Sie sie im *Pfadoperation-Dekorator*. -Bei umfangreichen Responses ist die direkte Rückgabe einer `Response` viel schneller als ein Dictionary zurückzugeben. +Bei umfangreichen Responses ist die direkte Rückgabe einer `Response` wesentlich schneller als ein Dictionary zurückzugeben. Das liegt daran, dass FastAPI standardmäßig jedes enthaltene Element überprüft und sicherstellt, dass es als JSON serialisierbar ist, und zwar unter Verwendung desselben [JSON-kompatiblen Encoders](../tutorial/encoder.md){.internal-link target=_blank}, der im Tutorial erläutert wurde. Dadurch können Sie **beliebige Objekte** zurückgeben, zum Beispiel Datenbankmodelle. @@ -32,7 +32,7 @@ Wenn Sie jedoch sicher sind, dass der von Ihnen zurückgegebene Inhalt **mit JSO {* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *} -/// info +/// info | Info Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren. @@ -44,11 +44,11 @@ Und er wird als solcher in OpenAPI dokumentiert. /// tip | Tipp -Die `ORJSONResponse` ist derzeit nur in FastAPI verfügbar, nicht in Starlette. +Die `ORJSONResponse` ist nur in FastAPI verfügbar, nicht in Starlette. /// -## HTML-Response +## HTML-Response { #html-response } Um eine Response mit HTML direkt von **FastAPI** zurückzugeben, verwenden Sie `HTMLResponse`. @@ -57,7 +57,7 @@ Um eine Response mit HTML direkt von **FastAPI** zurückzugeben, verwenden Sie ` {* ../../docs_src/custom_response/tutorial002.py hl[2,7] *} -/// info +/// info | Info Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren. @@ -67,7 +67,7 @@ Und er wird als solcher in OpenAPI dokumentiert. /// -### Eine `Response` zurückgeben +### Eine `Response` zurückgeben { #return-a-response } Wie in [Eine Response direkt zurückgeben](response-directly.md){.internal-link target=_blank} gezeigt, können Sie die Response auch direkt in Ihrer *Pfadoperation* überschreiben, indem Sie diese zurückgeben. @@ -81,19 +81,19 @@ Eine `Response`, die direkt von Ihrer *Pfadoperation-Funktion* zurückgegeben wi /// -/// info +/// info | Info Natürlich stammen der eigentliche `Content-Type`-Header, der Statuscode, usw., aus dem `Response`-Objekt, das Sie zurückgegeben haben. /// -### In OpenAPI dokumentieren und `Response` überschreiben +### In OpenAPI dokumentieren und `Response` überschreiben { #document-in-openapi-and-override-response } Wenn Sie die Response innerhalb der Funktion überschreiben und gleichzeitig den „Medientyp“ in OpenAPI dokumentieren möchten, können Sie den `response_class`-Parameter verwenden UND ein `Response`-Objekt zurückgeben. -Die `response_class` wird dann nur zur Dokumentation der OpenAPI-Pfadoperation* verwendet, Ihre `Response` wird jedoch unverändert verwendet. +Die `response_class` wird dann nur zur Dokumentation der OpenAPI-*Pfadoperation* verwendet, Ihre `Response` wird jedoch unverändert verwendet. -#### Eine `HTMLResponse` direkt zurückgeben +#### Eine `HTMLResponse` direkt zurückgeben { #return-an-htmlresponse-directly } Es könnte zum Beispiel so etwas sein: @@ -107,7 +107,7 @@ Aber da Sie die `HTMLResponse` auch in der `response_class` übergeben haben, we -## Verfügbare Responses +## Verfügbare Responses { #available-responses } Hier sind einige der verfügbaren Responses. @@ -121,7 +121,7 @@ Sie können auch `from starlette.responses import HTMLResponse` verwenden. /// -### `Response` +### `Response` { #response } Die Hauptklasse `Response`, alle anderen Responses erben von ihr. @@ -138,30 +138,42 @@ FastAPI (eigentlich Starlette) fügt automatisch einen Content-Length-Header ein {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} -### `HTMLResponse` +### `HTMLResponse` { #htmlresponse } Nimmt Text oder Bytes entgegen und gibt eine HTML-Response zurück, wie Sie oben gelesen haben. -### `PlainTextResponse` +### `PlainTextResponse` { #plaintextresponse } Nimmt Text oder Bytes entgegen und gibt eine Plain-Text-Response zurück. {* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *} -### `JSONResponse` +### `JSONResponse` { #jsonresponse } Nimmt einige Daten entgegen und gibt eine `application/json`-codierte Response zurück. Dies ist die Standard-Response, die in **FastAPI** verwendet wird, wie Sie oben gelesen haben. -### `ORJSONResponse` +### `ORJSONResponse` { #orjsonresponse } Eine schnelle alternative JSON-Response mit `orjson`, wie Sie oben gelesen haben. -### `UJSONResponse` +/// info | Info + +Dazu muss `orjson` installiert werden, z. B. mit `pip install orjson`. + +/// + +### `UJSONResponse` { #ujsonresponse } Eine alternative JSON-Response mit `ujson`. +/// info | Info + +Dazu muss `ujson` installiert werden, z. B. mit `pip install ujson`. + +/// + /// warning | Achtung `ujson` ist bei der Behandlung einiger Sonderfälle weniger sorgfältig als Pythons eingebaute Implementierung. @@ -176,7 +188,7 @@ Möglicherweise ist `ORJSONResponse` eine schnellere Alternative. /// -### `RedirectResponse` +### `RedirectResponse` { #redirectresponse } Gibt eine HTTP-Weiterleitung (HTTP-Redirect) zurück. Verwendet standardmäßig den Statuscode 307 – Temporäre Weiterleitung (Temporary Redirect). @@ -188,7 +200,6 @@ Sie können eine `RedirectResponse` direkt zurückgeben: Oder Sie können sie im Parameter `response_class` verwenden: - {* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *} Wenn Sie das tun, können Sie die URL direkt von Ihrer *Pfadoperation*-Funktion zurückgeben. @@ -201,26 +212,24 @@ Sie können den Parameter `status_code` auch in Kombination mit dem Parameter `r {* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *} -### `StreamingResponse` +### `StreamingResponse` { #streamingresponse } Nimmt einen asynchronen Generator oder einen normalen Generator/Iterator und streamt den Responsebody. {* ../../docs_src/custom_response/tutorial007.py hl[2,14] *} -#### Verwendung von `StreamingResponse` mit dateiähnlichen Objekten +#### Verwendung von `StreamingResponse` mit dateiartigen Objekten { #using-streamingresponse-with-file-like-objects } -Wenn Sie ein dateiähnliches (file-like) Objekt haben (z. B. das von `open()` zurückgegebene Objekt), können Sie eine Generatorfunktion erstellen, um über dieses dateiähnliche Objekt zu iterieren. +Wenn Sie ein dateiartiges (file-like) Objekt haben (z. B. das von `open()` zurückgegebene Objekt), können Sie eine Generatorfunktion erstellen, um über dieses dateiartige Objekt zu iterieren. Auf diese Weise müssen Sie nicht alles zuerst in den Arbeitsspeicher lesen und können diese Generatorfunktion an `StreamingResponse` übergeben und zurückgeben. Das umfasst viele Bibliotheken zur Interaktion mit Cloud-Speicher, Videoverarbeitung und anderen. -```{ .python .annotate hl_lines="2 10-12 14" } -{!../../docs_src/custom_response/tutorial008.py!} -``` +{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *} 1. Das ist die Generatorfunktion. Es handelt sich um eine „Generatorfunktion“, da sie `yield`-Anweisungen enthält. -2. Durch die Verwendung eines `with`-Blocks stellen wir sicher, dass das dateiähnliche Objekt geschlossen wird, nachdem die Generatorfunktion fertig ist. Also, nachdem sie mit dem Senden der Response fertig ist. +2. Durch die Verwendung eines `with`-Blocks stellen wir sicher, dass das dateiartige Objekt geschlossen wird, nachdem die Generatorfunktion fertig ist. Also, nachdem sie mit dem Senden der Response fertig ist. 3. Dieses `yield from` weist die Funktion an, über das Ding namens `file_like` zu iterieren. Und dann für jeden iterierten Teil, diesen Teil so zurückzugeben, als wenn er aus dieser Generatorfunktion (`iterfile`) stammen würde. Es handelt sich also hier um eine Generatorfunktion, die die „generierende“ Arbeit intern auf etwas anderes überträgt. @@ -233,7 +242,7 @@ Beachten Sie, dass wir, da wir Standard-`open()` verwenden, welches `async` und /// -### `FileResponse` +### `FileResponse` { #fileresponse } Streamt eine Datei asynchron als Response. @@ -254,7 +263,7 @@ Sie können auch den Parameter `response_class` verwenden: In diesem Fall können Sie den Dateipfad direkt von Ihrer *Pfadoperation*-Funktion zurückgeben. -## Benutzerdefinierte Response-Klasse +## Benutzerdefinierte Response-Klasse { #custom-response-class } Sie können Ihre eigene benutzerdefinierte Response-Klasse erstellen, die von `Response` erbt und diese verwendet. @@ -282,7 +291,7 @@ Statt: Natürlich werden Sie wahrscheinlich viel bessere Möglichkeiten finden, Vorteil daraus zu ziehen, als JSON zu formatieren. 😉 -## Standard-Response-Klasse +## Standard-Response-Klasse { #default-response-class } Beim Erstellen einer **FastAPI**-Klasseninstanz oder eines `APIRouter`s können Sie angeben, welche Response-Klasse standardmäßig verwendet werden soll. @@ -298,6 +307,6 @@ Sie können dennoch weiterhin `response_class` in *Pfadoperationen* überschreib /// -## Zusätzliche Dokumentation +## Zusätzliche Dokumentation { #additional-documentation } Sie können auch den Medientyp und viele andere Details in OpenAPI mit `responses` deklarieren: [Zusätzliche Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/de/docs/advanced/dataclasses.md b/docs/de/docs/advanced/dataclasses.md index 8e537c639..12ea8e9ec 100644 --- a/docs/de/docs/advanced/dataclasses.md +++ b/docs/de/docs/advanced/dataclasses.md @@ -1,24 +1,24 @@ -# Verwendung von Datenklassen +# Verwendung von Datenklassen { #using-dataclasses } -FastAPI basiert auf **Pydantic** und ich habe Ihnen gezeigt, wie Sie Pydantic-Modelle verwenden können, um Requests und Responses zu deklarieren. +FastAPI basiert auf **Pydantic**, und ich habe Ihnen gezeigt, wie Sie Pydantic-Modelle verwenden können, um Requests und Responses zu deklarieren. Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von `dataclasses`: {* ../../docs_src/dataclasses/tutorial001.py hl[1,7:12,19:20] *} -Das ist dank **Pydantic** ebenfalls möglich, da es `dataclasses` intern unterstützt. +Das ist dank **Pydantic** ebenfalls möglich, da es `dataclasses` intern unterstützt. -Auch wenn im obige Code Pydantic nicht explizit vorkommt, verwendet FastAPI Pydantic, um diese Standard-Datenklassen in Pydantics eigene Variante von Datenklassen zu konvertieren. +Auch wenn im obigen Code Pydantic nicht explizit vorkommt, verwendet FastAPI Pydantic, um diese Standard-Datenklassen in Pydantics eigene Variante von Datenklassen zu konvertieren. Und natürlich wird das gleiche unterstützt: -* Validierung der Daten -* Serialisierung der Daten -* Dokumentation der Daten, usw. +* Datenvalidierung +* Datenserialisierung +* Datendokumentation, usw. Das funktioniert genauso wie mit Pydantic-Modellen. Und tatsächlich wird es unter der Haube mittels Pydantic auf die gleiche Weise bewerkstelligt. -/// info +/// info | Info Bedenken Sie, dass Datenklassen nicht alles können, was Pydantic-Modelle können. @@ -28,7 +28,7 @@ Wenn Sie jedoch eine Menge Datenklassen herumliegen haben, ist dies ein guter Tr /// -## Datenklassen als `response_model` +## Datenklassen in `response_model` { #dataclasses-in-response-model } Sie können `dataclasses` auch im Parameter `response_model` verwenden: @@ -40,7 +40,7 @@ Auf diese Weise wird deren Schema in der Benutzeroberfläche der API-Dokumentati -## Datenklassen in verschachtelten Datenstrukturen +## Datenklassen in verschachtelten Datenstrukturen { #dataclasses-in-nested-data-structures } Sie können `dataclasses` auch mit anderen Typannotationen kombinieren, um verschachtelte Datenstrukturen zu erstellen. @@ -62,7 +62,7 @@ In diesem Fall können Sie einfach die Standard-`dataclasses` durch `pydantic.da In diesem Fall handelt es sich um eine Liste von `Item`-Datenklassen. -6. Hier geben wir ein Dictionary zurück, das `items` enthält, welches eine Liste von Datenklassen ist. +6. Hier geben wir ein Dictionary zurück, das `items` enthält, welches eine Liste von Datenklassen ist. FastAPI ist weiterhin in der Lage, die Daten nach JSON zu serialisieren. @@ -74,7 +74,7 @@ In diesem Fall können Sie einfach die Standard-`dataclasses` durch `pydantic.da Wie immer können Sie in FastAPI `def` und `async def` beliebig kombinieren. - Wenn Sie eine Auffrischung darüber benötigen, wann welche Anwendung sinnvoll ist, lesen Sie den Abschnitt „In Eile?“ in der Dokumentation zu [`async` und `await`](../async.md#in-eile){.internal-link target=_blank}. + Wenn Sie eine Auffrischung darüber benötigen, wann welche Anwendung sinnvoll ist, lesen Sie den Abschnitt „In Eile?“ in der Dokumentation zu [`async` und `await`](../async.md#in-a-hurry){.internal-link target=_blank}. 9. Diese *Pfadoperation-Funktion* gibt keine Datenklassen zurück (obwohl dies möglich wäre), sondern eine Liste von Dictionarys mit internen Daten. @@ -84,12 +84,12 @@ Sie können `dataclasses` mit anderen Typannotationen auf vielfältige Weise kom Weitere Einzelheiten finden Sie in den Bemerkungen im Quellcode oben. -## Mehr erfahren +## Mehr erfahren { #learn-more } Sie können `dataclasses` auch mit anderen Pydantic-Modellen kombinieren, von ihnen erben, sie in Ihre eigenen Modelle einbinden, usw. -Weitere Informationen finden Sie in der Pydantic-Dokumentation zu Datenklassen. +Weitere Informationen finden Sie in der Pydantic-Dokumentation zu Datenklassen. -## Version +## Version { #version } Dies ist verfügbar seit FastAPI-Version `0.67.0`. 🔖 diff --git a/docs/de/docs/advanced/events.md b/docs/de/docs/advanced/events.md index 65fc9e484..2ceef1190 100644 --- a/docs/de/docs/advanced/events.md +++ b/docs/de/docs/advanced/events.md @@ -1,14 +1,14 @@ -# Lifespan-Events +# Lifespan-Events { #lifespan-events } -Sie können Logik (Code) definieren, die ausgeführt werden soll, bevor die Anwendung **hochfährt**. Dies bedeutet, dass dieser Code **einmal** ausgeführt wird, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**. +Sie können Logik (Code) definieren, die ausgeführt werden soll, bevor die Anwendung **hochfährt**. Dies bedeutet, dass dieser Code **einmal** ausgeführt wird, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**. Auf die gleiche Weise können Sie Logik (Code) definieren, die ausgeführt werden soll, wenn die Anwendung **heruntergefahren** wird. In diesem Fall wird dieser Code **einmal** ausgeführt, **nachdem** möglicherweise **viele Requests** bearbeitet wurden. -Da dieser Code ausgeführt wird, bevor die Anwendung **beginnt**, Requests entgegenzunehmen, und unmittelbar, nachdem sie die Bearbeitung von Requests **abgeschlossen hat**, deckt er die gesamte **Lebensdauer – „Lifespan“** – der Anwendung ab (das Wort „Lifespan“ wird gleich wichtig sein 😉). +Da dieser Code ausgeführt wird, bevor die Anwendung **beginnt**, Requests entgegenzunehmen, und unmittelbar, nachdem sie die Bearbeitung von Requests **abgeschlossen hat**, deckt er den gesamten Anwendungs-**Lifespan** ab (das Wort „Lifespan“ wird gleich wichtig sein 😉). -Dies kann sehr nützlich sein, um **Ressourcen** einzurichten, die Sie in der gesamten Anwendung verwenden wollen und die von Requests **gemeinsam genutzt** werden und/oder die Sie anschließend **aufräumen** müssen. Zum Beispiel ein Pool von Datenbankverbindungen oder das Laden eines gemeinsam genutzten Modells für maschinelles Lernen. +Dies kann sehr nützlich sein, um **Ressourcen** einzurichten, die Sie in der gesamten App verwenden wollen und die von Requests **gemeinsam genutzt** werden und/oder die Sie anschließend **aufräumen** müssen. Zum Beispiel ein Pool von Datenbankverbindungen oder das Laden eines gemeinsam genutzten Modells für maschinelles Lernen. -## Anwendungsfall +## Anwendungsfall { #use-case } Beginnen wir mit einem Beispiel-**Anwendungsfall** und schauen uns dann an, wie wir ihn mit dieser Methode implementieren können. @@ -22,9 +22,9 @@ Sie könnten das auf der obersten Ebene des Moduls/der Datei machen, aber das w Das wollen wir besser machen: Laden wir das Modell, bevor die Requests bearbeitet werden, aber unmittelbar bevor die Anwendung beginnt, Requests zu empfangen, und nicht, während der Code geladen wird. -## Lifespan +## Lifespan { #lifespan } -Sie können diese Logik beim *Hochfahren* und *Herunterfahren* mithilfe des `lifespan`-Parameters der `FastAPI`-App und eines „Kontextmanagers“ definieren (ich zeige Ihnen gleich, was das ist). +Sie können diese Logik beim *Startup* und *Shutdown* mithilfe des `lifespan`-Parameters der `FastAPI`-App und eines „Kontextmanagers“ definieren (ich zeige Ihnen gleich, was das ist). Beginnen wir mit einem Beispiel und sehen es uns dann im Detail an. @@ -32,19 +32,19 @@ Wir erstellen eine asynchrone Funktion `lifespan()` mit `yield` wie folgt: {* ../../docs_src/events/tutorial003.py hl[16,19] *} -Hier simulieren wir das langsame *Hochfahren*, das Laden des Modells, indem wir die (Fake-)Modellfunktion vor dem `yield` in das Dictionary mit Modellen für maschinelles Lernen einfügen. Dieser Code wird ausgeführt, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**, während des *Hochfahrens*. +Hier simulieren wir den langsamen *Startup*, das Laden des Modells, indem wir die (Fake-)Modellfunktion vor dem `yield` in das Dictionary mit Modellen für maschinelles Lernen einfügen. Dieser Code wird ausgeführt, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**, während des *Startups*. -Und dann, direkt nach dem `yield`, entladen wir das Modell. Dieser Code wird unmittelbar vor dem *Herunterfahren* ausgeführt, **nachdem** die Anwendung **die Bearbeitung von Requests abgeschlossen hat**. Dadurch könnten beispielsweise Ressourcen wie Arbeitsspeicher oder eine GPU freigegeben werden. +Und dann, direkt nach dem `yield`, entladen wir das Modell. Dieser Code wird ausgeführt, **nachdem** die Anwendung **die Bearbeitung von Requests abgeschlossen hat**, direkt vor dem *Shutdown*. Dadurch könnten beispielsweise Ressourcen wie Arbeitsspeicher oder eine GPU freigegeben werden. /// tip | Tipp -Das *Herunterfahren* würde erfolgen, wenn Sie die Anwendung **stoppen**. +Das `shutdown` würde erfolgen, wenn Sie die Anwendung **stoppen**. Möglicherweise müssen Sie eine neue Version starten, oder Sie haben es einfach satt, sie auszuführen. 🤷 /// -### Lifespan-Funktion +### Lifespan-Funktion { #lifespan-function } Das Erste, was auffällt, ist, dass wir eine asynchrone Funktion mit `yield` definieren. Das ist sehr ähnlich zu Abhängigkeiten mit `yield`. @@ -54,7 +54,7 @@ Der erste Teil der Funktion, vor dem `yield`, wird ausgeführt **bevor** die Anw Und der Teil nach `yield` wird ausgeführt, **nachdem** die Anwendung beendet ist. -### Asynchroner Kontextmanager +### Asynchroner Kontextmanager { #async-context-manager } Wie Sie sehen, ist die Funktion mit einem `@asynccontextmanager` versehen. @@ -84,23 +84,23 @@ Der Parameter `lifespan` der `FastAPI`-App benötigt einen **asynchronen Kontext {* ../../docs_src/events/tutorial003.py hl[22] *} -## Alternative Events (deprecated) +## Alternative Events (deprecatet) { #alternative-events-deprecated } /// warning | Achtung -Der empfohlene Weg, das *Hochfahren* und *Herunterfahren* zu handhaben, ist die Verwendung des `lifespan`-Parameters der `FastAPI`-App, wie oben beschrieben. Wenn Sie einen `lifespan`-Parameter übergeben, werden die `startup`- und `shutdown`-Eventhandler nicht mehr aufgerufen. Es ist entweder alles `lifespan` oder alles Events, nicht beides. +Der empfohlene Weg, den *Startup* und *Shutdown* zu handhaben, ist die Verwendung des `lifespan`-Parameters der `FastAPI`-App, wie oben beschrieben. Wenn Sie einen `lifespan`-Parameter übergeben, werden die `startup`- und `shutdown`-Eventhandler nicht mehr aufgerufen. Es ist entweder alles `lifespan` oder alles Events, nicht beides. Sie können diesen Teil wahrscheinlich überspringen. /// -Es gibt eine alternative Möglichkeit, diese Logik zu definieren, sodass sie beim *Hochfahren* und beim *Herunterfahren* ausgeführt wird. +Es gibt eine alternative Möglichkeit, diese Logik zu definieren, sodass sie beim *Startup* und beim *Shutdown* ausgeführt wird. -Sie können Eventhandler (Funktionen) definieren, die ausgeführt werden sollen, bevor die Anwendung hochgefahren wird oder wenn die Anwendung heruntergefahren wird. +Sie können Eventhandler (Funktionen) definieren, die ausgeführt werden sollen, bevor die Anwendung hochgefahren wird oder wenn die Anwendung heruntergefahren wird. Diese Funktionen können mit `async def` oder normalem `def` deklariert werden. -### `startup`-Event +### `startup`-Event { #startup-event } Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `startup`: @@ -110,17 +110,17 @@ In diesem Fall initialisiert die Eventhandler-Funktion `startup` die „Datenban Sie können mehr als eine Eventhandler-Funktion hinzufügen. -Und Ihre Anwendung empfängt erst dann Anfragen, wenn alle `startup`-Eventhandler abgeschlossen sind. +Und Ihre Anwendung empfängt erst dann Requests, wenn alle `startup`-Eventhandler abgeschlossen sind. -### `shutdown`-Event +### `shutdown`-Event { #shutdown-event } -Um eine Funktion hinzuzufügen, die beim Herunterfahren der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `shutdown`: +Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `shutdown`: {* ../../docs_src/events/tutorial002.py hl[6] *} Hier schreibt die `shutdown`-Eventhandler-Funktion eine Textzeile `"Application shutdown"` in eine Datei `log.txt`. -/// info +/// info | Info In der Funktion `open()` bedeutet `mode="a"` „append“ („anhängen“), sodass die Zeile nach dem, was sich in dieser Datei befindet, hinzugefügt wird, ohne den vorherigen Inhalt zu überschreiben. @@ -138,21 +138,21 @@ Daher deklarieren wir die Eventhandler-Funktion mit Standard-`def` statt mit `as /// -### `startup` und `shutdown` zusammen +### `startup` und `shutdown` zusammen { #startup-and-shutdown-together } -Es besteht eine hohe Wahrscheinlichkeit, dass die Logik für Ihr *Hochfahren* und *Herunterfahren* miteinander verknüpft ist. Vielleicht möchten Sie etwas beginnen und es dann beenden, eine Ressource laden und sie dann freigeben usw. +Es besteht eine hohe Wahrscheinlichkeit, dass die Logik für Ihr *Startup* und *Shutdown* miteinander verknüpft ist. Vielleicht möchten Sie etwas beginnen und es dann beenden, eine Ressource laden und sie dann freigeben usw. Bei getrennten Funktionen, die keine gemeinsame Logik oder Variablen haben, ist dies schwieriger, da Sie Werte in globalen Variablen speichern oder ähnliche Tricks verwenden müssen. Aus diesem Grund wird jetzt empfohlen, stattdessen `lifespan` wie oben erläutert zu verwenden. -## Technische Details +## Technische Details { #technical-details } Nur ein technisches Detail für die neugierigen Nerds. 🤓 In der technischen ASGI-Spezifikation ist dies Teil des Lifespan Protokolls und definiert Events namens `startup` und `shutdown`. -/// info +/// info | Info Weitere Informationen zu Starlettes `lifespan`-Handlern finden Sie in Starlettes Lifespan-Dokumentation. @@ -160,6 +160,6 @@ Einschließlich, wie man Lifespan-Zustand handhabt, der in anderen Bereichen Ihr /// -## Unteranwendungen +## Unteranwendungen { #sub-applications } -🚨 Beachten Sie, dass diese Lifespan-Events (Hochfahren und Herunterfahren) nur für die Hauptanwendung ausgeführt werden, nicht für [Unteranwendungen – Mounts](sub-applications.md){.internal-link target=_blank}. +🚨 Beachten Sie, dass diese Lifespan-Events (Startup und Shutdown) nur für die Hauptanwendung ausgeführt werden, nicht für [Unteranwendungen – Mounts](sub-applications.md){.internal-link target=_blank}. diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md index f491d29af..d8836295b 100644 --- a/docs/de/docs/advanced/generate-clients.md +++ b/docs/de/docs/advanced/generate-clients.md @@ -1,121 +1,86 @@ -# Clients generieren +# SDKs generieren { #generating-sdks } -Da **FastAPI** auf der OpenAPI-Spezifikation basiert, erhalten Sie automatische Kompatibilität mit vielen Tools, einschließlich der automatischen API-Dokumentation (bereitgestellt von Swagger UI). +Da **FastAPI** auf der **OpenAPI**-Spezifikation basiert, können dessen APIs in einem standardisierten Format beschrieben werden, das viele Tools verstehen. -Ein besonderer Vorteil, der nicht unbedingt offensichtlich ist, besteht darin, dass Sie für Ihre API **Clients generieren** können (manchmal auch **SDKs** genannt), für viele verschiedene **Programmiersprachen**. +Dies vereinfacht es, aktuelle **Dokumentation** und Client-Bibliotheken (**SDKs**) in verschiedenen Sprachen zu generieren sowie **Test-** oder **Automatisierungs-Workflows**, die mit Ihrem Code synchron bleiben. -## OpenAPI-Client-Generatoren +In diesem Leitfaden erfahren Sie, wie Sie ein **TypeScript-SDK** für Ihr FastAPI-Backend generieren. -Es gibt viele Tools zum Generieren von Clients aus **OpenAPI**. +## Open Source SDK-Generatoren { #open-source-sdk-generators } -Ein gängiges Tool ist OpenAPI Generator. +Eine vielseitige Möglichkeit ist der OpenAPI Generator, der **viele Programmiersprachen** unterstützt und SDKs aus Ihrer OpenAPI-Spezifikation generieren kann. -Wenn Sie ein **Frontend** erstellen, ist openapi-ts eine sehr interessante Alternative. +Für **TypeScript-Clients** ist Hey API eine speziell entwickelte Lösung, die ein optimiertes Erlebnis für das TypeScript-Ökosystem bietet. -## Client- und SDK-Generatoren – Sponsor +Weitere SDK-Generatoren finden Sie auf OpenAPI.Tools. -Es gibt auch einige **vom Unternehmen entwickelte** Client- und SDK-Generatoren, die auf OpenAPI (FastAPI) basieren. In einigen Fällen können diese Ihnen **weitere Funktionalität** zusätzlich zu qualitativ hochwertigen generierten SDKs/Clients bieten. +/// tip | Tipp -Einige von diesen ✨ [**sponsern FastAPI**](../help-fastapi.md#den-autor-sponsern){.internal-link target=_blank} ✨, das gewährleistet die kontinuierliche und gesunde **Entwicklung** von FastAPI und seinem **Ökosystem**. +FastAPI generiert automatisch **OpenAPI 3.1**-Spezifikationen, daher muss jedes von Ihnen verwendete Tool diese Version unterstützen. -Und es zeigt deren wahres Engagement für FastAPI und seine **Community** (Sie), da diese Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie über ein **gutes und gesundes Framework** verfügen, FastAPI. 🙇 +/// -Beispielsweise könnten Sie Speakeasy ausprobieren. +## SDK-Generatoren von FastAPI-Sponsoren { #sdk-generators-from-fastapi-sponsors } -Es gibt auch mehrere andere Unternehmen, welche ähnliche Dienste anbieten und die Sie online suchen und finden können. 🤓 +Dieser Abschnitt hebt **venture-unterstützte** und **firmengestützte** Lösungen hervor, die von Unternehmen entwickelt werden, welche FastAPI sponsern. Diese Produkte bieten **zusätzliche Funktionen** und **Integrationen** zusätzlich zu hochwertig generierten SDKs. -## Einen TypeScript-Frontend-Client generieren +Durch das ✨ [**Sponsoring von FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ helfen diese Unternehmen sicherzustellen, dass das Framework und sein **Ökosystem** gesund und **nachhaltig** bleiben. + +Ihr Sponsoring zeigt auch ein starkes Engagement für die FastAPI-**Community** (Sie), was bedeutet, dass sie nicht nur einen **großartigen Service** bieten möchten, sondern auch ein **robustes und florierendes Framework**, FastAPI, unterstützen möchten. 🙇 + +Zum Beispiel könnten Sie ausprobieren: + +* Speakeasy +* Stainless +* liblab + +Einige dieser Lösungen sind möglicherweise auch Open Source oder bieten kostenlose Tarife an, sodass Sie diese ohne finanzielle Verpflichtung ausprobieren können. Andere kommerzielle SDK-Generatoren sind online verfügbar und können dort gefunden werden. 🤓 + +## Ein TypeScript-SDK erstellen { #create-a-typescript-sdk } Beginnen wir mit einer einfachen FastAPI-Anwendung: {* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *} -Beachten Sie, dass die *Pfadoperationen* die Modelle definieren, welche diese für die Request- und Response-Payload verwenden, indem sie die Modelle `Item` und `ResponseMessage` verwenden. +Beachten Sie, dass die *Pfadoperationen* die Modelle definieren, die sie für die Request- und Response-Payload verwenden, indem sie die Modelle `Item` und `ResponseMessage` verwenden. -### API-Dokumentation +### API-Dokumentation { #api-docs } -Wenn Sie zur API-Dokumentation gehen, werden Sie sehen, dass diese die **Schemas** für die Daten enthält, welche in Requests gesendet und in Responses empfangen werden: +Wenn Sie zu `/docs` gehen, sehen Sie, dass es die **Schemas** für die Daten enthält, die in Requests gesendet und in Responses empfangen werden: -Sie können diese Schemas sehen, da sie mit den Modellen in der Anwendung deklariert wurden. +Sie können diese Schemas sehen, da sie mit den Modellen in der App deklariert wurden. -Diese Informationen sind im **OpenAPI-Schema** der Anwendung verfügbar und werden dann in der API-Dokumentation angezeigt (von Swagger UI). +Diese Informationen sind im **OpenAPI-Schema** der Anwendung verfügbar und werden in der API-Dokumentation angezeigt. -Und dieselben Informationen aus den Modellen, die in OpenAPI enthalten sind, können zum **Generieren des Client-Codes** verwendet werden. +Diese Informationen aus den Modellen, die in OpenAPI enthalten sind, können verwendet werden, um **den Client-Code zu generieren**. -### Einen TypeScript-Client generieren +### Hey API { #hey-api } -Nachdem wir nun die Anwendung mit den Modellen haben, können wir den Client-Code für das Frontend generieren. +Sobald wir eine FastAPI-App mit den Modellen haben, können wir Hey API verwenden, um einen TypeScript-Client zu generieren. Der schnellste Weg das zu tun, ist über npx. -#### `openapi-ts` installieren - -Sie können `openapi-ts` in Ihrem Frontend-Code installieren mit: - -
- -```console -$ npm install @hey-api/openapi-ts --save-dev - ----> 100% +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ``` -
+Dies generiert ein TypeScript-SDK in `./src/client`. -#### Client-Code generieren +Sie können lernen, wie man `@hey-api/openapi-ts` installiert und über die erzeugte Ausgabe auf deren Website lesen. -Um den Client-Code zu generieren, können Sie das Kommandozeilentool `openapi-ts` verwenden, das soeben installiert wurde. +### Das SDK verwenden { #using-the-sdk } -Da es im lokalen Projekt installiert ist, könnten Sie diesen Befehl wahrscheinlich nicht direkt aufrufen, sondern würden ihn in Ihre Datei `package.json` einfügen. - -Diese könnte so aussehen: - -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} -``` - -Nachdem Sie das NPM-Skript `generate-client` dort stehen haben, können Sie es ausführen mit: - -
- -```console -$ npm run generate-client - -frontend-app@1.0.0 generate-client /home/user/code/frontend-app -> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios -``` - -
- -Dieser Befehl generiert Code in `./src/client` und verwendet intern `axios` (die Frontend-HTTP-Bibliothek). - -### Den Client-Code ausprobieren - -Jetzt können Sie den Client-Code importieren und verwenden. Er könnte wie folgt aussehen, beachten Sie, dass Sie automatische Codevervollständigung für die Methoden erhalten: +Jetzt können Sie den Client-Code importieren und verwenden. Er könnte wie folgt aussehen, beachten Sie, dass Sie eine automatische Vervollständigung für die Methoden erhalten: -Sie erhalten außerdem automatische Vervollständigung für die zu sendende Payload: +Sie werden auch eine automatische Vervollständigung für die zu sendende Payload erhalten: /// tip | Tipp -Beachten Sie die automatische Vervollständigung für `name` und `price`, welche in der FastAPI-Anwendung im `Item`-Modell definiert wurden. +Beachten Sie die automatische Vervollständigung für `name` und `price`, die in der FastAPI-Anwendung im `Item`-Modell definiert wurden. /// @@ -127,17 +92,17 @@ Das Response-Objekt hat auch automatische Vervollständigung: -## FastAPI-Anwendung mit Tags +## FastAPI-Anwendung mit Tags { #fastapi-app-with-tags } -In vielen Fällen wird Ihre FastAPI-Anwendung größer sein und Sie werden wahrscheinlich Tags verwenden, um verschiedene Gruppen von *Pfadoperationen* zu separieren. +In vielen Fällen wird Ihre FastAPI-App größer sein und Sie werden wahrscheinlich Tags verwenden, um verschiedene Gruppen von *Pfadoperationen* zu separieren. -Beispielsweise könnten Sie einen Abschnitt für **Items (Artikel)** und einen weiteren Abschnitt für **Users (Benutzer)** haben, und diese könnten durch Tags getrennt sein: +Zum Beispiel könnten Sie einen Abschnitt für **Items (Artikel)** und einen weiteren Abschnitt für **Users (Benutzer)** haben, und diese könnten durch Tags getrennt sein: {* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *} -### Einen TypeScript-Client mit Tags generieren +### Einen TypeScript-Client mit Tags generieren { #generate-a-typescript-client-with-tags } -Wenn Sie unter Verwendung von Tags einen Client für eine FastAPI-Anwendung generieren, wird normalerweise auch der Client-Code anhand der Tags getrennt. +Wenn Sie einen Client für eine FastAPI-App generieren, die Tags verwendet, wird normalerweise der Client-Code auch anhand der Tags getrennt. Auf diese Weise können Sie die Dinge für den Client-Code richtig ordnen und gruppieren: @@ -148,7 +113,7 @@ In diesem Fall haben Sie: * `ItemsService` * `UsersService` -### Client-Methodennamen +### Client-Methodennamen { #client-method-names } Im Moment sehen die generierten Methodennamen wie `createItemItemsPost` nicht sehr sauber aus: @@ -158,31 +123,31 @@ ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ... das liegt daran, dass der Client-Generator für jede *Pfadoperation* die OpenAPI-interne **Operation-ID** verwendet. -OpenAPI erfordert, dass jede Operation-ID innerhalb aller *Pfadoperationen* eindeutig ist. Daher verwendet FastAPI den **Funktionsnamen**, den **Pfad** und die **HTTP-Methode/-Operation**, um diese Operation-ID zu generieren. Denn so kann sichergestellt werden, dass die Operation-IDs eindeutig sind. +OpenAPI erfordert, dass jede Operation-ID innerhalb aller *Pfadoperationen* einzigartig ist. Daher verwendet FastAPI den **Funktionsnamen**, den **Pfad** und die **HTTP-Methode/-Operation**, um diese Operation-ID zu generieren. Denn so kann sichergestellt werden, dass die Operation-IDs einzigartig sind. -Aber ich zeige Ihnen als nächstes, wie Sie das verbessern können. 🤓 +Aber ich zeige Ihnen als Nächstes, wie Sie das verbessern können. 🤓 -## Benutzerdefinierte Operation-IDs und bessere Methodennamen +## Benutzerdefinierte Operation-IDs und bessere Methodennamen { #custom-operation-ids-and-better-method-names } Sie können die Art und Weise, wie diese Operation-IDs **generiert** werden, **ändern**, um sie einfacher zu machen und **einfachere Methodennamen** in den Clients zu haben. -In diesem Fall müssen Sie auf andere Weise sicherstellen, dass jede Operation-ID **eindeutig** ist. +In diesem Fall müssen Sie auf andere Weise sicherstellen, dass jede Operation-ID **einzigartig** ist. -Sie könnten beispielsweise sicherstellen, dass jede *Pfadoperation* einen Tag hat, und dann die Operation-ID basierend auf dem **Tag** und dem **Namen** der *Pfadoperation* (dem Funktionsnamen) generieren. +Zum Beispiel könnten Sie sicherstellen, dass jede *Pfadoperation* einen Tag hat, und dann die Operation-ID basierend auf dem **Tag** und dem *Pfadoperation*-**Namen** (dem Funktionsnamen) generieren. -### Funktion zum Generieren einer eindeutigen ID erstellen +### Eine benutzerdefinierte Funktion zur Erzeugung einer eindeutigen ID erstellen { #custom-generate-unique-id-function } -FastAPI verwendet eine **eindeutige ID** für jede *Pfadoperation*, diese wird für die **Operation-ID** und auch für die Namen aller benötigten benutzerdefinierten Modelle für Requests oder Responses verwendet. +FastAPI verwendet eine **eindeutige ID** für jede *Pfadoperation*, die für die **Operation-ID** und auch für die Namen aller benötigten benutzerdefinierten Modelle für Requests oder Responses verwendet wird. -Sie können diese Funktion anpassen. Sie nimmt eine `APIRoute` und gibt einen String zurück. +Sie können diese Funktion anpassen. Sie nimmt ein `APIRoute` und gibt einen String zurück. -Hier verwendet sie beispielsweise den ersten Tag (Sie werden wahrscheinlich nur einen Tag haben) und den Namen der *Pfadoperation* (den Funktionsnamen). +Hier verwendet sie beispielsweise den ersten Tag (Sie werden wahrscheinlich nur einen Tag haben) und den *Pfadoperation*-Namen (den Funktionsnamen). -Anschließend können Sie diese benutzerdefinierte Funktion als Parameter `generate_unique_id_function` an **FastAPI** übergeben: +Anschließend können Sie diese benutzerdefinierte Funktion als `generate_unique_id_function`-Parameter an **FastAPI** übergeben: {* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *} -### Einen TypeScript-Client mit benutzerdefinierten Operation-IDs generieren +### Einen TypeScript-Client mit benutzerdefinierten Operation-IDs generieren { #generate-a-typescript-client-with-custom-operation-ids } Wenn Sie nun den Client erneut generieren, werden Sie feststellen, dass er über die verbesserten Methodennamen verfügt: @@ -190,17 +155,17 @@ Wenn Sie nun den Client erneut generieren, werden Sie feststellen, dass er über Wie Sie sehen, haben die Methodennamen jetzt den Tag und dann den Funktionsnamen, aber keine Informationen aus dem URL-Pfad und der HTTP-Operation. -### Vorab-Modifikation der OpenAPI-Spezifikation für den Client-Generator +### Die OpenAPI-Spezifikation für den Client-Generator vorab modifizieren { #preprocess-the-openapi-specification-for-the-client-generator } -Der generierte Code enthält immer noch etwas **verdoppelte Information**. +Der generierte Code enthält immer noch einige **verdoppelte Informationen**. -Wir wissen bereits, dass diese Methode mit den **Items** zusammenhängt, da sich dieses Wort in `ItemsService` befindet (vom Tag übernommen), aber wir haben auch immer noch den Tagnamen im Methodennamen vorangestellt. 😕 +Wir wissen bereits, dass diese Methode mit den **Items** zusammenhängt, weil dieses Wort in `ItemsService` enthalten ist (vom Tag übernommen), aber wir haben den Tag-Namen dennoch im Methodennamen vorangestellt. 😕 -Wir werden das wahrscheinlich weiterhin für OpenAPI im Allgemeinen beibehalten wollen, da dadurch sichergestellt wird, dass die Operation-IDs **eindeutig** sind. +Wir werden das wahrscheinlich weiterhin für OpenAPI allgemein beibehalten wollen, da dadurch sichergestellt wird, dass die Operation-IDs **einzigartig** sind. Aber für den generierten Client könnten wir die OpenAPI-Operation-IDs direkt vor der Generierung der Clients **modifizieren**, um diese Methodennamen schöner und **sauberer** zu machen. -Wir könnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dann mit einem Skript wie dem folgenden **den vorangestellten Tag entfernen**: +Wir könnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dann mit einem Skript wie dem folgenden **den präfixierten Tag entfernen**: {* ../../docs_src/generate_clients/tutorial004.py *} @@ -214,44 +179,30 @@ Wir könnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dan Damit würden die Operation-IDs von Dingen wie `items-get_items` in `get_items` umbenannt, sodass der Client-Generator einfachere Methodennamen generieren kann. -### Einen TypeScript-Client mit der modifizierten OpenAPI generieren +### Einen TypeScript-Client mit der modifizierten OpenAPI generieren { #generate-a-typescript-client-with-the-preprocessed-openapi } -Da das Endergebnis nun in einer Datei `openapi.json` vorliegt, würden Sie die `package.json` ändern, um diese lokale Datei zu verwenden, zum Beispiel: +Da das Endergebnis nun in einer `openapi.json`-Datei vorliegt, müssen Sie Ihren Eingabeort aktualisieren: -```JSON hl_lines="7" -{ - "name": "frontend-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios" - }, - "author": "", - "license": "", - "devDependencies": { - "@hey-api/openapi-ts": "^0.27.38", - "typescript": "^4.6.2" - } -} +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client ``` -Nach der Generierung des neuen Clients hätten Sie nun **saubere Methodennamen** mit allen **Autovervollständigungen**, **Inline-Fehlerberichten**, usw.: +Nach der Generierung des neuen Clients haben Sie jetzt **saubere Methodennamen**, mit allen **Autovervollständigungen**, **Inline-Fehlerberichten**, usw.: -## Vorteile +## Vorteile { #benefits } -Wenn Sie die automatisch generierten Clients verwenden, erhalten Sie **automatische Codevervollständigung** für: +Wenn Sie die automatisch generierten Clients verwenden, erhalten Sie **Autovervollständigung** für: * Methoden. * Request-Payloads im Body, Query-Parameter, usw. * Response-Payloads. -Außerdem erhalten Sie für alles **Inline-Fehlerberichte**. +Sie erhalten auch **Inline-Fehlerberichte** für alles. -Und wann immer Sie den Backend-Code aktualisieren und das Frontend **neu generieren**, stehen alle neuen *Pfadoperationen* als Methoden zur Verfügung, die alten werden entfernt und alle anderen Änderungen werden im generierten Code reflektiert. 🤓 +Und wann immer Sie den Backend-Code aktualisieren und **das Frontend neu generieren**, stehen alle neuen *Pfadoperationen* als Methoden zur Verfügung, die alten werden entfernt und alle anderen Änderungen werden im generierten Code reflektiert. 🤓 -Das bedeutet auch, dass, wenn sich etwas ändert, dies automatisch im Client-Code **reflektiert** wird. Und wenn Sie den Client **erstellen**, kommt es zu einer Fehlermeldung, wenn die verwendeten Daten **nicht übereinstimmen**. +Das bedeutet auch, dass, wenn sich etwas ändert, dies automatisch im Client-Code **reflektiert** wird. Und wenn Sie den Client **erstellen**, wird eine Fehlermeldung ausgegeben, wenn die verwendeten Daten **nicht übereinstimmen**. -Sie würden also sehr früh im Entwicklungszyklus **viele Fehler erkennen**, anstatt darauf warten zu müssen, dass die Fehler Ihren Endbenutzern in der Produktion angezeigt werden, und dann zu versuchen, zu debuggen, wo das Problem liegt. ✨ +Sie würden also **viele Fehler sehr früh** im Entwicklungszyklus erkennen, anstatt darauf warten zu müssen, dass die Fehler Ihren Endbenutzern in der Produktion angezeigt werden, und dann zu versuchen, zu debuggen, wo das Problem liegt. ✨ diff --git a/docs/de/docs/advanced/index.md b/docs/de/docs/advanced/index.md index d93cd5fe8..98fc7bc2f 100644 --- a/docs/de/docs/advanced/index.md +++ b/docs/de/docs/advanced/index.md @@ -1,6 +1,6 @@ -# Handbuch für fortgeschrittene Benutzer +# Handbuch für fortgeschrittene Benutzer { #advanced-user-guide } -## Zusatzfunktionen +## Zusatzfunktionen { #additional-features } Das Haupt-[Tutorial – Benutzerhandbuch](../tutorial/index.md){.internal-link target=_blank} sollte ausreichen, um Ihnen einen Überblick über alle Hauptfunktionen von **FastAPI** zu geben. @@ -14,23 +14,8 @@ Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon l /// -## Lesen Sie zuerst das Tutorial +## Das Tutorial zuerst lesen { #read-the-tutorial-first } Sie können immer noch die meisten Funktionen in **FastAPI** mit den Kenntnissen aus dem Haupt-[Tutorial – Benutzerhandbuch](../tutorial/index.md){.internal-link target=_blank} nutzen. -Und in den nächsten Abschnitten wird davon ausgegangen, dass Sie es bereits gelesen haben und dass Sie diese Haupt-Ideen kennen. - -## Externe Kurse - -Obwohl das [Tutorial – Benutzerhandbuch](../tutorial/index.md){.internal-link target=_blank} und dieses **Handbuch für fortgeschrittene Benutzer** als geführtes Tutorial (wie ein Buch) geschrieben sind und für Sie ausreichen sollten, um **FastAPI zu lernen**, möchten Sie sie vielleicht durch zusätzliche Kurse ergänzen. - -Oder Sie belegen einfach lieber andere Kurse, weil diese besser zu Ihrem Lernstil passen. - -Einige Kursanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#den-autor-sponsern){.internal-link target=_blank} ✨, dies gewährleistet die kontinuierliche und gesunde **Entwicklung** von FastAPI und seinem **Ökosystem**. - -Und es zeigt deren wahres Engagement für FastAPI und seine **Gemeinschaft** (Sie), da diese Ihnen nicht nur eine **gute Lernerfahrung** bieten möchten, sondern auch sicherstellen möchten, dass Sie über ein **gutes und gesundes Framework verfügen **, FastAPI. 🙇 - -Vielleicht möchten Sie ihre Kurse ausprobieren: - -* Talk Python Training -* Test-Driven Development +Und die nächsten Abschnitte setzen voraus, dass Sie es bereits gelesen haben und dass Sie diese Hauptideen kennen. diff --git a/docs/de/docs/advanced/middleware.md b/docs/de/docs/advanced/middleware.md index 17b339788..0a2a39699 100644 --- a/docs/de/docs/advanced/middleware.md +++ b/docs/de/docs/advanced/middleware.md @@ -1,4 +1,4 @@ -# Fortgeschrittene Middleware +# Fortgeschrittene Middleware { #advanced-middleware } Im Haupttutorial haben Sie gelesen, wie Sie Ihrer Anwendung [benutzerdefinierte Middleware](../tutorial/middleware.md){.internal-link target=_blank} hinzufügen können. @@ -6,15 +6,15 @@ Und dann auch, wie man [CORS mittels der `CORSMiddleware`](../tutorial/cors.md){ In diesem Abschnitt werden wir sehen, wie man andere Middlewares verwendet. -## ASGI-Middleware hinzufügen +## ASGI-Middleware hinzufügen { #adding-asgi-middlewares } -Da **FastAPI** auf Starlette basiert und die ASGI-Spezifikation implementiert, können Sie jede ASGI-Middleware verwenden. +Da **FastAPI** auf Starlette basiert und die ASGI-Spezifikation implementiert, können Sie jede ASGI-Middleware verwenden. Eine Middleware muss nicht speziell für FastAPI oder Starlette gemacht sein, um zu funktionieren, solange sie der ASGI-Spezifikation genügt. Im Allgemeinen handelt es sich bei ASGI-Middleware um Klassen, die als erstes Argument eine ASGI-Anwendung erwarten. -In der Dokumentation für ASGI-Middlewares von Drittanbietern wird Ihnen wahrscheinlich gesagt, etwa Folgendes zu tun: +In der Dokumentation für ASGI-Middlewares von Drittanbietern wird Ihnen wahrscheinlich gesagt, dass Sie etwa Folgendes tun sollen: ```Python from unicorn import UnicornMiddleware @@ -39,7 +39,7 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow") `app.add_middleware()` empfängt eine Middleware-Klasse als erstes Argument und dann alle weiteren Argumente, die an die Middleware übergeben werden sollen. -## Integrierte Middleware +## Integrierte Middleware { #integrated-middlewares } **FastAPI** enthält mehrere Middlewares für gängige Anwendungsfälle. Wir werden als Nächstes sehen, wie man sie verwendet. @@ -51,15 +51,15 @@ Für die nächsten Beispiele könnten Sie auch `from starlette.middleware.someth /// -## `HTTPSRedirectMiddleware` +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } -Erzwingt, dass alle eingehenden Requests entweder `https` oder `wss` sein müssen. +Erzwingt, dass alle eingehenden Requests entweder `https` oder `wss` sein müssen. Alle eingehenden Requests an `http` oder `ws` werden stattdessen an das sichere Schema umgeleitet. {* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *} -## `TrustedHostMiddleware` +## `TrustedHostMiddleware` { #trustedhostmiddleware } Erzwingt, dass alle eingehenden Requests einen korrekt gesetzten `Host`-Header haben, um sich vor HTTP-Host-Header-Angriffen zu schützen. @@ -68,10 +68,11 @@ Erzwingt, dass alle eingehenden Requests einen korrekt gesetzten `Host`-Header h Die folgenden Argumente werden unterstützt: * `allowed_hosts` – Eine Liste von Domain-Namen, die als Hostnamen zulässig sein sollten. Wildcard-Domains wie `*.example.com` werden unterstützt, um Subdomains zu matchen. Um jeden Hostnamen zu erlauben, verwenden Sie entweder `allowed_hosts=["*"]` oder lassen Sie diese Middleware weg. +* `www_redirect` – Wenn auf True gesetzt, werden Requests an Nicht-www-Versionen der erlaubten Hosts zu deren www-Gegenstücken umgeleitet. Der Defaultwert ist `True`. -Wenn ein eingehender Request nicht korrekt validiert wird, wird eine „400“-Response gesendet. +Wenn ein eingehender Request nicht korrekt validiert wird, wird eine `400`-Response gesendet. -## `GZipMiddleware` +## `GZipMiddleware` { #gzipmiddleware } Verarbeitet GZip-Responses für alle Requests, die `"gzip"` im `Accept-Encoding`-Header enthalten. @@ -81,9 +82,10 @@ Diese Middleware verarbeitet sowohl Standard- als auch Streaming-Responses. Die folgenden Argumente werden unterstützt: -* `minimum_size` – Antworten, die kleiner als diese Mindestgröße in Bytes sind, nicht per GZip komprimieren. Der Defaultwert ist `500`. +* `minimum_size` – Responses, die kleiner als diese Mindestgröße in Bytes sind, nicht per GZip komprimieren. Der Defaultwert ist `500`. +* `compresslevel` – Wird während der GZip-Kompression verwendet. Es ist ein Ganzzahlwert zwischen 1 und 9. Der Defaultwert ist `9`. Ein niedrigerer Wert resultiert in schnellerer Kompression, aber größeren Dateigrößen, während ein höherer Wert langsamere Kompression, aber kleinere Dateigrößen zur Folge hat. -## Andere Middlewares +## Andere Middlewares { #other-middlewares } Es gibt viele andere ASGI-Middlewares. diff --git a/docs/de/docs/advanced/openapi-callbacks.md b/docs/de/docs/advanced/openapi-callbacks.md index 53f06e24e..afc48bbb8 100644 --- a/docs/de/docs/advanced/openapi-callbacks.md +++ b/docs/de/docs/advanced/openapi-callbacks.md @@ -1,12 +1,12 @@ -# OpenAPI-Callbacks +# OpenAPI-Callbacks { #openapi-callbacks } -Sie könnten eine API mit einer *Pfadoperation* erstellen, die einen Request an eine *externe API* auslösen könnte, welche von jemand anderem erstellt wurde (wahrscheinlich derselbe Entwickler, der Ihre API *verwenden* würde). +Sie könnten eine API mit einer *Pfadoperation* erstellen, die einen Request an eine *externe API* auslösen könnte, welche von jemand anderem erstellt wurde (wahrscheinlich derselbe Entwickler, der Ihre API *verwenden* würde). -Der Vorgang, der stattfindet, wenn Ihre API-Anwendung die *externe API* aufruft, wird als „Callback“ („Rückruf“) bezeichnet. Denn die Software, die der externe Entwickler geschrieben hat, sendet einen Request an Ihre API und dann *ruft Ihre API zurück* (*calls back*) und sendet einen Request an eine *externe API* (die wahrscheinlich vom selben Entwickler erstellt wurde). +Der Vorgang, der stattfindet, wenn Ihre API-Anwendung die *externe API* aufruft, wird als „Callback“ bezeichnet. Denn die Software, die der externe Entwickler geschrieben hat, sendet einen Request an Ihre API und dann *ruft Ihre API zurück* (*calls back*) und sendet einen Request an eine *externe API* (die wahrscheinlich vom selben Entwickler erstellt wurde). -In diesem Fall möchten Sie möglicherweise dokumentieren, wie diese externe API aussehen *sollte*. Welche *Pfadoperation* sie haben sollte, welchen Body sie erwarten sollte, welche Response sie zurückgeben sollte, usw. +In diesem Fall möchten Sie möglicherweise dokumentieren, wie diese externe API aussehen *sollte*. Welche *Pfadoperation* sie haben sollte, welchen Body sie erwarten sollte, welche Response sie zurückgeben sollte, usw. -## Eine Anwendung mit Callbacks +## Eine Anwendung mit Callbacks { #an-app-with-callbacks } Sehen wir uns das alles anhand eines Beispiels an. @@ -16,14 +16,14 @@ Diese Rechnungen haben eine `id`, einen optionalen `title`, einen `customer` (Ku Der Benutzer Ihrer API (ein externer Entwickler) erstellt mit einem POST-Request eine Rechnung in Ihrer API. -Dann wird Ihre API (beispielsweise): +Dann wird Ihre API (stellen wir uns vor): * die Rechnung an einen Kunden des externen Entwicklers senden. * das Geld einsammeln. * eine Benachrichtigung an den API-Benutzer (den externen Entwickler) zurücksenden. * Dies erfolgt durch Senden eines POST-Requests (von *Ihrer API*) an eine *externe API*, die von diesem externen Entwickler bereitgestellt wird (das ist der „Callback“). -## Die normale **FastAPI**-Anwendung +## Die normale **FastAPI**-Anwendung { #the-normal-fastapi-app } Sehen wir uns zunächst an, wie die normale API-Anwendung aussehen würde, bevor wir den Callback hinzufügen. @@ -41,7 +41,7 @@ Der Query-Parameter `callback_url` verwendet einen Pydantic-OpenAPI-3-Ausdruck enthalten (mehr dazu weiter unten), wo er Variablen mit Parametern und Teilen des ursprünglichen Requests verwenden kann, der an *Ihre API* gesendet wurde. -### Der Callback-Pfadausdruck +### Der Callback-Pfadausdruck { #the-callback-path-expression } Der Callback-*Pfad* kann einen OpenAPI-3-Ausdruck enthalten, welcher Teile des ursprünglichen Requests enthalten kann, der an *Ihre API* gesendet wurde. @@ -163,7 +163,7 @@ Beachten Sie, dass die verwendete Callback-URL die URL enthält, die als Query-P /// -### Den Callback-Router hinzufügen +### Den Callback-Router hinzufügen { #add-the-callback-router } An diesem Punkt haben Sie die benötigte(n) *Callback-Pfadoperation(en)* (diejenige(n), die der *externe Entwickler* in der *externen API* implementieren sollte) im Callback-Router, den Sie oben erstellt haben. @@ -177,9 +177,9 @@ Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an ` /// -### Es in der Dokumentation ansehen +### Es in der Dokumentation testen { #check-the-docs } -Jetzt können Sie Ihre Anwendung mit Uvicorn starten und auf http://127.0.0.1:8000/docs gehen. +Jetzt können Sie Ihre Anwendung starten und auf http://127.0.0.1:8000/docs gehen. Sie sehen Ihre Dokumentation, einschließlich eines Abschnitts „Callbacks“ für Ihre *Pfadoperation*, der zeigt, wie die *externe API* aussehen sollte: diff --git a/docs/de/docs/advanced/openapi-webhooks.md b/docs/de/docs/advanced/openapi-webhooks.md index 50b95eaf8..a09a675ed 100644 --- a/docs/de/docs/advanced/openapi-webhooks.md +++ b/docs/de/docs/advanced/openapi-webhooks.md @@ -1,54 +1,54 @@ -# OpenAPI-Webhooks +# OpenAPI Webhooks { #openapi-webhooks } -Es gibt Fälle, in denen Sie Ihren API-Benutzern mitteilen möchten, dass Ihre Anwendung mit einigen Daten *deren* Anwendung aufrufen (ein Request senden) könnte, normalerweise um über ein bestimmtes **Event** zu **benachrichtigen**. +Es gibt Fälle, in denen Sie Ihren API-**Benutzern** mitteilen möchten, dass Ihre App *deren* App mit einigen Daten aufrufen (einen Request senden) könnte, normalerweise um über ein bestimmtes **Event** zu **benachrichtigen**. -Das bedeutet, dass anstelle des normalen Prozesses, bei dem Benutzer Requests an Ihre API senden, **Ihre API** (oder Ihre Anwendung) **Requests an deren System** (an deren API, deren Anwendung) senden könnte. +Das bedeutet, dass anstelle des normalen Prozesses, bei dem Ihre Benutzer Requests an Ihre API senden, **Ihre API** (oder Ihre App) **Requests an deren System** (an deren API, deren App) senden könnte. -Das wird normalerweise als **Webhook** bezeichnet. +Das wird normalerweise als **Webhook** bezeichnet. -## Webhooks-Schritte +## Webhooks-Schritte { #webhooks-steps } Der Prozess besteht normalerweise darin, dass **Sie in Ihrem Code definieren**, welche Nachricht Sie senden möchten, den **Body des Requests**. -Sie definieren auch auf irgendeine Weise, zu welchen **Momenten** Ihre Anwendung diese Requests oder Events sendet. +Sie definieren auch auf irgendeine Weise, in welchen **Momenten** Ihre App diese Requests oder Events senden wird. -Und **Ihre Benutzer** definieren auf irgendeine Weise (zum Beispiel irgendwo in einem Web-Dashboard) die **URL**, an die Ihre Anwendung diese Requests senden soll. +Und **Ihre Benutzer** definieren auf irgendeine Weise (zum Beispiel irgendwo in einem Web-Dashboard) die **URL**, an die Ihre App diese Requests senden soll. Die gesamte **Logik** zur Registrierung der URLs für Webhooks und der Code zum tatsächlichen Senden dieser Requests liegt bei Ihnen. Sie schreiben es so, wie Sie möchten, in **Ihrem eigenen Code**. -## Webhooks mit **FastAPI** und OpenAPI dokumentieren +## Webhooks mit **FastAPI** und OpenAPI dokumentieren { #documenting-webhooks-with-fastapi-and-openapi } -Mit **FastAPI** können Sie mithilfe von OpenAPI die Namen dieser Webhooks, die Arten von HTTP-Operationen, die Ihre Anwendung senden kann (z. B. `POST`, `PUT`, usw.) und die Request**bodys** definieren, die Ihre Anwendung senden würde. +Mit **FastAPI**, mithilfe von OpenAPI, können Sie die Namen dieser Webhooks, die Arten von HTTP-Operationen, die Ihre App senden kann (z. B. `POST`, `PUT`, usw.) und die Request**bodys** definieren, die Ihre App senden würde. -Dies kann es Ihren Benutzern viel einfacher machen, **deren APIs zu implementieren**, um Ihre **Webhook**-Requests zu empfangen. Möglicherweise können diese sogar einen Teil des eigenem API-Codes automatisch generieren. +Dies kann es Ihren Benutzern viel einfacher machen, **deren APIs zu implementieren**, um Ihre **Webhook**-Requests zu empfangen. Möglicherweise können diese sogar einen Teil ihres eigenen API-Codes automatisch generieren. -/// info +/// info | Info Webhooks sind in OpenAPI 3.1.0 und höher verfügbar und werden von FastAPI `0.99.0` und höher unterstützt. /// -## Eine Anwendung mit Webhooks +## Eine App mit Webhooks { #an-app-with-webhooks } -Wenn Sie eine **FastAPI**-Anwendung erstellen, gibt es ein `webhooks`-Attribut, mit dem Sie *Webhooks* definieren können, genauso wie Sie *Pfadoperationen* definieren würden, zum Beispiel mit `@app.webhooks.post()`. +Wenn Sie eine **FastAPI**-Anwendung erstellen, gibt es ein `webhooks`-Attribut, das Sie verwenden können, um *Webhooks* zu definieren, genauso wie Sie *Pfadoperationen* definieren würden, zum Beispiel mit `@app.webhooks.post()`. {* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *} Die von Ihnen definierten Webhooks landen im **OpenAPI**-Schema und der automatischen **Dokumentations-Oberfläche**. -/// info +/// info | Info -Das `app.webhooks`-Objekt ist eigentlich nur ein `APIRouter`, derselbe Typ, den Sie verwenden würden, wenn Sie Ihre Anwendung mit mehreren Dateien strukturieren. +Das `app.webhooks`-Objekt ist eigentlich nur ein `APIRouter`, derselbe Typ, den Sie verwenden würden, wenn Sie Ihre App mit mehreren Dateien strukturieren. /// -Beachten Sie, dass Sie bei Webhooks tatsächlich keinen *Pfad* (wie `/items/`) deklarieren, sondern dass der Text, den Sie dort übergeben, lediglich eine **Kennzeichnung** des Webhooks (der Name des Events) ist. Zum Beispiel ist in `@app.webhooks.post("new-subscription")` der Webhook-Name `new-subscription`. +Beachten Sie, dass Sie bei Webhooks tatsächlich keinen *Pfad* (wie `/items/`) deklarieren, der Text, den Sie dort übergeben, ist lediglich eine **Kennzeichnung** des Webhooks (der Name des Events). Zum Beispiel ist in `@app.webhooks.post("new-subscription")` der Webhook-Name `new-subscription`. -Das liegt daran, dass erwartet wird, dass **Ihre Benutzer** den tatsächlichen **URL-Pfad**, an dem diese den Webhook-Request empfangen möchten, auf andere Weise definieren (z. B. über ein Web-Dashboard). +Das liegt daran, dass erwartet wird, dass **Ihre Benutzer** den tatsächlichen **URL-Pfad**, an dem sie den Webhook-Request empfangen möchten, auf andere Weise definieren (z. B. über ein Web-Dashboard). -### Es in der Dokumentation ansehen +### Die Dokumentation testen { #check-the-docs } -Jetzt können Sie Ihre Anwendung mit Uvicorn starten und auf http://127.0.0.1:8000/docs gehen. +Jetzt können Sie Ihre App starten und auf http://127.0.0.1:8000/docs gehen. Sie werden sehen, dass Ihre Dokumentation die normalen *Pfadoperationen* und jetzt auch einige **Webhooks** enthält: diff --git a/docs/de/docs/advanced/path-operation-advanced-configuration.md b/docs/de/docs/advanced/path-operation-advanced-configuration.md index b6e88d2c9..f5ec7c49e 100644 --- a/docs/de/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/de/docs/advanced/path-operation-advanced-configuration.md @@ -1,6 +1,6 @@ -# Fortgeschrittene Konfiguration der Pfadoperation +# Fortgeschrittene Konfiguration der Pfadoperation { #path-operation-advanced-configuration } -## OpenAPI operationId +## OpenAPI operationId { #openapi-operationid } /// warning | Achtung @@ -14,13 +14,13 @@ Sie müssten sicherstellen, dass sie für jede Operation eindeutig ist. {* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *} -### Verwendung des Namens der *Pfadoperation-Funktion* als operationId +### Verwendung des Namens der *Pfadoperation-Funktion* als operationId { #using-the-path-operation-function-name-as-the-operationid } Wenn Sie die Funktionsnamen Ihrer API als `operationId`s verwenden möchten, können Sie über alle iterieren und die `operation_id` jeder *Pfadoperation* mit deren `APIRoute.name` überschreiben. Sie sollten dies tun, nachdem Sie alle Ihre *Pfadoperationen* hinzugefügt haben. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2, 12:21, 24] *} /// tip | Tipp @@ -36,13 +36,13 @@ Auch wenn diese sich in unterschiedlichen Modulen (Python-Dateien) befinden. /// -## Von OpenAPI ausschließen +## Von OpenAPI ausschließen { #exclude-from-openapi } Um eine *Pfadoperation* aus dem generierten OpenAPI-Schema (und damit aus den automatischen Dokumentationssystemen) auszuschließen, verwenden Sie den Parameter `include_in_schema` und setzen Sie ihn auf `False`: {* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *} -## Fortgeschrittene Beschreibung mittels Docstring +## Fortgeschrittene Beschreibung mittels Docstring { #advanced-description-from-docstring } Sie können die verwendeten Zeilen aus dem Docstring einer *Pfadoperation-Funktion* einschränken, die für OpenAPI verwendet werden. @@ -52,17 +52,17 @@ Sie wird nicht in der Dokumentation angezeigt, aber andere Tools (z. B. Sphinx) {* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *} -## Zusätzliche Responses +## Zusätzliche Responses { #additional-responses } Sie haben wahrscheinlich gesehen, wie man das `response_model` und den `status_code` für eine *Pfadoperation* deklariert. -Das definiert die Metadaten der Haupt-Response einer *Pfadoperation*. +Das definiert die Metadaten der Haupt-Response einer *Pfadoperation*. Sie können auch zusätzliche Responses mit deren Modellen, Statuscodes usw. deklarieren. Es gibt hier in der Dokumentation ein ganzes Kapitel darüber, Sie können es unter [Zusätzliche Responses in OpenAPI](additional-responses.md){.internal-link target=_blank} lesen. -## OpenAPI-Extra +## OpenAPI-Extra { #openapi-extra } Wenn Sie in Ihrer Anwendung eine *Pfadoperation* deklarieren, generiert **FastAPI** automatisch die relevanten Metadaten dieser *Pfadoperation*, die in das OpenAPI-Schema aufgenommen werden sollen. @@ -80,7 +80,7 @@ Dieses *Pfadoperation*-spezifische OpenAPI-Schema wird normalerweise automatisch /// tip | Tipp -Dies ist ein Low-Level Erweiterungspunkt. +Dies ist ein Low-Level-Erweiterungspunkt. Wenn Sie nur zusätzliche Responses deklarieren müssen, können Sie dies bequemer mit [Zusätzliche Responses in OpenAPI](additional-responses.md){.internal-link target=_blank} tun. @@ -88,9 +88,9 @@ Wenn Sie nur zusätzliche Responses deklarieren müssen, können Sie dies bequem Sie können das OpenAPI-Schema für eine *Pfadoperation* erweitern, indem Sie den Parameter `openapi_extra` verwenden. -### OpenAPI-Erweiterungen +### OpenAPI-Erweiterungen { #openapi-extensions } -Dieses `openapi_extra` kann beispielsweise hilfreich sein, um OpenAPI-Erweiterungen zu deklarieren: +Dieses `openapi_extra` kann beispielsweise hilfreich sein, um [OpenAPI-Erweiterungen](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) zu deklarieren: {* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *} @@ -129,43 +129,43 @@ Und wenn Sie die resultierende OpenAPI sehen (unter `/openapi.json` in Ihrer API } ``` -### Benutzerdefiniertes OpenAPI-*Pfadoperation*-Schema +### Benutzerdefiniertes OpenAPI-*Pfadoperation*-Schema { #custom-openapi-path-operation-schema } -Das Dictionary in `openapi_extra` wird mit dem automatisch generierten OpenAPI-Schema für die *Pfadoperation* zusammengeführt (mittels Deep Merge). +Das Dictionary in `openapi_extra` wird mit dem automatisch generierten OpenAPI-Schema für die *Pfadoperation* zusammengeführt (mittels Deep Merge). Sie können dem automatisch generierten Schema also zusätzliche Daten hinzufügen. -Sie könnten sich beispielsweise dafür entscheiden, den Request mit Ihrem eigenen Code zu lesen und zu validieren, ohne die automatischen Funktionen von FastAPI mit Pydantic zu verwenden, aber Sie könnten den Request trotzdem im OpenAPI-Schema definieren wollen. +Sie könnten sich beispielsweise dafür entscheiden, den Request mit Ihrem eigenen Code zu lesen und zu validieren, ohne die automatischen Funktionen von FastAPI mit Pydantic zu verwenden, aber Sie könnten den Request trotzdem im OpenAPI-Schema definieren wollen. Das könnte man mit `openapi_extra` machen: -{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[20:37,39:40] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36, 39:40] *} -In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsächlich wird der Requestbody nicht einmal als JSON geparst, sondern direkt als `bytes` gelesen und die Funktion `magic_data_reader ()` wäre dafür verantwortlich, ihn in irgendeiner Weise zu parsen. +In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsächlich wird der Requestbody nicht einmal als JSON geparst, sondern direkt als `bytes` gelesen und die Funktion `magic_data_reader()` wäre dafür verantwortlich, ihn in irgendeiner Weise zu parsen. Dennoch können wir das zu erwartende Schema für den Requestbody deklarieren. -### Benutzerdefinierter OpenAPI-Content-Type +### Benutzerdefinierter OpenAPI-Content-Type { #custom-openapi-content-type } Mit demselben Trick könnten Sie ein Pydantic-Modell verwenden, um das JSON-Schema zu definieren, das dann im benutzerdefinierten Abschnitt des OpenAPI-Schemas für die *Pfadoperation* enthalten ist. -Und Sie könnten dies auch tun, wenn der Datentyp in der Anfrage nicht JSON ist. +Und Sie könnten dies auch tun, wenn der Datentyp im Request nicht JSON ist. In der folgenden Anwendung verwenden wir beispielsweise weder die integrierte Funktionalität von FastAPI zum Extrahieren des JSON-Schemas aus Pydantic-Modellen noch die automatische Validierung für JSON. Tatsächlich deklarieren wir den Request-Content-Type als YAML und nicht als JSON: //// tab | Pydantic v2 -{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22,24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22, 24] *} //// //// tab | Pydantic v1 -{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22,24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22, 24] *} //// -/// info +/// info | Info In Pydantic Version 1 hieß die Methode zum Abrufen des JSON-Schemas für ein Modell `Item.schema()`, in Pydantic Version 2 heißt die Methode `Item.model_json_schema()`. @@ -189,7 +189,7 @@ Und dann parsen wir in unserem Code diesen YAML-Inhalt direkt und verwenden dann //// -/// info +/// info | Info In Pydantic Version 1 war die Methode zum Parsen und Validieren eines Objekts `Item.parse_obj()`, in Pydantic Version 2 heißt die Methode `Item.model_validate()`. diff --git a/docs/de/docs/advanced/response-change-status-code.md b/docs/de/docs/advanced/response-change-status-code.md index 0aac32f4e..b079e241d 100644 --- a/docs/de/docs/advanced/response-change-status-code.md +++ b/docs/de/docs/advanced/response-change-status-code.md @@ -1,31 +1,31 @@ -# Response – Statuscode ändern +# Response – Statuscode ändern { #response-change-status-code } -Sie haben wahrscheinlich schon vorher gelesen, dass Sie einen Standard-[Response-Statuscode](../tutorial/response-status-code.md){.internal-link target=_blank} festlegen können. +Sie haben wahrscheinlich schon vorher gelesen, dass Sie einen Default-[Response-Statuscode](../tutorial/response-status-code.md){.internal-link target=_blank} festlegen können. -In manchen Fällen müssen Sie jedoch einen anderen als den Standard-Statuscode zurückgeben. +In manchen Fällen müssen Sie jedoch einen anderen als den Default-Statuscode zurückgeben. -## Anwendungsfall +## Anwendungsfall { #use-case } Stellen Sie sich zum Beispiel vor, Sie möchten standardmäßig den HTTP-Statuscode „OK“ `200` zurückgeben. -Wenn die Daten jedoch nicht vorhanden waren, möchten Sie diese erstellen und den HTTP-Statuscode „CREATED“ `201` zurückgeben. +Wenn die Daten jedoch nicht vorhanden sind, möchten Sie diese erstellen und den HTTP-Statuscode „CREATED“ `201` zurückgeben. Sie möchten aber dennoch in der Lage sein, die von Ihnen zurückgegebenen Daten mit einem `response_model` zu filtern und zu konvertieren. In diesen Fällen können Sie einen `Response`-Parameter verwenden. -## Einen `Response`-Parameter verwenden +## Einen `Response`-Parameter verwenden { #use-a-response-parameter } Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren (wie Sie es auch für Cookies und Header tun können). -Anschließend können Sie den `status_code` in diesem *vorübergehenden* Response-Objekt festlegen. +Anschließend können Sie den `status_code` in diesem *vorübergehenden* Response-Objekt festlegen. {* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *} -Und dann können Sie wie gewohnt jedes benötigte Objekt zurückgeben (ein `dict`, ein Datenbankmodell usw.). +Und dann können Sie jedes benötigte Objekt zurückgeben, wie Sie es normalerweise tun würden (ein `dict`, ein Datenbankmodell usw.). Und wenn Sie ein `response_model` deklariert haben, wird es weiterhin zum Filtern und Konvertieren des von Ihnen zurückgegebenen Objekts verwendet. **FastAPI** verwendet diese *vorübergehende* Response, um den Statuscode (auch Cookies und Header) zu extrahieren und fügt diese in die endgültige Response ein, die den von Ihnen zurückgegebenen Wert enthält, gefiltert nach einem beliebigen `response_model`. -Sie können den Parameter `Response` auch in Abhängigkeiten deklarieren und den Statuscode darin festlegen. Bedenken Sie jedoch, dass der gewinnt, welcher zuletzt gesetzt wird. +Sie können den Parameter `Response` auch in Abhängigkeiten deklarieren und den Statuscode darin festlegen. Bedenken Sie jedoch, dass der zuletzt gesetzte gewinnt. diff --git a/docs/de/docs/advanced/response-cookies.md b/docs/de/docs/advanced/response-cookies.md index 5fe2cf7e3..0dd4175dd 100644 --- a/docs/de/docs/advanced/response-cookies.md +++ b/docs/de/docs/advanced/response-cookies.md @@ -1,12 +1,12 @@ -# Response-Cookies +# Response-Cookies { #response-cookies } -## Einen `Response`-Parameter verwenden +## Einen `Response`-Parameter verwenden { #use-a-response-parameter } Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren. -Und dann können Sie Cookies in diesem *vorübergehenden* Response-Objekt setzen. +Und dann können Sie Cookies in diesem *vorübergehenden* Response-Objekt setzen. -{* ../../docs_src/response_cookies/tutorial002.py hl[1,8:9] *} +{* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *} Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.). @@ -16,7 +16,7 @@ Und wenn Sie ein `response_model` deklariert haben, wird es weiterhin zum Filter Sie können den `Response`-Parameter auch in Abhängigkeiten deklarieren und darin Cookies (und Header) setzen. -## Eine `Response` direkt zurückgeben +## Eine `Response` direkt zurückgeben { #return-a-response-directly } Sie können Cookies auch erstellen, wenn Sie eine `Response` direkt in Ihrem Code zurückgeben. @@ -36,7 +36,7 @@ Und auch, dass Sie keine Daten senden, die durch ein `response_model` hätten ge /// -### Mehr Informationen +### Mehr Informationen { #more-info } /// note | Technische Details diff --git a/docs/de/docs/advanced/response-directly.md b/docs/de/docs/advanced/response-directly.md index b84aa8ab9..d99517373 100644 --- a/docs/de/docs/advanced/response-directly.md +++ b/docs/de/docs/advanced/response-directly.md @@ -1,16 +1,16 @@ -# Eine Response direkt zurückgeben +# Eine Response direkt zurückgeben { #return-a-response-directly } -Wenn Sie eine **FastAPI** *Pfadoperation* erstellen, können Sie normalerweise beliebige Daten davon zurückgeben: ein `dict`, eine `list`e, ein Pydantic-Modell, ein Datenbankmodell, usw. +Wenn Sie eine **FastAPI** *Pfadoperation* erstellen, können Sie normalerweise beliebige Daten davon zurückgeben: ein `dict`, eine `list`, ein Pydantic-Modell, ein Datenbankmodell, usw. Standardmäßig konvertiert **FastAPI** diesen Rückgabewert automatisch nach JSON, mithilfe des `jsonable_encoder`, der in [JSON-kompatibler Encoder](../tutorial/encoder.md){.internal-link target=_blank} erläutert wird. -Dann würde es hinter den Kulissen diese JSON-kompatiblen Daten (z. B. ein `dict`) in eine `JSONResponse` einfügen, die zum Senden der Response an den Client verwendet würde. +Dann würde es hinter den Kulissen diese JSON-kompatiblen Daten (z. B. ein `dict`) in eine `JSONResponse` einfügen, die zum Senden der Response an den Client verwendet wird. Sie können jedoch direkt eine `JSONResponse` von Ihren *Pfadoperationen* zurückgeben. Das kann beispielsweise nützlich sein, um benutzerdefinierte Header oder Cookies zurückzugeben. -## Eine `Response` zurückgeben +## Eine `Response` zurückgeben { #return-a-response } Tatsächlich können Sie jede `Response` oder jede Unterklasse davon zurückgeben. @@ -26,7 +26,7 @@ Es wird keine Datenkonvertierung mit Pydantic-Modellen durchführen, es wird den Dadurch haben Sie viel Flexibilität. Sie können jeden Datentyp zurückgeben, jede Datendeklaration oder -validierung überschreiben, usw. -## Verwendung des `jsonable_encoder` in einer `Response` +## Verwendung des `jsonable_encoder` in einer `Response` { #using-the-jsonable-encoder-in-a-response } Da **FastAPI** keine Änderungen an einer von Ihnen zurückgegebenen `Response` vornimmt, müssen Sie sicherstellen, dass deren Inhalt dafür bereit ist. @@ -38,13 +38,13 @@ In diesen Fällen können Sie den `jsonable_encoder` verwenden, um Ihre Daten zu /// note | Technische Details -Sie können auch `from starlette.responses import JSONResponse` verwenden. +Sie könnten auch `from starlette.responses import JSONResponse` verwenden. **FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. /// -## Eine benutzerdefinierte `Response` zurückgeben +## Eine benutzerdefinierte `Response` zurückgeben { #returning-a-custom-response } Das obige Beispiel zeigt alle Teile, die Sie benötigen, ist aber noch nicht sehr nützlich, da Sie das `item` einfach direkt hätten zurückgeben können, und **FastAPI** würde es für Sie in eine `JSONResponse` einfügen, es in ein `dict` konvertieren, usw. All das standardmäßig. @@ -56,7 +56,7 @@ Sie könnten Ihren XML-Inhalt als String in eine `Response` einfügen und sie zu {* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} -## Anmerkungen +## Anmerkungen { #notes } Wenn Sie eine `Response` direkt zurücksenden, werden deren Daten weder validiert, konvertiert (serialisiert), noch automatisch dokumentiert. diff --git a/docs/de/docs/advanced/response-headers.md b/docs/de/docs/advanced/response-headers.md index bf0bd7296..a5e310d55 100644 --- a/docs/de/docs/advanced/response-headers.md +++ b/docs/de/docs/advanced/response-headers.md @@ -1,12 +1,12 @@ -# Response-Header +# Response-Header { #response-headers } -## Verwenden Sie einen `Response`-Parameter +## Einen `Response`-Parameter verwenden { #use-a-response-parameter } Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren (wie Sie es auch für Cookies tun können). -Und dann können Sie Header in diesem *vorübergehenden* Response-Objekt festlegen. +Und dann können Sie Header in diesem *vorübergehenden* Response-Objekt festlegen. -{* ../../docs_src/response_headers/tutorial002.py hl[1,7:8] *} +{* ../../docs_src/response_headers/tutorial002.py hl[1, 7:8] *} Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.). @@ -16,7 +16,7 @@ Und wenn Sie ein `response_model` deklariert haben, wird es weiterhin zum Filter Sie können den Parameter `Response` auch in Abhängigkeiten deklarieren und darin Header (und Cookies) festlegen. -## Eine `Response` direkt zurückgeben +## Eine `Response` direkt zurückgeben { #return-a-response-directly } Sie können auch Header hinzufügen, wenn Sie eine `Response` direkt zurückgeben. @@ -34,8 +34,8 @@ Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, /// -## Benutzerdefinierte Header +## Benutzerdefinierte Header { #custom-headers } -Beachten Sie, dass benutzerdefinierte proprietäre Header mittels des Präfix 'X-' hinzugefügt werden können. +Beachten Sie, dass benutzerdefinierte proprietäre Header mittels des Präfix `X-` hinzugefügt werden können. -Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihren CORS-Konfigurationen hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), unter Verwendung des Parameters `expose_headers`, dokumentiert in Starlettes CORS-Dokumentation. +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihrer CORS-Konfiguration hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), unter Verwendung des Parameters `expose_headers`, dokumentiert in Starlettes CORS-Dokumentation. diff --git a/docs/de/docs/advanced/security/http-basic-auth.md b/docs/de/docs/advanced/security/http-basic-auth.md index 36498c01d..f906ecd92 100644 --- a/docs/de/docs/advanced/security/http-basic-auth.md +++ b/docs/de/docs/advanced/security/http-basic-auth.md @@ -1,4 +1,4 @@ -# HTTP Basic Auth +# HTTP Basic Auth { #http-basic-auth } Für die einfachsten Fälle können Sie HTTP Basic Auth verwenden. @@ -6,13 +6,13 @@ Bei HTTP Basic Auth erwartet die Anwendung einen Header, der einen Benutzernamen Wenn sie diesen nicht empfängt, gibt sie den HTTP-Error 401 „Unauthorized“ zurück. -Und gibt einen Header `WWW-Authenticate` mit dem Wert `Basic` und einem optionalen `realm`-Parameter („Bereich“) zurück. +Und gibt einen Header `WWW-Authenticate` mit dem Wert `Basic` und einem optionalen `realm`-Parameter zurück. Dadurch wird der Browser angewiesen, die integrierte Eingabeaufforderung für einen Benutzernamen und ein Passwort anzuzeigen. Wenn Sie dann den Benutzernamen und das Passwort eingeben, sendet der Browser diese automatisch im Header. -## Einfaches HTTP Basic Auth +## Einfaches HTTP Basic Auth { #simple-http-basic-auth } * Importieren Sie `HTTPBasic` und `HTTPBasicCredentials`. * Erstellen Sie mit `HTTPBasic` ein „`security`-Schema“. @@ -21,11 +21,12 @@ Wenn Sie dann den Benutzernamen und das Passwort eingeben, sendet der Browser di * Es enthält den gesendeten `username` und das gesendete `password`. {* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *} + Wenn Sie versuchen, die URL zum ersten Mal zu öffnen (oder in der Dokumentation auf den Button „Execute“ zu klicken), wird der Browser Sie nach Ihrem Benutzernamen und Passwort fragen: -## Den Benutzernamen überprüfen +## Den Benutzernamen überprüfen { #check-the-username } Hier ist ein vollständigeres Beispiel. @@ -51,13 +52,13 @@ if not (credentials.username == "stanleyjobson") or not (credentials.password == Aber durch die Verwendung von `secrets.compare_digest()` ist dieser Code sicher vor einer Art von Angriffen, die „Timing-Angriffe“ genannt werden. -### Timing-Angriffe +### Timing-Angriffe { #timing-attacks } Aber was ist ein „Timing-Angriff“? Stellen wir uns vor, dass einige Angreifer versuchen, den Benutzernamen und das Passwort zu erraten. -Und sie senden eine Anfrage mit dem Benutzernamen `johndoe` und dem Passwort `love123`. +Und sie senden einen Request mit dem Benutzernamen `johndoe` und dem Passwort `love123`. Dann würde der Python-Code in Ihrer Anwendung etwa so aussehen: @@ -77,21 +78,21 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": ... ``` -Python muss das gesamte `stanleyjobso` in `stanleyjobsox` und `stanleyjobson` vergleichen, bevor es erkennt, dass beide Zeichenfolgen nicht gleich sind. Daher wird es einige zusätzliche Mikrosekunden dauern, bis die Antwort „Incorrect username or password“ erfolgt. +Python muss das gesamte `stanleyjobso` in `stanleyjobsox` und `stanleyjobson` vergleichen, bevor es erkennt, dass beide Zeichenfolgen nicht gleich sind. Daher wird es einige zusätzliche Mikrosekunden dauern, bis die Response „Incorrect username or password“ erfolgt. -#### Die Zeit zum Antworten hilft den Angreifern +#### Die Zeit zum Antworten hilft den Angreifern { #the-time-to-answer-helps-the-attackers } -Wenn die Angreifer zu diesem Zeitpunkt feststellen, dass der Server einige Mikrosekunden länger braucht, um die Antwort „Incorrect username or password“ zu senden, wissen sie, dass sie _etwas_ richtig gemacht haben, einige der Anfangsbuchstaben waren richtig. +Wenn die Angreifer zu diesem Zeitpunkt feststellen, dass der Server einige Mikrosekunden länger braucht, um die Response „Incorrect username or password“ zu senden, wissen sie, dass sie _etwas_ richtig gemacht haben, einige der Anfangsbuchstaben waren richtig. Und dann können sie es noch einmal versuchen, wohl wissend, dass es wahrscheinlich eher etwas mit `stanleyjobsox` als mit `johndoe` zu tun hat. -#### Ein „professioneller“ Angriff +#### Ein „professioneller“ Angriff { #a-professional-attack } Natürlich würden die Angreifer das alles nicht von Hand versuchen, sondern ein Programm dafür schreiben, möglicherweise mit Tausenden oder Millionen Tests pro Sekunde. Und würden jeweils nur einen zusätzlichen richtigen Buchstaben erhalten. Aber so hätten die Angreifer in wenigen Minuten oder Stunden mit der „Hilfe“ unserer Anwendung den richtigen Benutzernamen und das richtige Passwort erraten, indem sie die Zeitspanne zur Hilfe nehmen, die diese zur Beantwortung benötigt. -#### Das Problem beheben mittels `secrets.compare_digest()` +#### Das Problem beheben mittels `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest } Aber in unserem Code verwenden wir tatsächlich `secrets.compare_digest()`. @@ -99,7 +100,7 @@ Damit wird, kurz gesagt, der Vergleich von `stanleyjobsox` mit `stanleyjobson` g So ist Ihr Anwendungscode, dank der Verwendung von `secrets.compare_digest()`, vor dieser ganzen Klasse von Sicherheitsangriffen geschützt. -### Den Error zurückgeben +### Den Error zurückgeben { #return-the-error } Nachdem Sie festgestellt haben, dass die Anmeldeinformationen falsch sind, geben Sie eine `HTTPException` mit dem Statuscode 401 zurück (derselbe, der auch zurückgegeben wird, wenn keine Anmeldeinformationen angegeben werden) und fügen den Header `WWW-Authenticate` hinzu, damit der Browser die Anmeldeaufforderung erneut anzeigt: diff --git a/docs/de/docs/advanced/security/index.md b/docs/de/docs/advanced/security/index.md index 25eeb25b5..d7e633231 100644 --- a/docs/de/docs/advanced/security/index.md +++ b/docs/de/docs/advanced/security/index.md @@ -1,6 +1,6 @@ -# Fortgeschrittene Sicherheit +# Fortgeschrittene Sicherheit { #advanced-security } -## Zusatzfunktionen +## Zusatzfunktionen { #additional-features } Neben den in [Tutorial – Benutzerhandbuch: Sicherheit](../../tutorial/security/index.md){.internal-link target=_blank} behandelten Funktionen gibt es noch einige zusätzliche Funktionen zur Handhabung der Sicherheit. @@ -12,8 +12,8 @@ Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon l /// -## Lesen Sie zuerst das Tutorial +## Das Tutorial zuerst lesen { #read-the-tutorial-first } -In den nächsten Abschnitten wird davon ausgegangen, dass Sie das Haupt-[Tutorial – Benutzerhandbuch: Sicherheit](../../tutorial/security/index.md){.internal-link target=_blank} bereits gelesen haben. +Die nächsten Abschnitte setzen voraus, dass Sie das Haupt-[Tutorial – Benutzerhandbuch: Sicherheit](../../tutorial/security/index.md){.internal-link target=_blank} bereits gelesen haben. Sie basieren alle auf den gleichen Konzepten, ermöglichen jedoch einige zusätzliche Funktionalitäten. diff --git a/docs/de/docs/advanced/security/oauth2-scopes.md b/docs/de/docs/advanced/security/oauth2-scopes.md index 01bc4fb95..b96715d5a 100644 --- a/docs/de/docs/advanced/security/oauth2-scopes.md +++ b/docs/de/docs/advanced/security/oauth2-scopes.md @@ -1,4 +1,4 @@ -# OAuth2-Scopes +# OAuth2-Scopes { #oauth2-scopes } Sie können OAuth2-Scopes direkt in **FastAPI** verwenden, sie sind nahtlos integriert. @@ -26,7 +26,7 @@ Aber wenn Sie wissen, dass Sie es brauchen oder neugierig sind, lesen Sie weiter /// -## OAuth2-Scopes und OpenAPI +## OAuth2-Scopes und OpenAPI { #oauth2-scopes-and-openapi } Die OAuth2-Spezifikation definiert „Scopes“ als eine Liste von durch Leerzeichen getrennten Strings. @@ -46,7 +46,7 @@ Er wird normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu dekla * `instagram_basic` wird von Facebook / Instagram verwendet. * `https://www.googleapis.com/auth/drive` wird von Google verwendet. -/// info +/// info | Info In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert. @@ -58,21 +58,21 @@ Für OAuth2 sind es einfach nur Strings. /// -## Gesamtübersicht +## Gesamtübersicht { #global-view } Sehen wir uns zunächst kurz die Teile an, die sich gegenüber den Beispielen im Haupt-**Tutorial – Benutzerhandbuch** für [OAuth2 mit Password (und Hashing), Bearer mit JWT-Tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ändern. Diesmal verwenden wir OAuth2-Scopes: -{* ../../docs_src/security/tutorial005_an_py310.py hl[4,8,12,46,64,105,107:115,121:124,128:134,139,155] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} Sehen wir uns diese Änderungen nun Schritt für Schritt an. -## OAuth2-Sicherheitsschema +## OAuth2-Sicherheitsschema { #oauth2-security-scheme } Die erste Änderung ist, dass wir jetzt das OAuth2-Sicherheitsschema mit zwei verfügbaren Scopes deklarieren: `me` und `items`. -Der `scopes`-Parameter erhält ein `dict` mit jedem Scope als Schlüssel und dessen Beschreibung als Wert: +Der `scopes`-Parameter erhält ein `dict` mit jedem Scope als Schlüssel und dessen Beschreibung als Wert: -{* ../../docs_src/security/tutorial005_an_py310.py hl[62:65] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} Da wir diese Scopes jetzt deklarieren, werden sie in der API-Dokumentation angezeigt, wenn Sie sich einloggen/autorisieren. @@ -82,11 +82,11 @@ Das ist derselbe Mechanismus, der verwendet wird, wenn Sie beim Anmelden mit Fac -## JWT-Token mit Scopes +## JWT-Token mit Scopes { #jwt-token-with-scopes } Ändern Sie nun die Token-*Pfadoperation*, um die angeforderten Scopes zurückzugeben. -Wir verwenden immer noch dasselbe `OAuth2PasswordRequestForm`. Es enthält eine Eigenschaft `scopes` mit einer `list`e von `str`s für jeden Scope, den es im Request erhalten hat. +Wir verwenden immer noch dasselbe `OAuth2PasswordRequestForm`. Es enthält eine Eigenschaft `scopes` mit einer `list`e von `str`s für jeden Scope, den es im Request erhalten hat. Und wir geben die Scopes als Teil des JWT-Tokens zurück. @@ -98,9 +98,9 @@ Aus Sicherheitsgründen sollten Sie jedoch sicherstellen, dass Sie in Ihrer Anwe /// -{* ../../docs_src/security/tutorial005_an_py310.py hl[155] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} -## Scopes in *Pfadoperationen* und Abhängigkeiten deklarieren +## Scopes in *Pfadoperationen* und Abhängigkeiten deklarieren { #declare-scopes-in-path-operations-and-dependencies } Jetzt deklarieren wir, dass die *Pfadoperation* für `/users/me/items/` den Scope `items` erfordert. @@ -124,7 +124,7 @@ Wir tun dies hier, um zu demonstrieren, wie **FastAPI** auf verschiedenen Ebenen /// -{* ../../docs_src/security/tutorial005_an_py310.py hl[4,139,170] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} /// info | Technische Details @@ -136,7 +136,7 @@ Wenn Sie jedoch `Query`, `Path`, `Depends`, `Security` und andere von `fastapi` /// -## `SecurityScopes` verwenden +## `SecurityScopes` verwenden { #use-securityscopes } Aktualisieren Sie nun die Abhängigkeit `get_current_user`. @@ -150,9 +150,9 @@ Wir deklarieren auch einen speziellen Parameter vom Typ `SecurityScopes`, der au Diese `SecurityScopes`-Klasse ähnelt `Request` (`Request` wurde verwendet, um das Request-Objekt direkt zu erhalten). -{* ../../docs_src/security/tutorial005_an_py310.py hl[8,105] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} -## Die `scopes` verwenden +## Die `scopes` verwenden { #use-the-scopes } Der Parameter `security_scopes` wird vom Typ `SecurityScopes` sein. @@ -164,9 +164,9 @@ Wir erstellen eine `HTTPException`, die wir später an mehreren Stellen wiederve In diese Exception fügen wir (falls vorhanden) die erforderlichen Scopes als durch Leerzeichen getrennten String ein (unter Verwendung von `scope_str`). Wir fügen diesen String mit den Scopes in den Header `WWW-Authenticate` ein (das ist Teil der Spezifikation). -{* ../../docs_src/security/tutorial005_an_py310.py hl[105,107:115] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} -## Den `username` und das Format der Daten überprüfen +## Den `username` und das Format der Daten überprüfen { #verify-the-username-and-data-shape } Wir verifizieren, dass wir einen `username` erhalten, und extrahieren die Scopes. @@ -180,17 +180,17 @@ Anstelle beispielsweise eines `dict`s oder etwas anderem, was später in der Anw Wir verifizieren auch, dass wir einen Benutzer mit diesem Benutzernamen haben, und wenn nicht, lösen wir dieselbe Exception aus, die wir zuvor erstellt haben. -{* ../../docs_src/security/tutorial005_an_py310.py hl[46,116:127] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} -## Die `scopes` verifizieren +## Die `scopes` verifizieren { #verify-the-scopes } -Wir überprüfen nun, ob das empfangenen Token alle Scopes enthält, die von dieser Abhängigkeit und deren Verwendern (einschließlich *Pfadoperationen*) gefordert werden. Andernfalls lösen wir eine `HTTPException` aus. +Wir überprüfen nun, ob das empfangene Token alle Scopes enthält, die von dieser Abhängigkeit und deren Verwendern (einschließlich *Pfadoperationen*) gefordert werden. Andernfalls lösen wir eine `HTTPException` aus. Hierzu verwenden wir `security_scopes.scopes`, das eine `list`e mit allen diesen Scopes als `str` enthält. -{* ../../docs_src/security/tutorial005_an_py310.py hl[128:134] *} +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} -## Abhängigkeitsbaum und Scopes +## Abhängigkeitsbaum und Scopes { #dependency-tree-and-scopes } Sehen wir uns diesen Abhängigkeitsbaum und die Scopes noch einmal an. @@ -223,7 +223,7 @@ Alles hängt von den „Scopes“ ab, die in jeder *Pfadoperation* und jeder Abh /// -## Weitere Details zu `SecurityScopes`. +## Weitere Details zu `SecurityScopes` { #more-details-about-securityscopes } Sie können `SecurityScopes` an jeder Stelle und an mehreren Stellen verwenden, es muss sich nicht in der „Wurzel“-Abhängigkeit befinden. @@ -233,7 +233,7 @@ Da die `SecurityScopes` alle von den Verwendern der Abhängigkeiten deklarierten Diese werden für jede *Pfadoperation* unabhängig überprüft. -## Testen Sie es +## Es testen { #check-it } Wenn Sie die API-Dokumentation öffnen, können Sie sich authentisieren und angeben, welche Scopes Sie autorisieren möchten. @@ -245,7 +245,7 @@ Und wenn Sie den Scope `me`, aber nicht den Scope `items` auswählen, können Si Das würde einer Drittanbieteranwendung passieren, die versucht, auf eine dieser *Pfadoperationen* mit einem Token zuzugreifen, das von einem Benutzer bereitgestellt wurde, abhängig davon, wie viele Berechtigungen der Benutzer dieser Anwendung erteilt hat. -## Über Integrationen von Drittanbietern +## Über Integrationen von Drittanbietern { #about-third-party-integrations } In diesem Beispiel verwenden wir den OAuth2-Flow „Password“. @@ -269,6 +269,6 @@ Aber am Ende implementieren sie denselben OAuth2-Standard. **FastAPI** enthält Werkzeuge für alle diese OAuth2-Authentifizierungs-Flows in `fastapi.security.oauth2`. -## `Security` in Dekorator-`dependencies` +## `Security` in Dekorator-`dependencies` { #security-in-decorator-dependencies } Auf die gleiche Weise können Sie eine `list`e von `Depends` im Parameter `dependencies` des Dekorators definieren (wie in [Abhängigkeiten in Pfadoperation-Dekoratoren](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} erläutert), Sie könnten auch dort `Security` mit `scopes` verwenden. diff --git a/docs/de/docs/advanced/settings.md b/docs/de/docs/advanced/settings.md index 00cc2ac37..ccd7f373d 100644 --- a/docs/de/docs/advanced/settings.md +++ b/docs/de/docs/advanced/settings.md @@ -1,4 +1,4 @@ -# Einstellungen und Umgebungsvariablen +# Einstellungen und Umgebungsvariablen { #settings-and-environment-variables } In vielen Fällen benötigt Ihre Anwendung möglicherweise einige externe Einstellungen oder Konfigurationen, zum Beispiel geheime Schlüssel, Datenbank-Anmeldeinformationen, Anmeldeinformationen für E-Mail-Dienste, usw. @@ -6,143 +6,25 @@ Die meisten dieser Einstellungen sind variabel (können sich ändern), wie z. B. Aus diesem Grund werden diese üblicherweise in Umgebungsvariablen bereitgestellt, die von der Anwendung gelesen werden. -## Umgebungsvariablen - /// tip | Tipp -Wenn Sie bereits wissen, was „Umgebungsvariablen“ sind und wie man sie verwendet, können Sie gerne mit dem nächsten Abschnitt weiter unten fortfahren. +Um Umgebungsvariablen zu verstehen, können Sie [Umgebungsvariablen](../environment-variables.md){.internal-link target=_blank} lesen. /// -Eine Umgebungsvariable (auch bekannt als „env var“) ist eine Variable, die sich außerhalb des Python-Codes im Betriebssystem befindet und von Ihrem Python-Code (oder auch von anderen Programmen) gelesen werden kann. - -Sie können Umgebungsvariablen in der Shell erstellen und verwenden, ohne Python zu benötigen: - -//// tab | Linux, macOS, Windows Bash - -
- -```console -// Sie könnten eine Umgebungsvariable MY_NAME erstellen mittels -$ export MY_NAME="Wade Wilson" - -// Dann könnten Sie diese mit anderen Programmen verwenden, etwa -$ echo "Hello $MY_NAME" - -Hello Wade Wilson -``` - -
- -//// - -//// tab | Windows PowerShell - -
- -```console -// Erstelle eine Umgebungsvariable MY_NAME -$ $Env:MY_NAME = "Wade Wilson" - -// Verwende sie mit anderen Programmen, etwa -$ echo "Hello $Env:MY_NAME" - -Hello Wade Wilson -``` - -
- -//// - -### Umgebungsvariablen mit Python auslesen - -Sie können Umgebungsvariablen auch außerhalb von Python im Terminal (oder mit einer anderen Methode) erstellen und diese dann mit Python auslesen. - -Sie könnten zum Beispiel eine Datei `main.py` haben mit: - -```Python hl_lines="3" -import os - -name = os.getenv("MY_NAME", "World") -print(f"Hello {name} from Python") -``` - -/// tip | Tipp - -Das zweite Argument für `os.getenv()` ist der zurückzugebende Defaultwert. - -Wenn nicht angegeben, ist er standardmäßig `None`. Hier übergeben wir `"World"` als Defaultwert. - -/// - -Dann könnten Sie dieses Python-Programm aufrufen: - -
- -```console -// Hier legen wir die Umgebungsvariable noch nicht fest -$ python main.py - -// Da wir die Umgebungsvariable nicht festgelegt haben, erhalten wir den Standardwert - -Hello World from Python - -// Aber wenn wir zuerst eine Umgebungsvariable erstellen -$ export MY_NAME="Wade Wilson" - -// Und dann das Programm erneut aufrufen -$ python main.py - -// Kann es jetzt die Umgebungsvariable lesen - -Hello Wade Wilson from Python -``` - -
- -Da Umgebungsvariablen außerhalb des Codes festgelegt, aber vom Code gelesen werden können und nicht zusammen mit den übrigen Dateien gespeichert (an `git` committet) werden müssen, werden sie häufig für Konfigurationen oder Einstellungen verwendet. - -Sie können eine Umgebungsvariable auch nur für einen bestimmten Programmaufruf erstellen, die nur für dieses Programm und nur für dessen Dauer verfügbar ist. - -Erstellen Sie diese dazu direkt vor dem Programm selbst, in derselben Zeile: - -
- -```console -// Erstelle eine Umgebungsvariable MY_NAME inline für diesen Programmaufruf -$ MY_NAME="Wade Wilson" python main.py - -// main.py kann jetzt diese Umgebungsvariable lesen - -Hello Wade Wilson from Python - -// Die Umgebungsvariable existiert danach nicht mehr -$ python main.py - -Hello World from Python -``` - -
- -/// tip | Tipp - -Weitere Informationen dazu finden Sie unter The Twelve-Factor App: Config. - -/// - -### Typen und Validierung +## Typen und Validierung { #types-and-validation } Diese Umgebungsvariablen können nur Text-Zeichenketten verarbeiten, da sie außerhalb von Python liegen und mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen wie Linux, Windows, macOS) kompatibel sein müssen. Das bedeutet, dass jeder in Python aus einer Umgebungsvariablen gelesene Wert ein `str` ist und jede Konvertierung in einen anderen Typ oder jede Validierung im Code erfolgen muss. -## Pydantic `Settings` +## Pydantic `Settings` { #pydantic-settings } Glücklicherweise bietet Pydantic ein großartiges Werkzeug zur Verarbeitung dieser Einstellungen, die von Umgebungsvariablen stammen, mit Pydantic: Settings Management. -### `pydantic-settings` installieren +### `pydantic-settings` installieren { #install-pydantic-settings } -Installieren Sie zunächst das Package `pydantic-settings`: +Stellen Sie zunächst sicher, dass Sie Ihre [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellt und aktiviert haben, und installieren Sie dann das Package `pydantic-settings`:
@@ -164,13 +46,13 @@ $ pip install "fastapi[all]"
-/// info +/// info | Info -In Pydantic v1 war das im Hauptpackage enthalten. Jetzt wird es als unabhängiges Package verteilt, sodass Sie wählen können, ob Sie es installieren möchten oder nicht, falls Sie die Funktionalität nicht benötigen. +In Pydantic v1 war es im Hauptpackage enthalten. Jetzt wird es als unabhängiges Package verteilt, sodass Sie wählen können, ob Sie es installieren möchten oder nicht, falls Sie die Funktionalität nicht benötigen. /// -### Das `Settings`-Objekt erstellen +### Das `Settings`-Objekt erstellen { #create-the-settings-object } Importieren Sie `BaseSettings` aus Pydantic und erstellen Sie eine Unterklasse, ganz ähnlich wie bei einem Pydantic-Modell. @@ -186,7 +68,7 @@ Sie können dieselben Validierungs-Funktionen und -Tools verwenden, die Sie für //// tab | Pydantic v1 -/// info +/// info | Info In Pydantic v1 würden Sie `BaseSettings` direkt von `pydantic` statt von `pydantic_settings` importieren. @@ -206,20 +88,20 @@ Wenn Sie dann eine Instanz dieser `Settings`-Klasse erstellen (in diesem Fall al Als Nächstes werden die Daten konvertiert und validiert. Wenn Sie also dieses `settings`-Objekt verwenden, verfügen Sie über Daten mit den von Ihnen deklarierten Typen (z. B. ist `items_per_user` ein `int`). -### `settings` verwenden +### `settings` verwenden { #use-the-settings } Dann können Sie das neue `settings`-Objekt in Ihrer Anwendung verwenden: {* ../../docs_src/settings/tutorial001.py hl[18:20] *} -### Den Server ausführen +### Den Server ausführen { #run-the-server } Als Nächstes würden Sie den Server ausführen und die Konfigurationen als Umgebungsvariablen übergeben. Sie könnten beispielsweise `ADMIN_EMAIL` und `APP_NAME` festlegen mit:
```console -$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" uvicorn main:app +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -236,9 +118,9 @@ Und dann würde die Einstellung `admin_email` auf `"deadpool@example.com"` geset Der `app_name` wäre `"ChimichangApp"`. -Und `items_per_user` würde seinen Standardwert von `50` behalten. +Und `items_per_user` würde seinen Defaultwert von `50` behalten. -## Einstellungen in einem anderen Modul +## Einstellungen in einem anderen Modul { #settings-in-another-module } Sie könnten diese Einstellungen in eine andere Moduldatei einfügen, wie Sie in [Größere Anwendungen – mehrere Dateien](../tutorial/bigger-applications.md){.internal-link target=_blank} gesehen haben. @@ -256,13 +138,13 @@ Sie benötigen außerdem eine Datei `__init__.py`, wie in [Größere Anwendungen /// -## Einstellungen in einer Abhängigkeit +## Einstellungen in einer Abhängigkeit { #settings-in-a-dependency } In manchen Fällen kann es nützlich sein, die Einstellungen mit einer Abhängigkeit bereitzustellen, anstatt ein globales Objekt `settings` zu haben, das überall verwendet wird. Dies könnte besonders beim Testen nützlich sein, da es sehr einfach ist, eine Abhängigkeit mit Ihren eigenen benutzerdefinierten Einstellungen zu überschreiben. -### Die Konfigurationsdatei +### Die Konfigurationsdatei { #the-config-file } Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen: @@ -270,7 +152,7 @@ Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen: Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen. -### Die Haupt-Anwendungsdatei +### Die Haupt-Anwendungsdatei { #the-main-app-file } Jetzt erstellen wir eine Abhängigkeit, die ein neues `config.Settings()` zurückgibt. @@ -288,7 +170,7 @@ Und dann können wir das von der *Pfadoperation-Funktion* als Abhängigkeit einf {* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} -### Einstellungen und Tests +### Einstellungen und Tests { #settings-and-testing } Dann wäre es sehr einfach, beim Testen ein anderes Einstellungsobjekt bereitzustellen, indem man eine Abhängigkeitsüberschreibung für `get_settings` erstellt: @@ -298,7 +180,7 @@ Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_ema Dann können wir testen, ob das verwendet wird. -## Lesen einer `.env`-Datei +## Lesen einer `.env`-Datei { #reading-a-env-file } Wenn Sie viele Einstellungen haben, die sich möglicherweise oft ändern, vielleicht in verschiedenen Umgebungen, kann es nützlich sein, diese in eine Datei zu schreiben und sie dann daraus zu lesen, als wären sie Umgebungsvariablen. @@ -320,7 +202,7 @@ Damit das funktioniert, müssen Sie `pip install python-dotenv` ausführen. /// -### Die `.env`-Datei +### Die `.env`-Datei { #the-env-file } Sie könnten eine `.env`-Datei haben, mit: @@ -329,7 +211,7 @@ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" ``` -### Einstellungen aus `.env` lesen +### Einstellungen aus `.env` lesen { #read-settings-from-env } Und dann aktualisieren Sie Ihre `config.py` mit: @@ -339,7 +221,7 @@ Und dann aktualisieren Sie Ihre `config.py` mit: /// tip | Tipp -Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter Pydantic: Configuration. +Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter Pydantic: Concepts: Configuration. /// @@ -357,17 +239,17 @@ Die Klasse `Config` wird nur für die Pydantic-Konfiguration verwendet. Weitere //// -/// info +/// info | Info -In Pydantic Version 1 erfolgte die Konfiguration in einer internen Klasse `Config`, in Pydantic Version 2 erfolgt sie in einem Attribut `model_config`. Dieses Attribut akzeptiert ein `dict`. Um automatische Codevervollständigung und Inline-Fehlerberichte zu erhalten, können Sie `SettingsConfigDict` importieren und verwenden, um dieses `dict` zu definieren. +In Pydantic Version 1 erfolgte die Konfiguration in einer internen Klasse `Config`, in Pydantic Version 2 erfolgt sie in einem Attribut `model_config`. Dieses Attribut akzeptiert ein `dict`. Um automatische Codevervollständigung und Inline-Fehlerberichte zu erhalten, können Sie `SettingsConfigDict` importieren und verwenden, um dieses `dict` zu definieren. /// Hier definieren wir die Konfiguration `env_file` innerhalb Ihrer Pydantic-`Settings`-Klasse und setzen den Wert auf den Dateinamen mit der dotenv-Datei, die wir verwenden möchten. -### Die `Settings` nur einmal laden mittels `lru_cache` +### Die `Settings` nur einmal laden mittels `lru_cache` { #creating-the-settings-only-once-with-lru-cache } -Das Lesen einer Datei von der Festplatte ist normalerweise ein kostspieliger (langsamer) Vorgang, daher möchten Sie ihn wahrscheinlich nur einmal ausführen und dann dasselbe Einstellungsobjekt erneut verwenden, anstatt es für jeden Request zu lesen. +Das Lesen einer Datei von der Festplatte ist normalerweise ein kostspieliger (langsamer) Vorgang, daher möchten Sie ihn wahrscheinlich nur einmal ausführen und dann dasselbe Einstellungsobjekt erneut verwenden, anstatt es für jeden Request zu lesen. Aber jedes Mal, wenn wir ausführen: @@ -392,7 +274,7 @@ Da wir jedoch den `@lru_cache`-Dekorator oben verwenden, wird das `Settings`-Obj Dann wird bei allen nachfolgenden Aufrufen von `get_settings()`, in den Abhängigkeiten für darauffolgende Requests, dasselbe Objekt zurückgegeben, das beim ersten Aufruf zurückgegeben wurde, anstatt den Code von `get_settings()` erneut auszuführen und ein neues `Settings`-Objekt zu erstellen. -#### Technische Details zu `lru_cache` +#### Technische Details zu `lru_cache` { #lru-cache-technical-details } `@lru_cache` ändert die Funktion, die es dekoriert, dahingehend, denselben Wert zurückzugeben, der beim ersten Mal zurückgegeben wurde, anstatt ihn erneut zu berechnen und den Code der Funktion jedes Mal auszuführen. @@ -413,7 +295,7 @@ sequenceDiagram participant code as Code participant function as say_hi() -participant execute as Funktion ausgeführt +participant execute as Funktion ausführen rect rgba(0, 255, 0, .1) code ->> function: say_hi(name="Camila") @@ -455,7 +337,7 @@ Auf diese Weise verhält es sich fast so, als wäre es nur eine globale Variable `@lru_cache` ist Teil von `functools`, welches Teil von Pythons Standardbibliothek ist. Weitere Informationen dazu finden Sie in der Python Dokumentation für `@lru_cache`. -## Zusammenfassung +## Zusammenfassung { #recap } Mit Pydantic Settings können Sie die Einstellungen oder Konfigurationen für Ihre Anwendung verwalten und dabei die gesamte Leistungsfähigkeit der Pydantic-Modelle nutzen. diff --git a/docs/de/docs/advanced/sub-applications.md b/docs/de/docs/advanced/sub-applications.md index f123147b3..d634aac23 100644 --- a/docs/de/docs/advanced/sub-applications.md +++ b/docs/de/docs/advanced/sub-applications.md @@ -1,41 +1,41 @@ -# Unteranwendungen – Mounts +# Unteranwendungen – Mounts { #sub-applications-mounts } Wenn Sie zwei unabhängige FastAPI-Anwendungen mit deren eigenen unabhängigen OpenAPI und deren eigenen Dokumentationsoberflächen benötigen, können Sie eine Hauptanwendung haben und dann eine (oder mehrere) Unteranwendung(en) „mounten“. -## Mounten einer **FastAPI**-Anwendung +## Eine **FastAPI**-Anwendung mounten { #mounting-a-fastapi-application } „Mounten“ („Einhängen“) bedeutet das Hinzufügen einer völlig „unabhängigen“ Anwendung an einem bestimmten Pfad, die sich dann um die Handhabung aller unter diesem Pfad liegenden _Pfadoperationen_ kümmert, welche in dieser Unteranwendung deklariert sind. -### Hauptanwendung +### Hauptanwendung { #top-level-application } Erstellen Sie zunächst die Hauptanwendung **FastAPI** und deren *Pfadoperationen*: -{* ../../docs_src/sub_applications/tutorial001.py hl[3,6:8] *} +{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *} -### Unteranwendung +### Unteranwendung { #sub-application } Erstellen Sie dann Ihre Unteranwendung und deren *Pfadoperationen*. Diese Unteranwendung ist nur eine weitere Standard-FastAPI-Anwendung, aber diese wird „gemountet“: -{* ../../docs_src/sub_applications/tutorial001.py hl[11,14:16] *} +{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *} -### Die Unteranwendung mounten +### Die Unteranwendung mounten { #mount-the-sub-application } Mounten Sie in Ihrer Top-Level-Anwendung `app` die Unteranwendung `subapi`. In diesem Fall wird sie im Pfad `/subapi` gemountet: -{* ../../docs_src/sub_applications/tutorial001.py hl[11,19] *} +{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *} -### Es in der automatischen API-Dokumentation betrachten +### Die automatische API-Dokumentation testen { #check-the-automatic-api-docs } -Führen Sie nun `uvicorn` mit der Hauptanwendung aus. Wenn Ihre Datei `main.py` lautet, wäre das: +Führen Sie nun den `fastapi`-Befehl mit Ihrer Datei aus:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -56,7 +56,7 @@ Sie sehen die automatische API-Dokumentation für die Unteranwendung, welche nur Wenn Sie versuchen, mit einer der beiden Benutzeroberflächen zu interagieren, funktionieren diese ordnungsgemäß, da der Browser mit jeder spezifischen Anwendung oder Unteranwendung kommunizieren kann. -### Technische Details: `root_path` +### Technische Details: `root_path` { #technical-details-root-path } Wenn Sie eine Unteranwendung wie oben beschrieben mounten, kümmert sich FastAPI darum, den Mount-Pfad für die Unteranwendung zu kommunizieren, mithilfe eines Mechanismus aus der ASGI-Spezifikation namens `root_path`. diff --git a/docs/de/docs/advanced/templates.md b/docs/de/docs/advanced/templates.md index 136ce6027..fdaeb3413 100644 --- a/docs/de/docs/advanced/templates.md +++ b/docs/de/docs/advanced/templates.md @@ -1,4 +1,4 @@ -# Templates +# Templates { #templates } Sie können jede gewünschte Template-Engine mit **FastAPI** verwenden. @@ -6,9 +6,9 @@ Eine häufige Wahl ist Jinja2, dasselbe, was auch von Flask und anderen Tools ve Es gibt Werkzeuge zur einfachen Konfiguration, die Sie direkt in Ihrer **FastAPI**-Anwendung verwenden können (bereitgestellt von Starlette). -## Abhängigkeiten installieren +## Abhängigkeiten installieren { #install-dependencies } -Installieren Sie `jinja2`: +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und `jinja2` installieren:
@@ -20,12 +20,12 @@ $ pip install jinja2
-## Verwendung von `Jinja2Templates` +## `Jinja2Templates` verwenden { #using-jinja2templates } * Importieren Sie `Jinja2Templates`. * Erstellen Sie ein `templates`-Objekt, das Sie später wiederverwenden können. -* Deklarieren Sie einen `Request`-Parameter in der *Pfadoperation*, welcher ein Template zurückgibt. -* Verwenden Sie die von Ihnen erstellten `templates`, um eine `TemplateResponse` zu rendern und zurückzugeben, übergeben Sie den Namen des Templates, das Requestobjekt und ein „Kontext“-Dictionary mit Schlüssel-Wert-Paaren, die innerhalb des Jinja2-Templates verwendet werden sollen. +* Deklarieren Sie einen `Request`-Parameter in der *Pfadoperation*, welcher ein Template zurückgibt. +* Verwenden Sie die von Ihnen erstellten `templates`, um eine `TemplateResponse` zu rendern und zurückzugeben, übergeben Sie den Namen des Templates, das Requestobjekt und ein „Kontext“-Dictionary mit Schlüssel-Wert-Paaren, die innerhalb des Jinja2-Templates verwendet werden sollen. {* ../../docs_src/templates/tutorial001.py hl[4,11,15:18] *} @@ -39,7 +39,7 @@ Außerdem wurde in früheren Versionen das `request`-Objekt als Teil der Schlüs /// tip | Tipp -Durch die Deklaration von `response_class=HTMLResponse` kann die Dokumentationsoberfläche erkennen, dass die Response HTML sein wird. +Durch die Deklaration von `response_class=HTMLResponse` kann die Dokumentationsoberfläche erkennen, dass die Response HTML sein wird. /// @@ -47,11 +47,11 @@ Durch die Deklaration von `response_class=HTMLResponse` kann die Dokumentationso Sie können auch `from starlette.templating import Jinja2Templates` verwenden. -**FastAPI** bietet dasselbe `starlette.templating` auch via `fastapi.templating` an, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber direkt von Starlette. Das Gleiche gilt für `Request` und `StaticFiles`. +**FastAPI** bietet dasselbe `starlette.templating` auch via `fastapi.templating` an, als Annehmlichkeit für Sie, den Entwickler. Aber die meisten der verfügbaren Responses kommen direkt von Starlette. Das Gleiche gilt für `Request` und `StaticFiles`. /// -## Templates erstellen +## Templates erstellen { #writing-templates } Dann können Sie unter `templates/item.html` ein Template erstellen, mit z. B. folgendem Inhalt: @@ -59,7 +59,7 @@ Dann können Sie unter `templates/item.html` ein Template erstellen, mit z. B. f {!../../docs_src/templates/templates/item.html!} ``` -### Template-Kontextwerte +### Template-Kontextwerte { #template-context-values } Im HTML, welches enthält: @@ -83,7 +83,7 @@ Mit beispielsweise einer ID `42` würde das wie folgt gerendert werden: Item ID: 42 ``` -### Template-`url_for`-Argumente +### Template-`url_for`-Argumente { #template-url-for-arguments } Sie können `url_for()` auch innerhalb des Templates verwenden, es nimmt als Argumente dieselben Argumente, die von Ihrer *Pfadoperation-Funktion* verwendet werden. @@ -105,7 +105,7 @@ Mit beispielsweise der ID `42` würde dies Folgendes ergeben: ``` -## Templates und statische Dateien +## Templates und statische Dateien { #templates-and-static-files } Sie können `url_for()` innerhalb des Templates auch beispielsweise mit den `StaticFiles` verwenden, die Sie mit `name="static"` gemountet haben. @@ -119,8 +119,8 @@ In diesem Beispiel würde das zu einer CSS-Datei unter `static/styles.css` verli {!../../docs_src/templates/static/styles.css!} ``` -Und da Sie `StaticFiles` verwenden, wird diese CSS-Datei automatisch von Ihrer **FastAPI**-Anwendung unter der URL `/static/styles.css` bereitgestellt. +Und da Sie `StaticFiles` verwenden, wird diese CSS-Datei automatisch von Ihrer **FastAPI**-Anwendung unter der URL `/static/styles.css` ausgeliefert. -## Mehr Details +## Mehr Details { #more-details } -Weitere Informationen, einschließlich, wie man Templates testet, finden Sie in der Starlette Dokumentation zu Templates. +Weitere Informationen, einschließlich, wie man Templates testet, finden Sie in Starlettes Dokumentation zu Templates. diff --git a/docs/de/docs/advanced/testing-dependencies.md b/docs/de/docs/advanced/testing-dependencies.md index 8299d6dd7..4fc653f77 100644 --- a/docs/de/docs/advanced/testing-dependencies.md +++ b/docs/de/docs/advanced/testing-dependencies.md @@ -1,6 +1,6 @@ -# Testen mit Ersatz für Abhängigkeiten +# Testen mit Überschreibungen für Abhängigkeiten { #testing-dependencies-with-overrides } -## Abhängigkeiten beim Testen überschreiben +## Abhängigkeiten beim Testen überschreiben { #overriding-dependencies-during-testing } Es gibt einige Szenarien, in denen Sie beim Testen möglicherweise eine Abhängigkeit überschreiben möchten. @@ -8,21 +8,21 @@ Sie möchten nicht, dass die ursprüngliche Abhängigkeit ausgeführt wird (und Stattdessen möchten Sie eine andere Abhängigkeit bereitstellen, die nur während Tests (möglicherweise nur bei einigen bestimmten Tests) verwendet wird und einen Wert bereitstellt, der dort verwendet werden kann, wo der Wert der ursprünglichen Abhängigkeit verwendet wurde. -### Anwendungsfälle: Externer Service +### Anwendungsfälle: Externer Service { #use-cases-external-service } Ein Beispiel könnte sein, dass Sie einen externen Authentifizierungsanbieter haben, mit dem Sie sich verbinden müssen. Sie senden ihm ein Token und er gibt einen authentifizierten Benutzer zurück. -Dieser Anbieter berechnet Ihnen möglicherweise Gebühren pro Anfrage, und der Aufruf könnte etwas länger dauern, als wenn Sie einen vordefinierten Scheinbenutzer für Tests hätten. +Dieser Anbieter berechnet Ihnen möglicherweise Gebühren pro Request, und der Aufruf könnte etwas länger dauern, als wenn Sie einen vordefinierten Mock-Benutzer für Tests hätten. Sie möchten den externen Anbieter wahrscheinlich einmal testen, ihn aber nicht unbedingt bei jedem weiteren ausgeführten Test aufrufen. -In diesem Fall können Sie die Abhängigkeit, die diesen Anbieter aufruft, überschreiben und eine benutzerdefinierte Abhängigkeit verwenden, die einen Scheinbenutzer zurückgibt, nur für Ihre Tests. +In diesem Fall können Sie die Abhängigkeit, die diesen Anbieter aufruft, überschreiben und eine benutzerdefinierte Abhängigkeit verwenden, die einen Mock-Benutzer zurückgibt, nur für Ihre Tests. -### Verwenden Sie das Attribut `app.dependency_overrides`. +### Das Attribut `app.dependency_overrides` verwenden { #use-the-app-dependency-overrides-attribute } -Für diese Fälle verfügt Ihre **FastAPI**-Anwendung über das Attribut `app.dependency_overrides`, bei diesem handelt sich um ein einfaches `dict`. +Für diese Fälle verfügt Ihre **FastAPI**-Anwendung über das Attribut `app.dependency_overrides`, bei diesem handelt sich um ein einfaches `dict`. Um eine Abhängigkeit für das Testen zu überschreiben, geben Sie als Schlüssel die ursprüngliche Abhängigkeit (eine Funktion) und als Wert Ihre Überschreibung der Abhängigkeit (eine andere Funktion) ein. @@ -46,6 +46,7 @@ Anschließend können Sie Ihre Überschreibungen zurücksetzen (entfernen), inde app.dependency_overrides = {} ``` + /// tip | Tipp Wenn Sie eine Abhängigkeit nur während einiger Tests überschreiben möchten, können Sie die Überschreibung zu Beginn des Tests (innerhalb der Testfunktion) festlegen und am Ende (am Ende der Testfunktion) zurücksetzen. diff --git a/docs/de/docs/advanced/testing-events.md b/docs/de/docs/advanced/testing-events.md index 05d6bcb2b..1a68b7714 100644 --- a/docs/de/docs/advanced/testing-events.md +++ b/docs/de/docs/advanced/testing-events.md @@ -1,5 +1,12 @@ -# Events testen: Hochfahren – Herunterfahren +# Events testen: Lifespan und Startup – Shutdown { #testing-events-lifespan-and-startup-shutdown } -Wenn Sie in Ihren Tests Ihre Event-Handler (`startup` und `shutdown`) ausführen wollen, können Sie den `TestClient` mit einer `with`-Anweisung verwenden: +Wenn Sie `lifespan` in Ihren Tests ausführen müssen, können Sie den `TestClient` mit einer `with`-Anweisung verwenden: + +{* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *} + + +Sie können mehr Details unter [„Lifespan in Tests ausführen in der offiziellen Starlette-Dokumentation.“](https://www.starlette.io/lifespan/#running-lifespan-in-tests) nachlesen. + +Für die deprecateten Events `startup` und `shutdown` können Sie den `TestClient` wie folgt verwenden: {* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *} diff --git a/docs/de/docs/advanced/testing-websockets.md b/docs/de/docs/advanced/testing-websockets.md index 5932e6d6a..a71310cbf 100644 --- a/docs/de/docs/advanced/testing-websockets.md +++ b/docs/de/docs/advanced/testing-websockets.md @@ -1,4 +1,4 @@ -# WebSockets testen +# WebSockets testen { #testing-websockets } Sie können den schon bekannten `TestClient` zum Testen von WebSockets verwenden. @@ -8,6 +8,6 @@ Dazu verwenden Sie den `TestClient` in einer `with`-Anweisung, eine Verbindung z /// note | Hinweis -Weitere Informationen finden Sie in der Starlette-Dokumentation zum Testen von WebSockets. +Weitere Informationen finden Sie in Starlettes Dokumentation zum Testen von WebSockets. /// diff --git a/docs/de/docs/advanced/using-request-directly.md b/docs/de/docs/advanced/using-request-directly.md index a0a5ec1ab..7782237ec 100644 --- a/docs/de/docs/advanced/using-request-directly.md +++ b/docs/de/docs/advanced/using-request-directly.md @@ -1,6 +1,6 @@ -# Den Request direkt verwenden +# Den Request direkt verwenden { #using-the-request-directly } -Bisher haben Sie die Teile des Requests, die Sie benötigen, mithilfe von deren Typen deklariert. +Bisher haben Sie die Teile des Requests, die Sie benötigen, mithilfe von deren Typen deklariert. Daten nehmend von: @@ -13,9 +13,9 @@ Und indem Sie das tun, validiert **FastAPI** diese Daten, konvertiert sie und ge Es gibt jedoch Situationen, in denen Sie möglicherweise direkt auf das `Request`-Objekt zugreifen müssen. -## Details zum `Request`-Objekt +## Details zum `Request`-Objekt { #details-about-the-request-object } -Da **FastAPI** unter der Haube eigentlich **Starlette** ist, mit einer Ebene von mehreren Tools darüber, können Sie Starlette's `Request`-Objekt direkt verwenden, wenn Sie es benötigen. +Da **FastAPI** unter der Haube eigentlich **Starlette** ist, mit einer Ebene von mehreren Tools darüber, können Sie Starlettes `Request`-Objekt direkt verwenden, wenn Sie es benötigen. Das bedeutet allerdings auch, dass, wenn Sie Daten direkt vom `Request`-Objekt nehmen (z. B. dessen Body lesen), diese von FastAPI nicht validiert, konvertiert oder dokumentiert werden (mit OpenAPI, für die automatische API-Benutzeroberfläche). @@ -23,7 +23,7 @@ Obwohl jeder andere normal deklarierte Parameter (z. B. der Body, mit einem Pyda Es gibt jedoch bestimmte Fälle, in denen es nützlich ist, auf das `Request`-Objekt zuzugreifen. -## Das `Request`-Objekt direkt verwenden +## Das `Request`-Objekt direkt verwenden { #use-the-request-object-directly } Angenommen, Sie möchten auf die IP-Adresse/den Host des Clients in Ihrer *Pfadoperation-Funktion* zugreifen. @@ -43,7 +43,7 @@ Auf die gleiche Weise können Sie wie gewohnt jeden anderen Parameter deklariere /// -## `Request`-Dokumentation +## `Request`-Dokumentation { #request-documentation } Weitere Details zum `Request`-Objekt finden Sie in der offiziellen Starlette-Dokumentation. diff --git a/docs/de/docs/advanced/websockets.md b/docs/de/docs/advanced/websockets.md index 020c20bc0..ad1f6f5b1 100644 --- a/docs/de/docs/advanced/websockets.md +++ b/docs/de/docs/advanced/websockets.md @@ -1,10 +1,10 @@ -# WebSockets +# WebSockets { #websockets } Sie können WebSockets mit **FastAPI** verwenden. -## `WebSockets` installieren +## `websockets` installieren { #install-websockets } -Zuerst müssen Sie `WebSockets` installieren: +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und `websockets` installieren (eine Python-Bibliothek, die die Verwendung des „WebSocket“-Protokolls erleichtert):
@@ -16,9 +16,9 @@ $ pip install websockets
-## WebSockets-Client +## WebSockets-Client { #websockets-client } -### In Produktion +### In Produktion { #in-production } In Ihrem Produktionssystem haben Sie wahrscheinlich ein Frontend, das mit einem modernen Framework wie React, Vue.js oder Angular erstellt wurde. @@ -36,11 +36,11 @@ Das ist natürlich nicht optimal und man würde das nicht in der Produktion mach In der Produktion hätten Sie eine der oben genannten Optionen. -Aber es ist die einfachste Möglichkeit, sich auf die Serverseite von WebSockets zu konzentrieren und ein funktionierendes Beispiel zu haben: +Aber es ist der einfachste Weg, sich auf die Serverseite von WebSockets zu konzentrieren und ein funktionierendes Beispiel zu haben: {* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *} -## Einen `websocket` erstellen +## Einen `websocket` erstellen { #create-a-websocket } Erstellen Sie in Ihrer **FastAPI**-Anwendung einen `websocket`: @@ -48,13 +48,13 @@ Erstellen Sie in Ihrer **FastAPI**-Anwendung einen `websocket`: /// note | Technische Details -Sie können auch `from starlette.websockets import WebSocket` verwenden. +Sie könnten auch `from starlette.websockets import WebSocket` verwenden. **FastAPI** stellt den gleichen `WebSocket` direkt zur Verfügung, als Annehmlichkeit für Sie, den Entwickler. Er kommt aber direkt von Starlette. /// -## Nachrichten erwarten und Nachrichten senden +## Nachrichten erwarten und Nachrichten senden { #await-for-messages-and-send-messages } In Ihrer WebSocket-Route können Sie Nachrichten `await`en und Nachrichten senden. @@ -62,14 +62,14 @@ In Ihrer WebSocket-Route können Sie Nachrichten `await`en und Nachrichten sende Sie können Binär-, Text- und JSON-Daten empfangen und senden. -## Es ausprobieren +## Es ausprobieren { #try-it } Wenn Ihre Datei `main.py` heißt, führen Sie Ihre Anwendung so aus:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -96,7 +96,7 @@ Sie können viele Nachrichten senden (und empfangen): Und alle verwenden dieselbe WebSocket-Verbindung. -## Verwendung von `Depends` und anderen +## Verwendung von `Depends` und anderen { #using-depends-and-others } In WebSocket-Endpunkten können Sie Folgendes aus `fastapi` importieren und verwenden: @@ -111,7 +111,7 @@ Diese funktionieren auf die gleiche Weise wie für andere FastAPI-Endpunkte/*Pfa {* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} -/// info +/// info | Info Da es sich um einen WebSocket handelt, macht es keinen Sinn, eine `HTTPException` auszulösen, stattdessen lösen wir eine `WebSocketException` aus. @@ -119,14 +119,14 @@ Sie können einen „Closing“-Code verwenden, aus den ```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -142,7 +142,7 @@ Dort können Sie einstellen: /// tip | Tipp -Beachten Sie, dass der Query-„Token“ von einer Abhängigkeit verarbeitet wird. +Beachten Sie, dass die Query `token` von einer Abhängigkeit verarbeitet wird. /// @@ -150,7 +150,7 @@ Damit können Sie den WebSocket verbinden und dann Nachrichten senden und empfan -## Verbindungsabbrüche und mehreren Clients handhaben +## Verbindungsabbrüche und mehrere Clients handhaben { #handling-disconnections-and-multiple-clients } Wenn eine WebSocket-Verbindung geschlossen wird, löst `await websocket.receive_text()` eine `WebSocketDisconnect`-Exception aus, die Sie dann wie in folgendem Beispiel abfangen und behandeln können. @@ -178,7 +178,7 @@ Wenn Sie etwas benötigen, das sich leicht in FastAPI integrieren lässt, aber r /// -## Mehr Informationen +## Mehr Informationen { #more-info } Weitere Informationen zu Optionen finden Sie in der Dokumentation von Starlette: diff --git a/docs/de/docs/advanced/wsgi.md b/docs/de/docs/advanced/wsgi.md index c0998a621..1de9739dd 100644 --- a/docs/de/docs/advanced/wsgi.md +++ b/docs/de/docs/advanced/wsgi.md @@ -1,10 +1,10 @@ -# WSGI inkludieren – Flask, Django und andere +# WSGI inkludieren – Flask, Django und andere { #including-wsgi-flask-django-others } Sie können WSGI-Anwendungen mounten, wie Sie es in [Unteranwendungen – Mounts](sub-applications.md){.internal-link target=_blank}, [Hinter einem Proxy](behind-a-proxy.md){.internal-link target=_blank} gesehen haben. Dazu können Sie die `WSGIMiddleware` verwenden und damit Ihre WSGI-Anwendung wrappen, zum Beispiel Flask, Django usw. -## `WSGIMiddleware` verwenden +## `WSGIMiddleware` verwenden { #using-wsgimiddleware } Sie müssen `WSGIMiddleware` importieren. @@ -12,15 +12,15 @@ Wrappen Sie dann die WSGI-Anwendung (z. B. Flask) mit der Middleware. Und dann mounten Sie das auf einem Pfad. -{* ../../docs_src/wsgi/tutorial001.py hl[2:3,23] *} +{* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *} -## Es ansehen +## Es testen { #check-it } -Jetzt wird jede Anfrage unter dem Pfad `/v1/` von der Flask-Anwendung verarbeitet. +Jetzt wird jeder Request unter dem Pfad `/v1/` von der Flask-Anwendung verarbeitet. Und der Rest wird von **FastAPI** gehandhabt. -Wenn Sie das mit Uvicorn ausführen und auf http://localhost:8000/v1/ gehen, sehen Sie die Response von Flask: +Wenn Sie das ausführen und auf http://localhost:8000/v1/ gehen, sehen Sie die Response von Flask: ```txt Hello, World from Flask! diff --git a/docs/de/docs/alternatives.md b/docs/de/docs/alternatives.md index 611315501..15c0719fb 100644 --- a/docs/de/docs/alternatives.md +++ b/docs/de/docs/alternatives.md @@ -1,8 +1,8 @@ -# Alternativen, Inspiration und Vergleiche +# Alternativen, Inspiration und Vergleiche { #alternatives-inspiration-and-comparisons } -Was hat **FastAPI** inspiriert, ein Vergleich zu Alternativen, und was FastAPI von diesen gelernt hat. +Was hat **FastAPI** inspiriert, wie es sich im Vergleich zu Alternativen verhält und was es von ihnen gelernt hat. -## Einführung +## Einführung { #intro } **FastAPI** würde ohne die frühere Arbeit anderer nicht existieren. @@ -12,17 +12,17 @@ Ich habe die Schaffung eines neuen Frameworks viele Jahre lang vermieden. Zuerst Aber irgendwann gab es keine andere Möglichkeit, als etwas zu schaffen, das all diese Funktionen bereitstellte, die besten Ideen früherer Tools aufnahm und diese auf die bestmögliche Weise kombinierte, wobei Sprachfunktionen verwendet wurden, die vorher noch nicht einmal verfügbar waren (Python 3.6+ Typhinweise). -## Vorherige Tools +## Vorherige Tools { #previous-tools } -### Django +### Django { #django } Es ist das beliebteste Python-Framework und genießt großes Vertrauen. Es wird zum Aufbau von Systemen wie Instagram verwendet. -Ist relativ eng mit relationalen Datenbanken (wie MySQL oder PostgreSQL) gekoppelt, daher ist es nicht sehr einfach, eine NoSQL-Datenbank (wie Couchbase, MongoDB, Cassandra, usw.) als Hauptspeicherengine zu verwenden. +Es ist relativ eng mit relationalen Datenbanken (wie MySQL oder PostgreSQL) gekoppelt, daher ist es nicht sehr einfach, eine NoSQL-Datenbank (wie Couchbase, MongoDB, Cassandra, usw.) als Hauptspeicherengine zu verwenden. -Es wurde erstellt, um den HTML-Code im Backend zu generieren, nicht um APIs zu erstellen, die von einem modernen Frontend (wie React, Vue.js und Angular) oder von anderen Systemen (wie IoT-Geräten) verwendet werden, um mit ihm zu kommunizieren. +Es wurde erstellt, um den HTML-Code im Backend zu generieren, nicht um APIs zu erstellen, die von einem modernen Frontend (wie React, Vue.js und Angular) oder von anderen Systemen (wie IoT-Geräten) verwendet werden, um mit ihm zu kommunizieren. -### Django REST Framework +### Django REST Framework { #django-rest-framework } Das Django REST Framework wurde als flexibles Toolkit zum Erstellen von Web-APIs unter Verwendung von Django entwickelt, um dessen API-Möglichkeiten zu verbessern. @@ -42,7 +42,7 @@ Eine automatische API-Dokumentationsoberfläche zu haben. /// -### Flask +### Flask { #flask } Flask ist ein „Mikroframework“, es enthält weder Datenbankintegration noch viele der Dinge, die standardmäßig in Django enthalten sind. @@ -64,7 +64,7 @@ Ein Mikroframework zu sein. Es einfach zu machen, die benötigten Tools und Teil /// -### Requests +### Requests { #requests } **FastAPI** ist eigentlich keine Alternative zu **Requests**. Der Umfang der beiden ist sehr unterschiedlich. @@ -82,7 +82,7 @@ Aus diesem Grund heißt es auf der offiziellen Website: > Requests ist eines der am häufigsten heruntergeladenen Python-Packages aller Zeiten -Die Art und Weise, wie Sie es verwenden, ist sehr einfach. Um beispielsweise einen `GET`-Request zu machen, würden Sie schreiben: +Die Art und Weise, wie Sie es verwenden, ist sehr einfach. Um beispielsweise einen `GET`-Request zu machen, würden Sie schreiben: ```Python response = requests.get("http://example.com/some/url") @@ -106,7 +106,7 @@ Sehen Sie sich die Ähnlichkeiten in `requests.get(...)` und `@app.get(...)` an. /// -### Swagger / OpenAPI +### Swagger / OpenAPI { #swagger-openapi } Die Hauptfunktion, die ich vom Django REST Framework haben wollte, war die automatische API-Dokumentation. @@ -131,13 +131,13 @@ Diese beiden wurden ausgewählt, weil sie ziemlich beliebt und stabil sind, aber /// -### Flask REST Frameworks +### Flask REST Frameworks { #flask-rest-frameworks } Es gibt mehrere Flask REST Frameworks, aber nachdem ich die Zeit und Arbeit investiert habe, sie zu untersuchen, habe ich festgestellt, dass viele nicht mehr unterstützt werden oder abgebrochen wurden und dass mehrere fortbestehende Probleme sie unpassend machten. -### Marshmallow +### Marshmallow { #marshmallow } -Eine der von API-Systemen benötigen Hauptfunktionen ist die Daten-„Serialisierung“, welche Daten aus dem Code (Python) entnimmt und in etwas umwandelt, was durch das Netzwerk gesendet werden kann. Beispielsweise das Konvertieren eines Objekts, welches Daten aus einer Datenbank enthält, in ein JSON-Objekt. Konvertieren von `datetime`-Objekten in Strings, usw. +Eine der von API-Systemen benötigten Hauptfunktionen ist die Daten-„Serialisierung“, welche Daten aus dem Code (Python) entnimmt und in etwas umwandelt, was durch das Netzwerk gesendet werden kann. Beispielsweise das Konvertieren eines Objekts, welches Daten aus einer Datenbank enthält, in ein JSON-Objekt. Konvertieren von `datetime`-Objekten in Strings, usw. Eine weitere wichtige Funktion, benötigt von APIs, ist die Datenvalidierung, welche sicherstellt, dass die Daten unter gegebenen Umständen gültig sind. Zum Beispiel, dass ein Feld ein `int` ist und kein zufälliger String. Das ist besonders nützlich für hereinkommende Daten. @@ -145,7 +145,7 @@ Ohne ein Datenvalidierungssystem müssten Sie alle Prüfungen manuell im Code du Für diese Funktionen wurde Marshmallow entwickelt. Es ist eine großartige Bibliothek und ich habe sie schon oft genutzt. -Aber sie wurde erstellt, bevor Typhinweise in Python existierten. Um also ein Schema zu definieren, müssen Sie bestimmte Werkzeuge und Klassen verwenden, die von Marshmallow bereitgestellt werden. +Aber sie wurde erstellt, bevor Typhinweise in Python existierten. Um also ein Schema zu definieren, müssen Sie bestimmte Werkzeuge und Klassen verwenden, die von Marshmallow bereitgestellt werden. /// check | Inspirierte **FastAPI** @@ -153,7 +153,7 @@ Code zu verwenden, um „Schemas“ zu definieren, welche Datentypen und Validie /// -### Webargs +### Webargs { #webargs } Eine weitere wichtige Funktion, die von APIs benötigt wird, ist das Parsen von Daten aus eingehenden Requests. @@ -163,7 +163,7 @@ Es verwendet unter der Haube Marshmallow, um die Datenvalidierung durchzuführen Es ist ein großartiges Tool und ich habe es auch oft verwendet, bevor ich **FastAPI** hatte. -/// info +/// info | Info Webargs wurde von denselben Marshmallow-Entwicklern erstellt. @@ -175,7 +175,7 @@ Eingehende Requestdaten automatisch zu validieren. /// -### APISpec +### APISpec { #apispec } Marshmallow und Webargs bieten Validierung, Parsen und Serialisierung als Plugins. @@ -193,7 +193,7 @@ Aber dann haben wir wieder das Problem einer Mikrosyntax innerhalb eines Python- Der Texteditor kann dabei nicht viel helfen. Und wenn wir Parameter oder Marshmallow-Schemas ändern und vergessen, auch den YAML-Docstring zu ändern, wäre das generierte Schema veraltet. -/// info +/// info | Info APISpec wurde von denselben Marshmallow-Entwicklern erstellt. @@ -205,7 +205,7 @@ Den offenen Standard für APIs, OpenAPI, zu unterstützen. /// -### Flask-apispec +### Flask-apispec { #flask-apispec } Hierbei handelt es sich um ein Flask-Plugin, welches Webargs, Marshmallow und APISpec miteinander verbindet. @@ -225,7 +225,7 @@ Die Verwendung führte zur Entwicklung mehrerer Flask-Full-Stack-Generatoren. Di Und dieselben Full-Stack-Generatoren bildeten die Basis der [**FastAPI**-Projektgeneratoren](project-generation.md){.internal-link target=_blank}. -/// info +/// info | Info Flask-apispec wurde von denselben Marshmallow-Entwicklern erstellt. @@ -237,7 +237,7 @@ Das OpenAPI-Schema automatisch zu generieren, aus demselben Code, welcher die Se /// -### NestJS (und Angular) +### NestJS (und Angular) { #nestjs-and-angular } Dies ist nicht einmal Python, NestJS ist ein von Angular inspiriertes JavaScript (TypeScript) NodeJS Framework. @@ -249,7 +249,7 @@ Da die Parameter mit TypeScript-Typen beschrieben werden (ähnlich den Python-Ty Da TypeScript-Daten jedoch nach der Kompilierung nach JavaScript nicht erhalten bleiben, können die Typen nicht gleichzeitig die Validierung, Serialisierung und Dokumentation definieren. Aus diesem Grund und aufgrund einiger Designentscheidungen ist es für die Validierung, Serialisierung und automatische Schemagenerierung erforderlich, an vielen Stellen Dekoratoren hinzuzufügen. Es wird also ziemlich ausführlich. -Es kann nicht sehr gut mit verschachtelten Modellen umgehen. Wenn es sich beim JSON-Body in der Anfrage also um ein JSON-Objekt mit inneren Feldern handelt, die wiederum verschachtelte JSON-Objekte sind, kann er nicht richtig dokumentiert und validiert werden. +Es kann nicht sehr gut mit verschachtelten Modellen umgehen. Wenn es sich beim JSON-Body im Request also um ein JSON-Objekt mit inneren Feldern handelt, die wiederum verschachtelte JSON-Objekte sind, kann er nicht richtig dokumentiert und validiert werden. /// check | Inspirierte **FastAPI** @@ -259,7 +259,7 @@ Python-Typen zu verwenden, um eine hervorragende Editorunterstützung zu erhalte /// -### Sanic +### Sanic { #sanic } Es war eines der ersten extrem schnellen Python-Frameworks, welches auf `asyncio` basierte. Es wurde so gestaltet, dass es Flask sehr ähnlich ist. @@ -279,11 +279,11 @@ Aus diesem Grund basiert **FastAPI** auf Starlette, da dieses das schnellste ver /// -### Falcon +### Falcon { #falcon } Falcon ist ein weiteres leistungsstarkes Python-Framework. Es ist minimalistisch konzipiert und dient als Grundlage für andere Frameworks wie Hug. -Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter empfangen, einen „Request“ und eine „Response“. Dann „lesen“ Sie Teile des Requests und „schreiben“ Teile der Response. Aufgrund dieses Designs ist es nicht möglich, Request-Parameter und -Bodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. +Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter empfangen, einen „Request“ und eine „Response“. Dann „lesen“ Sie Teile des Requests und „schreiben“ Teile der Response. Aufgrund dieses Designs ist es nicht möglich, Request-Parameter und -Bodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. Daher müssen Datenvalidierung, Serialisierung und Dokumentation im Code und nicht automatisch erfolgen. Oder sie müssen als Framework oberhalb von Falcon implementiert werden, so wie Hug. Dieselbe Unterscheidung findet auch in anderen Frameworks statt, die vom Design von Falcon inspiriert sind und ein Requestobjekt und ein Responseobjekt als Parameter haben. @@ -297,7 +297,7 @@ Obwohl er in FastAPI optional ist und hauptsächlich zum Festlegen von Headern, /// -### Molten +### Molten { #molten } Ich habe Molten in den ersten Phasen der Entwicklung von **FastAPI** entdeckt. Und es hat ganz ähnliche Ideen: @@ -321,7 +321,7 @@ Das hat tatsächlich dazu geführt, dass Teile von Pydantic aktualisiert wurden, /// -### Hug +### Hug { #hug } Hug war eines der ersten Frameworks, welches die Deklaration von API-Parametertypen mithilfe von Python-Typhinweisen implementierte. Das war eine großartige Idee, die andere Tools dazu inspirierte, dasselbe zu tun. @@ -335,9 +335,9 @@ Es verfügt über eine interessante, ungewöhnliche Funktion: Mit demselben Fram Da es auf dem bisherigen Standard für synchrone Python-Webframeworks (WSGI) basiert, kann es nicht mit Websockets und anderen Dingen umgehen, verfügt aber dennoch über eine hohe Performanz. -/// info +/// info | Info -Hug wurde von Timothy Crosley erstellt, dem gleichen Schöpfer von `isort`, einem großartigen Tool zum automatischen Sortieren von Importen in Python-Dateien. +Hug wurde von Timothy Crosley erstellt, demselben Schöpfer von `isort`, einem großartigen Tool zum automatischen Sortieren von Importen in Python-Dateien. /// @@ -351,7 +351,7 @@ Hug inspirierte **FastAPI** dazu, einen `response`-Parameter in Funktionen zu de /// -### APIStar (≦ 0.5) +### APIStar (≦ 0.5) { #apistar-0-5 } Kurz bevor ich mich entschied, **FastAPI** zu erstellen, fand ich den **APIStar**-Server. Er hatte fast alles, was ich suchte, und ein tolles Design. @@ -375,7 +375,7 @@ Es handelte sich nicht länger um ein API-Webframework, da sich der Entwickler a Jetzt handelt es sich bei APIStar um eine Reihe von Tools zur Validierung von OpenAPI-Spezifikationen, nicht um ein Webframework. -/// info +/// info | Info APIStar wurde von Tom Christie erstellt. Derselbe, welcher Folgendes erstellt hat: @@ -399,9 +399,9 @@ Ich betrachte **FastAPI** als einen „spirituellen Nachfolger“ von APIStar, w /// -## Verwendet von **FastAPI** +## Verwendet von **FastAPI** { #used-by-fastapi } -### Pydantic +### Pydantic { #pydantic } Pydantic ist eine Bibliothek zum Definieren von Datenvalidierung, Serialisierung und Dokumentation (unter Verwendung von JSON Schema) basierend auf Python-Typhinweisen. @@ -417,7 +417,7 @@ Die gesamte Datenvalidierung, Datenserialisierung und automatische Modelldokumen /// -### Starlette +### Starlette { #starlette } Starlette ist ein leichtgewichtiges ASGI-Framework/Toolkit, welches sich ideal für die Erstellung hochperformanter asynchroner Dienste eignet. @@ -428,9 +428,9 @@ Es bietet: * Eine sehr beeindruckende Leistung. * WebSocket-Unterstützung. * Hintergrundtasks im selben Prozess. -* Events für das Hoch- und Herunterfahren. +* Startup- und Shutdown-Events. * Testclient basierend auf HTTPX. -* CORS, GZip, statische Dateien, Streamende Responses. +* CORS, GZip, statische Dateien, Responses streamen. * Session- und Cookie-Unterstützung. * 100 % Testabdeckung. * 100 % Typannotierte Codebasis. @@ -462,7 +462,7 @@ Alles, was Sie also mit Starlette machen können, können Sie direkt mit **FastA /// -### Uvicorn +### Uvicorn { #uvicorn } Uvicorn ist ein blitzschneller ASGI-Server, der auf uvloop und httptools basiert. @@ -474,12 +474,12 @@ Es ist der empfohlene Server für Starlette und **FastAPI**. Hauptwebserver zum Ausführen von **FastAPI**-Anwendungen. -Sie können ihn mit Gunicorn kombinieren, um einen asynchronen Multiprozess-Server zu erhalten. +Sie können auch die Kommandozeilenoption `--workers` verwenden, um einen asynchronen Multiprozess-Server zu erhalten. Weitere Details finden Sie im Abschnitt [Deployment](deployment/index.md){.internal-link target=_blank}. /// -## Benchmarks und Geschwindigkeit +## Benchmarks und Geschwindigkeit { #benchmarks-and-speed } Um den Unterschied zwischen Uvicorn, Starlette und FastAPI zu verstehen, zu vergleichen und zu sehen, lesen Sie den Abschnitt über [Benchmarks](benchmarks.md){.internal-link target=_blank}. diff --git a/docs/de/docs/async.md b/docs/de/docs/async.md index ae1795b62..3dbd442e5 100644 --- a/docs/de/docs/async.md +++ b/docs/de/docs/async.md @@ -1,8 +1,8 @@ -# Nebenläufigkeit und async / await +# Nebenläufigkeit und async / await { #concurrency-and-async-await } Details zur `async def`-Syntax für *Pfadoperation-Funktionen* und Hintergrundinformationen zu asynchronem Code, Nebenläufigkeit und Parallelität. -## In Eile? +## In Eile? { #in-a-hurry } TL;DR: @@ -12,7 +12,7 @@ Wenn Sie Bibliotheken von Dritten verwenden, die mit `await` aufgerufen werden m results = await some_library() ``` -Dann deklarieren Sie Ihre *Pfadoperation-Funktionen* mit `async def` wie in: +Dann deklarieren Sie Ihre *Pfadoperation-Funktionen* mit `async def`, wie in: ```Python hl_lines="2" @app.get('/') @@ -21,7 +21,7 @@ async def read_results(): return results ``` -/// note +/// note | Hinweis Sie können `await` nur innerhalb von Funktionen verwenden, die mit `async def` erstellt wurden. @@ -29,7 +29,7 @@ Sie können `await` nur innerhalb von Funktionen verwenden, die mit `async def` --- -Wenn Sie eine Bibliothek eines Dritten verwenden, die mit etwas kommuniziert (einer Datenbank, einer API, dem Dateisystem, usw.) und welche die Verwendung von `await` nicht unterstützt (dies ist derzeit bei den meisten Datenbankbibliotheken der Fall), dann deklarieren Sie Ihre *Pfadoperation-Funktionen* ganz normal nur mit `def`, etwa: +Wenn Sie eine Bibliothek eines Dritten verwenden, die mit etwas kommuniziert (einer Datenbank, einer API, dem Dateisystem, usw.) und welche die Verwendung von `await` nicht unterstützt (dies ist derzeit bei den meisten Datenbankbibliotheken der Fall), dann deklarieren Sie Ihre *Pfadoperation-Funktionen* ganz normal nur mit `def`, wie in: ```Python hl_lines="2" @app.get('/') @@ -40,7 +40,7 @@ def results(): --- -Wenn Ihre Anwendung (irgendwie) mit nichts anderem kommunizieren und auf dessen Antwort warten muss, verwenden Sie `async def`. +Wenn Ihre Anwendung (irgendwie) nicht mit etwas anderem kommunizieren und auf dessen Antwort warten muss, verwenden Sie `async def`, auch wenn Sie `await` im Inneren nicht verwenden müssen. --- @@ -52,11 +52,11 @@ Wenn Sie sich unsicher sind, verwenden Sie einfach `def`. Wie dem auch sei, in jedem der oben genannten Fälle wird FastAPI immer noch asynchron arbeiten und extrem schnell sein. -Wenn Sie jedoch den oben genannten Schritten folgen, können einige Performance-Optimierungen vorgenommen werden. +Wenn Sie jedoch den oben genannten Schritten folgen, können einige Performanz-Optimierungen vorgenommen werden. -## Technische Details +## Technische Details { #technical-details } -Moderne Versionen von Python unterstützen **„asynchronen Code“** unter Verwendung sogenannter **„Coroutinen“** mithilfe der Syntax **`async`** und **`await`**. +Moderne Versionen von Python unterstützen **„asynchronen Code“** unter Verwendung sogenannter **„Coroutinen“** mithilfe der Syntax **`async` und `await`**. Nehmen wir obigen Satz in den folgenden Abschnitten Schritt für Schritt unter die Lupe: @@ -64,13 +64,13 @@ Nehmen wir obigen Satz in den folgenden Abschnitten Schritt für Schritt unter d * **`async` und `await`** * **Coroutinen** -## Asynchroner Code +## Asynchroner Code { #asynchronous-code } -Asynchroner Code bedeutet lediglich, dass die Sprache 💬 eine Möglichkeit hat, dem Computersystem / Programm 🤖 mitzuteilen, dass es 🤖 an einem bestimmten Punkt im Code darauf warten muss, dass *etwas anderes* irgendwo anders fertig wird. Nehmen wir an, *etwas anderes* ist hier „Langsam-Datei“ 📝. +Asynchroner Code bedeutet lediglich, dass die Sprache 💬 eine Möglichkeit hat, dem Computer / Programm 🤖 mitzuteilen, dass es 🤖 an einem bestimmten Punkt im Code darauf warten muss, dass *etwas anderes* irgendwo anders fertig wird. Nehmen wir an, *etwas anderes* ist hier „Langsam-Datei“ 📝. Während der Zeit, die „Langsam-Datei“ 📝 benötigt, kann das System also andere Aufgaben erledigen. -Dann kommt das System / Programm 🤖 bei jeder Gelegenheit zurück, wenn es entweder wieder wartet, oder wann immer es 🤖 die ganze Arbeit erledigt hat, die zu diesem Zeitpunkt zu tun war. Und es 🤖 wird nachschauen, ob eine der Aufgaben, auf die es gewartet hat, fertig damit ist, zu tun, was sie tun sollte. +Dann kommt der Computer / das Programm 🤖 bei jeder Gelegenheit zurück, weil es entweder wieder wartet oder wann immer es 🤖 die ganze Arbeit erledigt hat, die zu diesem Zeitpunkt zu tun war. Und es 🤖 wird nachschauen, ob eine der Aufgaben, auf die es gewartet hat, fertig ist. Dann nimmt es 🤖 die erste erledigte Aufgabe (sagen wir, unsere „Langsam-Datei“ 📝) und bearbeitet sie weiter. @@ -87,13 +87,13 @@ Das „Warten auf etwas anderes“ bezieht sich normalerweise auf I/O-Operationen verbraucht wird, nennt man dies auch „I/O-lastige“ („I/O bound“) Operationen. -„Asynchron“, sagt man, weil das Computersystem / Programm nicht mit einer langsamen Aufgabe „synchronisiert“ werden muss und nicht auf den genauen Moment warten muss, in dem die Aufgabe beendet ist, ohne dabei etwas zu tun, um schließlich das Ergebnis der Aufgabe zu übernehmen und die Arbeit fortsetzen zu können. +„Asynchron“, sagt man, weil der Computer / das Programm nicht mit einer langsamen Aufgabe „synchronisiert“ werden muss und nicht auf den genauen Moment warten muss, in dem die Aufgabe beendet ist, ohne dabei etwas zu tun, um schließlich das Ergebnis der Aufgabe zu übernehmen und die Arbeit fortsetzen zu können. -Da es sich stattdessen um ein „asynchrones“ System handelt, kann die Aufgabe nach Abschluss ein wenig (einige Mikrosekunden) in der Schlange warten, bis das System / Programm seine anderen Dinge erledigt hat und zurückkommt, um die Ergebnisse entgegenzunehmen und mit ihnen weiterzuarbeiten. +Da es sich stattdessen um ein „asynchrones“ System handelt, kann die Aufgabe nach Abschluss ein wenig (einige Mikrosekunden) in der Schlange warten, bis der Computer / das Programm seine anderen Dinge erledigt hat und zurückkommt, um die Ergebnisse entgegenzunehmen und mit ihnen weiterzuarbeiten. -Für „synchron“ (im Gegensatz zu „asynchron“) wird auch oft der Begriff „sequentiell“ verwendet, da das System / Programm alle Schritte in einer Sequenz („der Reihe nach“) ausführt, bevor es zu einer anderen Aufgabe wechselt, auch wenn diese Schritte mit Warten verbunden sind. +Für „synchron“ (im Gegensatz zu „asynchron“) wird auch oft der Begriff „sequentiell“ verwendet, da der Computer / das Programm alle Schritte in einer Sequenz („der Reihe nach“) ausführt, bevor es zu einer anderen Aufgabe wechselt, auch wenn diese Schritte mit Warten verbunden sind. -### Nebenläufigkeit und Hamburger +### Nebenläufigkeit und Hamburger { #concurrency-and-burgers } Diese oben beschriebene Idee von **asynchronem** Code wird manchmal auch **„Nebenläufigkeit“** genannt. Sie unterscheidet sich von **„Parallelität“**. @@ -103,7 +103,7 @@ Aber die Details zwischen *Nebenläufigkeit* und *Parallelität* sind ziemlich u Um den Unterschied zu erkennen, stellen Sie sich die folgende Geschichte über Hamburger vor: -### Nebenläufige Hamburger +### Nebenläufige Hamburger { #concurrent-burgers } Sie gehen mit Ihrem Schwarm Fastfood holen, stehen in der Schlange, während der Kassierer die Bestellungen der Leute vor Ihnen entgegennimmt. 😍 @@ -139,7 +139,7 @@ Sie und Ihr Schwarm essen die Burger und haben eine schöne Zeit. ✨ -/// info +/// info | Info Die wunderschönen Illustrationen stammen von Ketrina Thompson. 🎨 @@ -147,7 +147,7 @@ Die wunderschönen Illustrationen stammen von Ketrina Thompson. 🎨 @@ -233,15 +233,15 @@ Und man muss lange in der Schlange warten 🕙 sonst kommt man nicht an die Reih Sie würden Ihren Schwarm 😍 wahrscheinlich nicht mitnehmen wollen, um Besorgungen bei der Bank zu erledigen 🏦. -### Hamburger Schlussfolgerung +### Hamburger Schlussfolgerung { #burger-conclusion } -In diesem Szenario „Fast Food Burger mit Ihrem Schwarm“ ist es viel sinnvoller, ein nebenläufiges System zu haben ⏸🔀⏯, da viel gewartet wird 🕙. +In diesem Szenario „Fastfood-Burger mit Ihrem Schwarm“ ist es viel sinnvoller, ein nebenläufiges System zu haben ⏸🔀⏯, da viel gewartet wird 🕙. Das ist auch bei den meisten Webanwendungen der Fall. -Viele, viele Benutzer, aber Ihr Server wartet 🕙 darauf, dass deren nicht so gute Internetverbindungen die Requests übermitteln. +Viele, viele Benutzer, aber Ihr Server wartet 🕙 darauf, dass deren nicht so gute Internetverbindungen die Requests übermitteln. -Und dann warten 🕙, bis die Responses zurückkommen. +Und dann wieder warten 🕙, bis die Responses zurückkommen. Dieses „Warten“ 🕙 wird in Mikrosekunden gemessen, aber zusammenfassend lässt sich sagen, dass am Ende eine Menge gewartet wird. @@ -253,7 +253,7 @@ Und das ist das gleiche Leistungsniveau, das Sie mit **FastAPI** erhalten. Und da Sie Parallelität und Asynchronität gleichzeitig haben können, erzielen Sie eine höhere Performanz als die meisten getesteten NodeJS-Frameworks und sind mit Go auf Augenhöhe, einer kompilierten Sprache, die näher an C liegt (alles dank Starlette). -### Ist Nebenläufigkeit besser als Parallelität? +### Ist Nebenläufigkeit besser als Parallelität? { #is-concurrency-better-than-parallelism } Nein! Das ist nicht die Moral der Geschichte. @@ -290,17 +290,17 @@ Zum Beispiel: * **Maschinelles Lernen**: Normalerweise sind viele „Matrix“- und „Vektor“-Multiplikationen erforderlich. Stellen Sie sich eine riesige Tabelle mit Zahlen vor, in der Sie alle Zahlen gleichzeitig multiplizieren. * **Deep Learning**: Dies ist ein Teilgebiet des maschinellen Lernens, daher gilt das Gleiche. Es ist nur so, dass es nicht eine einzige Tabelle mit Zahlen zum Multiplizieren gibt, sondern eine riesige Menge davon, und in vielen Fällen verwendet man einen speziellen Prozessor, um diese Modelle zu erstellen und / oder zu verwenden. -### Nebenläufigkeit + Parallelität: Web + maschinelles Lernen +### Nebenläufigkeit + Parallelität: Web + maschinelles Lernen { #concurrency-parallelism-web-machine-learning } Mit **FastAPI** können Sie die Vorteile der Nebenläufigkeit nutzen, die in der Webentwicklung weit verbreitet ist (derselbe Hauptvorteil von NodeJS). -Sie können aber auch die Vorteile von Parallelität und Multiprocessing (Mehrere Prozesse werden parallel ausgeführt) für **CPU-lastige** Workloads wie in Systemen für maschinelles Lernen nutzen. +Sie können aber auch die Vorteile von Parallelität und Multiprocessing (mehrere Prozesse werden parallel ausgeführt) für **CPU-lastige** Workloads wie in Systemen für maschinelles Lernen nutzen. Dies und die einfache Tatsache, dass Python die Hauptsprache für **Data Science**, maschinelles Lernen und insbesondere Deep Learning ist, machen FastAPI zu einem sehr passenden Werkzeug für Web-APIs und Anwendungen für Data Science / maschinelles Lernen (neben vielen anderen). Wie Sie diese Parallelität in der Produktion erreichen, erfahren Sie im Abschnitt über [Deployment](deployment/index.md){.internal-link target=_blank}. -## `async` und `await`. +## `async` und `await` { #async-and-await } Moderne Versionen von Python verfügen über eine sehr intuitive Möglichkeit, asynchronen Code zu schreiben. Dadurch sieht es wie normaler „sequentieller“ Code aus und übernimmt im richtigen Moment das „Warten“ für Sie. @@ -316,16 +316,16 @@ Damit `await` funktioniert, muss es sich in einer Funktion befinden, die diese A ```Python hl_lines="1" async def get_burgers(number: int): - # Mach Sie hier etwas Asynchrones, um die Burger zu erstellen + # Mache hier etwas Asynchrones, um die Burger zu erstellen return burgers ``` ... statt mit `def`: ```Python hl_lines="2" -# Die ist nicht asynchron +# Dies ist nicht asynchron def get_sequential_burgers(number: int): - # Mach Sie hier etwas Sequentielles, um die Burger zu erstellen + # Mache hier etwas Sequentielles, um die Burger zu erstellen return burgers ``` @@ -349,7 +349,7 @@ async def read_burgers(): return burgers ``` -### Weitere technische Details +### Weitere technische Details { #more-technical-details } Ihnen ist wahrscheinlich aufgefallen, dass `await` nur innerhalb von Funktionen verwendet werden kann, die mit `async def` definiert sind. @@ -361,15 +361,17 @@ Wenn Sie mit **FastAPI** arbeiten, müssen Sie sich darüber keine Sorgen machen Wenn Sie jedoch `async` / `await` ohne FastAPI verwenden möchten, können Sie dies auch tun. -### Schreiben Sie Ihren eigenen asynchronen Code +### Schreiben Sie Ihren eigenen asynchronen Code { #write-your-own-async-code } -Starlette (und **FastAPI**) basiert auf AnyIO, was bedeutet, es ist sowohl kompatibel mit der Python-Standardbibliothek asyncio, als auch mit Trio. +Starlette (und **FastAPI**) basieren auf AnyIO, was bedeutet, dass es sowohl kompatibel mit der Python-Standardbibliothek asyncio als auch mit Trio ist. -Insbesondere können Sie AnyIO direkt verwenden für Ihre fortgeschritten nebenläufigen und parallelen Anwendungsfälle, die fortgeschrittenere Muster in Ihrem eigenen Code erfordern. +Insbesondere können Sie AnyIO direkt verwenden für Ihre fortgeschrittenen nebenläufigen Anwendungsfälle, die fortgeschrittenere Muster in Ihrem eigenen Code erfordern. -Und selbst wenn Sie FastAPI nicht verwenden würden, könnten Sie auch Ihre eigenen asynchronen Anwendungen mit AnyIO so schreiben, dass sie hoch kompatibel sind und Sie dessen Vorteile nutzen können (z. B. *strukturierte Nebenläufigkeit*). +Und auch wenn Sie FastAPI nicht verwenden würden, könnten Sie Ihre eigenen asynchronen Anwendungen mit AnyIO schreiben, um hochkompatibel zu sein und dessen Vorteile zu nutzen (z. B. *strukturierte Nebenläufigkeit*). -### Andere Formen von asynchronem Code +Ich habe eine weitere Bibliothek auf Basis von AnyIO erstellt, als dünne Schicht obendrauf, um die Typannotationen etwas zu verbessern und bessere **Autovervollständigung**, **Inline-Fehler** usw. zu erhalten. Sie hat auch eine freundliche Einführung und ein Tutorial, um Ihnen zu helfen, **Ihren eigenen asynchronen Code zu verstehen** und zu schreiben: Asyncer. Sie ist insbesondere nützlich, wenn Sie **asynchronen Code mit regulärem** (blockierendem/synchronem) Code kombinieren müssen. + +### Andere Formen von asynchronem Code { #other-forms-of-asynchronous-code } Diese Art der Verwendung von `async` und `await` ist in der Sprache relativ neu. @@ -381,25 +383,25 @@ Davor war der Umgang mit asynchronem Code jedoch deutlich komplexer und schwieri In früheren Versionen von Python hätten Sie Threads oder Gevent verwenden können. Der Code ist jedoch viel komplexer zu verstehen, zu debuggen und nachzuvollziehen. -In früheren Versionen von NodeJS / Browser JavaScript hätten Sie „Callbacks“ verwendet. Was zur "Callback-Hölle" führt. +In früheren Versionen von NodeJS / Browser JavaScript hätten Sie „Callbacks“ verwendet. Was zur „Callback-Hölle“ führt. -## Coroutinen +## Coroutinen { #coroutines } **Coroutine** ist nur ein schicker Begriff für dasjenige, was von einer `async def`-Funktion zurückgegeben wird. Python weiß, dass es so etwas wie eine Funktion ist, die es starten kann und die irgendwann endet, aber auch dass sie pausiert ⏸ werden kann, wann immer darin ein `await` steht. Aber all diese Funktionalität der Verwendung von asynchronem Code mit `async` und `await` wird oft als Verwendung von „Coroutinen“ zusammengefasst. Es ist vergleichbar mit dem Hauptmerkmal von Go, den „Goroutinen“. -## Fazit +## Fazit { #conclusion } Sehen wir uns den gleichen Satz von oben noch mal an: -> Moderne Versionen von Python unterstützen **„asynchronen Code“** unter Verwendung sogenannter **„Coroutinen“** mithilfe der Syntax **`async`** und **`await`**. +> Moderne Versionen von Python unterstützen **„asynchronen Code“** unter Verwendung sogenannter **„Coroutinen“** mithilfe der Syntax **`async` und `await`**. Das sollte jetzt mehr Sinn ergeben. ✨ All das ist es, was FastAPI (via Starlette) befeuert und es eine so beeindruckende Performanz haben lässt. -## Sehr technische Details +## Sehr technische Details { #very-technical-details } /// warning | Achtung @@ -411,23 +413,23 @@ Wenn Sie über gute technische Kenntnisse verfügen (Coroutinen, Threads, Blocki /// -### Pfadoperation-Funktionen +### Pfadoperation-Funktionen { #path-operation-functions } Wenn Sie eine *Pfadoperation-Funktion* mit normalem `def` anstelle von `async def` deklarieren, wird sie in einem externen Threadpool ausgeführt, der dann `await`et wird, anstatt direkt aufgerufen zu werden (da dies den Server blockieren würde). Wenn Sie von einem anderen asynchronen Framework kommen, das nicht auf die oben beschriebene Weise funktioniert, und Sie es gewohnt sind, triviale, nur-berechnende *Pfadoperation-Funktionen* mit einfachem `def` zu definieren, um einen geringfügigen Geschwindigkeitsgewinn (etwa 100 Nanosekunden) zu erzielen, beachten Sie bitte, dass der Effekt in **FastAPI** genau gegenteilig wäre. In solchen Fällen ist es besser, `async def` zu verwenden, es sei denn, Ihre *Pfadoperation-Funktionen* verwenden Code, der blockierende I/O-Operationen durchführt. -Dennoch besteht in beiden Fällen eine gute Chance, dass **FastAPI** [immer noch schneller](index.md#performanz){.internal-link target=_blank} als Ihr bisheriges Framework (oder zumindest damit vergleichbar) ist. +Dennoch besteht in beiden Fällen eine gute Chance, dass **FastAPI** [immer noch schneller](index.md#performance){.internal-link target=_blank} als Ihr bisheriges Framework (oder zumindest damit vergleichbar) ist. -### Abhängigkeiten +### Abhängigkeiten { #dependencies } -Das Gleiche gilt für [Abhängigkeiten](tutorial/dependencies/index.md){.internal-link target=_blank}. Wenn eine Abhängigkeit eine normale `def`-Funktion ist, anstelle einer `async def`-Funktion, dann wird sie im externen Threadpool ausgeführt. +Das Gleiche gilt für [Abhängigkeiten](tutorial/dependencies/index.md){.internal-link target=_blank}. Wenn eine Abhängigkeit eine normale `def`-Funktion anstelle einer `async def` ist, wird sie im externen Threadpool ausgeführt. -### Unterabhängigkeiten +### Unterabhängigkeiten { #sub-dependencies } -Sie können mehrere Abhängigkeiten und [Unterabhängigkeiten](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} haben, die einander bedingen (als Parameter der Funktionsdefinitionen), einige davon könnten erstellt werden mit `async def` und einige mit normalem `def`. Es würde immer noch funktionieren und diejenigen, die mit normalem `def` erstellt wurden, würden in einem externen Thread (vom Threadpool stammend) aufgerufen werden, anstatt `await`et zu werden. +Sie können mehrere Abhängigkeiten und [Unterabhängigkeiten](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} haben, die einander bedingen (als Parameter der Funktionsdefinitionen), einige davon könnten erstellt werden mit `async def` und einige mit normalem `def`. Es würde immer noch funktionieren, und diejenigen, die mit normalem `def` erstellt wurden, würden in einem externen Thread (vom Threadpool stammend) aufgerufen werden, anstatt `await`et zu werden. -### Andere Hilfsfunktionen +### Andere Hilfsfunktionen { #other-utility-functions } Jede andere Hilfsfunktion, die Sie direkt aufrufen, kann mit normalem `def` oder `async def` erstellt werden, und FastAPI beeinflusst nicht die Art und Weise, wie Sie sie aufrufen. @@ -439,4 +441,4 @@ Wenn Ihre Hilfsfunktion eine normale Funktion mit `def` ist, wird sie direkt auf Nochmal, es handelt sich hier um sehr technische Details, die Ihnen helfen, falls Sie danach gesucht haben. -Andernfalls liegen Sie richtig, wenn Sie sich an die Richtlinien aus dem obigen Abschnitt halten: In Eile?. +Andernfalls liegen Sie richtig, wenn Sie sich an die Richtlinien aus dem obigen Abschnitt halten: In Eile?. diff --git a/docs/de/docs/benchmarks.md b/docs/de/docs/benchmarks.md index 6efd56e83..09126c5d9 100644 --- a/docs/de/docs/benchmarks.md +++ b/docs/de/docs/benchmarks.md @@ -1,16 +1,16 @@ -# Benchmarks +# Benchmarks { #benchmarks } -Unabhängige TechEmpower-Benchmarks zeigen, **FastAPI**-Anwendungen, die unter Uvicorn ausgeführt werden, gehören zu den schnellsten existierenden Python-Frameworks, nur Starlette und Uvicorn selbst (intern von FastAPI verwendet) sind schneller. +Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn ausgeführt werden, als eines der schnellsten verfügbaren Python-Frameworks, nur unterhalb von Starlette und Uvicorn selbst (die intern von FastAPI verwendet werden). -Beim Ansehen von Benchmarks und Vergleichen sollten Sie jedoch Folgende Punkte beachten. +Aber bei der Betrachtung von Benchmarks und Vergleichen sollten Sie Folgendes beachten. -## Benchmarks und Geschwindigkeit +## Benchmarks und Geschwindigkeit { #benchmarks-and-speed } -Wenn Sie sich die Benchmarks ansehen, werden häufig mehrere Tools mit unterschiedlichen Eigenschaften als gleichwertig verglichen. +Wenn Sie die Benchmarks ansehen, ist es üblich, dass mehrere Tools unterschiedlichen Typs als gleichwertig verglichen werden. -Konkret geht es darum, Uvicorn, Starlette und FastAPI miteinander zu vergleichen (neben vielen anderen Tools). +Insbesondere dass Uvicorn, Starlette und FastAPI zusammen verglichen werden (neben vielen anderen Tools). -Je einfacher das Problem, welches durch das Tool gelöst wird, desto besser ist die Performanz. Und die meisten Benchmarks testen nicht die zusätzlichen Funktionen, welche das Tool bietet. +Je einfacher das Problem, das durch das Tool gelöst wird, desto besser wird die Performanz sein. Und die meisten Benchmarks testen nicht die zusätzlichen Funktionen, die das Tool bietet. Die Hierarchie ist wie folgt: @@ -19,16 +19,16 @@ Die Hierarchie ist wie folgt: * **FastAPI**: (verwendet Starlette) ein API-Mikroframework mit mehreren zusätzlichen Funktionen zum Erstellen von APIs, mit Datenvalidierung, usw. * **Uvicorn**: - * Bietet die beste Leistung, da außer dem Server selbst nicht viel zusätzlicher Code vorhanden ist. - * Sie würden eine Anwendung nicht direkt in Uvicorn schreiben. Das würde bedeuten, dass Ihr Code zumindest mehr oder weniger den gesamten von Starlette (oder **FastAPI**) bereitgestellten Code enthalten müsste. Und wenn Sie das täten, hätte Ihre endgültige Anwendung den gleichen Overhead wie die Verwendung eines Frameworks nebst Minimierung Ihres Anwendungscodes und der Fehler. + * Wird die beste Performanz haben, da außer dem Server selbst nicht viel zusätzlicher Code vorhanden ist. + * Sie würden eine Anwendung nicht direkt in Uvicorn schreiben. Das würde bedeuten, dass Ihr Code zumindest mehr oder weniger den gesamten von Starlette (oder **FastAPI**) bereitgestellten Code enthalten müsste. Und wenn Sie das täten, hätte Ihre endgültige Anwendung den gleichen Overhead wie bei der Verwendung eines Frameworks und der Minimierung Ihres Anwendungscodes und der Fehler. * Wenn Sie Uvicorn vergleichen, vergleichen Sie es mit Anwendungsservern wie Daphne, Hypercorn, uWSGI, usw. * **Starlette**: - * Wird nach Uvicorn die nächstbeste Performanz erbringen. Tatsächlich nutzt Starlette intern Uvicorn. Daher kann es wahrscheinlich nur „langsamer“ als Uvicorn sein, weil mehr Code ausgeführt wird. - * Aber es bietet Ihnen die Tools zum Erstellen einfacher Webanwendungen, mit Routing basierend auf Pfaden, usw. + * Wird nach Uvicorn die nächstbeste Performanz erbringen. Tatsächlich verwendet Starlette intern Uvicorn, um zu laufen. Daher kann es wahrscheinlich nur „langsamer“ als Uvicorn werden, weil mehr Code ausgeführt werden muss. + * Aber es bietet Ihnen die Werkzeuge, um einfache Webanwendungen zu erstellen, mit Routing basierend auf Pfaden, usw. * Wenn Sie Starlette vergleichen, vergleichen Sie es mit Webframeworks (oder Mikroframeworks) wie Sanic, Flask, Django, usw. * **FastAPI**: * So wie Starlette Uvicorn verwendet und nicht schneller als dieses sein kann, verwendet **FastAPI** Starlette, sodass es nicht schneller als dieses sein kann. - * FastAPI bietet zusätzlich zu Starlette weitere Funktionen. Funktionen, die Sie beim Erstellen von APIs fast immer benötigen, wie Datenvalidierung und Serialisierung. Und wenn Sie es verwenden, erhalten Sie kostenlos automatische Dokumentation (die automatische Dokumentation verursacht nicht einmal zusätzlichen Aufwand für laufende Anwendungen, sie wird beim Start generiert). - * Wenn Sie FastAPI nicht, und direkt Starlette (oder ein anderes Tool wie Sanic, Flask, Responder, usw.) verwenden würden, müssten Sie die gesamte Datenvalidierung und Serialisierung selbst implementieren. Ihre finale Anwendung hätte also immer noch den gleichen Overhead, als ob sie mit FastAPI erstellt worden wäre. Und in vielen Fällen ist diese Datenvalidierung und Serialisierung der größte Teil des in Anwendungen geschriebenen Codes. - * Durch die Verwendung von FastAPI sparen Sie also Entwicklungszeit, Fehler und Codezeilen und würden wahrscheinlich die gleiche Leistung (oder eine bessere) erzielen, die Sie hätten, wenn Sie es nicht verwenden würden (da Sie alles in Ihrem Code implementieren müssten). - * Wenn Sie FastAPI vergleichen, vergleichen Sie es mit einem Webanwendung-Framework (oder einer Reihe von Tools), welche Datenvalidierung, Serialisierung und Dokumentation bereitstellen, wie Flask-apispec, NestJS, Molten, usw. – Frameworks mit integrierter automatischer Datenvalidierung, Serialisierung und Dokumentation. + * FastAPI bietet zusätzliche Funktionen auf Basis von Starlette. Funktionen, die Sie beim Erstellen von APIs fast immer benötigen, wie Datenvalidierung und Serialisierung. Und wenn Sie es verwenden, erhalten Sie kostenlose automatische Dokumentation (die automatische Dokumentation verursacht nicht einmal zusätzlichen Overhead für laufende Anwendungen, sie wird beim Starten generiert). + * Wenn Sie FastAPI nicht verwenden und stattdessen Starlette direkt (oder ein anderes Tool wie Sanic, Flask, Responder, usw.) verwenden würden, müssten Sie die gesamte Datenvalidierung und Serialisierung selbst implementieren. Ihre finale Anwendung hätte also immer noch den gleichen Overhead, als ob sie mit FastAPI erstellt worden wäre. Und in vielen Fällen ist diese Datenvalidierung und Serialisierung der größte Teil des in Anwendungen geschriebenen Codes. + * Durch die Verwendung von FastAPI sparen Sie also Entwicklungszeit, Fehler und Codezeilen und würden wahrscheinlich die gleiche Performanz (oder eine bessere) erzielen, die Sie hätten, wenn Sie es nicht verwenden würden (da Sie alles in Ihrem Code implementieren müssten). + * Wenn Sie FastAPI vergleichen, vergleichen Sie es mit einem Webanwendungs-Framework (oder einer Reihe von Tools), das Datenvalidierung, Serialisierung und Dokumentation bereitstellt, wie Flask-apispec, NestJS, Molten, usw. – Frameworks mit integrierter automatischer Datenvalidierung, Serialisierung und Dokumentation. diff --git a/docs/de/docs/deployment/cloud.md b/docs/de/docs/deployment/cloud.md index 042a92a81..ca1ba3b3b 100644 --- a/docs/de/docs/deployment/cloud.md +++ b/docs/de/docs/deployment/cloud.md @@ -1,13 +1,16 @@ -# FastAPI-Deployment bei Cloud-Anbietern +# FastAPI bei Cloudanbietern bereitstellen { #deploy-fastapi-on-cloud-providers } -Sie können praktisch **jeden Cloud-Anbieter** für das Deployment Ihrer FastAPI-Anwendung verwenden. +Sie können praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung bereitzustellen. -In den meisten Fällen verfügen die Haupt-Cloud-Anbieter über Anleitungen zum Deployment von FastAPI. +In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Bereitstellen von FastAPI an. -## Cloud-Anbieter – Sponsoren +## Cloudanbieter – Sponsoren { #cloud-providers-sponsors } -Einige Cloud-Anbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#den-autor-sponsern){.internal-link target=_blank} ✨, dies gewährleistet die kontinuierliche und gesunde **Entwicklung** von FastAPI und seinem **Ökosystem**. +Einige Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, dies stellt die kontinuierliche und gesunde **Entwicklung** von FastAPI und seinem **Ökosystem** sicher. -Und es zeigt deren wahres Engagement für FastAPI und seine **Community** (Sie), da diese Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie über ein **gutes und gesundes Framework** verfügen, FastAPI. 🙇 +Und es zeigt ihr wahres Engagement für FastAPI und seine **Community** (Sie), da sie Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie ein **gutes und gesundes Framework**, FastAPI, haben. 🙇 -Vielleicht möchten Sie deren Dienste ausprobieren und deren Anleitungen folgen. +Vielleicht möchten Sie deren Dienste ausprobieren und deren Anleitungen folgen: + +* Render +* Railway diff --git a/docs/de/docs/deployment/concepts.md b/docs/de/docs/deployment/concepts.md index 907598e54..ef0f458a7 100644 --- a/docs/de/docs/deployment/concepts.md +++ b/docs/de/docs/deployment/concepts.md @@ -1,4 +1,4 @@ -# Deployment-Konzepte +# Deployment-Konzepte { #deployments-concepts } Bei dem Deployment – der Bereitstellung – einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe der Sie die **am besten geeignete** Methode zur **Bereitstellung Ihrer Anwendung** finden können. @@ -13,7 +13,7 @@ Einige wichtige Konzepte sind: Wir werden sehen, wie diese sich auf das **Deployment** auswirken. -Letztendlich besteht das ultimative Ziel darin, **Ihre API-Clients** auf **sichere** Weise zu bedienen, um **Unterbrechungen** zu vermeiden und die **Rechenressourcen** (z. B. entfernte Server/virtuelle Maschinen) so effizient wie möglich zu nutzen. 🚀 +Letztendlich besteht das ultimative Ziel darin, **Ihre API-Clients** auf **sichere** Weise zu versorgen, um **Unterbrechungen** zu vermeiden und die **Rechenressourcen** (z. B. entfernte Server/virtuelle Maschinen) so effizient wie möglich zu nutzen. 🚀 Ich erzähle Ihnen hier etwas mehr über diese **Konzepte**, was Ihnen hoffentlich die **Intuition** gibt, die Sie benötigen, um zu entscheiden, wie Sie Ihre API in sehr unterschiedlichen Umgebungen bereitstellen, möglicherweise sogar in **zukünftigen**, die jetzt noch nicht existieren. @@ -23,7 +23,7 @@ In den nächsten Kapiteln werde ich Ihnen mehr **konkrete Rezepte** für die Ber Aber schauen wir uns zunächst einmal diese grundlegenden **konzeptionellen Ideen** an. Diese Konzepte gelten auch für jede andere Art von Web-API. 💡 -## Sicherheit – HTTPS +## Sicherheit – HTTPS { #security-https } Im [vorherigen Kapitel über HTTPS](https.md){.internal-link target=_blank} haben wir erfahren, wie HTTPS Verschlüsselung für Ihre API bereitstellt. @@ -31,7 +31,7 @@ Wir haben auch gesehen, dass HTTPS normalerweise von einer Komponente **außerha Und es muss etwas geben, das für die **Erneuerung der HTTPS-Zertifikate** zuständig ist, es könnte sich um dieselbe Komponente handeln oder um etwas anderes. -### Beispieltools für HTTPS +### Beispieltools für HTTPS { #example-tools-for-https } Einige der Tools, die Sie als TLS-Terminierungsproxy verwenden können, sind: @@ -55,11 +55,11 @@ In den nächsten Kapiteln zeige ich Ihnen einige konkrete Beispiele. Die nächsten zu berücksichtigenden Konzepte drehen sich dann um das Programm, das Ihre eigentliche API ausführt (z. B. Uvicorn). -## Programm und Prozess +## Programm und Prozess { #program-and-process } Wir werden viel über den laufenden „**Prozess**“ sprechen, daher ist es nützlich, Klarheit darüber zu haben, was das bedeutet und was der Unterschied zum Wort „**Programm**“ ist. -### Was ist ein Programm? +### Was ist ein Programm { #what-is-a-program } Das Wort **Programm** wird häufig zur Beschreibung vieler Dinge verwendet: @@ -67,7 +67,7 @@ Das Wort **Programm** wird häufig zur Beschreibung vieler Dinge verwendet: * Die **Datei**, die vom Betriebssystem **ausgeführt** werden kann, zum Beispiel: `python`, `python.exe` oder `uvicorn`. * Ein bestimmtes Programm, während es auf dem Betriebssystem **läuft**, die CPU nutzt und Dinge im Arbeitsspeicher ablegt. Dies wird auch als **Prozess** bezeichnet. -### Was ist ein Prozess? +### Was ist ein Prozess { #what-is-a-process } Das Wort **Prozess** wird normalerweise spezifischer verwendet und bezieht sich nur auf das, was im Betriebssystem ausgeführt wird (wie im letzten Punkt oben): @@ -88,13 +88,13 @@ Und Sie werden beispielsweise wahrscheinlich feststellen, dass mehrere Prozesse Nachdem wir nun den Unterschied zwischen den Begriffen **Prozess** und **Programm** kennen, sprechen wir weiter über das Deployment. -## Beim Hochfahren ausführen +## Beim Hochfahren ausführen { #running-on-startup } Wenn Sie eine Web-API erstellen, möchten Sie in den meisten Fällen, dass diese **immer läuft**, ununterbrochen, damit Ihre Clients immer darauf zugreifen können. Es sei denn natürlich, Sie haben einen bestimmten Grund, warum Sie möchten, dass diese nur in bestimmten Situationen ausgeführt wird. Meistens möchten Sie jedoch, dass sie ständig ausgeführt wird und **verfügbar** ist. -### Auf einem entfernten Server +### Auf einem entfernten Server { #in-a-remote-server } -Wenn Sie einen entfernten Server (einen Cloud-Server, eine virtuelle Maschine, usw.) einrichten, können Sie am einfachsten Uvicorn (oder ähnliches) manuell ausführen, genau wie bei der lokalen Entwicklung. +Wenn Sie einen entfernten Server (einen Cloud-Server, eine virtuelle Maschine, usw.) einrichten, können Sie am einfachsten `fastapi run` (welches Uvicorn verwendet) oder etwas Ähnliches manuell ausführen, genau wie bei der lokalen Entwicklung. Und es wird funktionieren und **während der Entwicklung** nützlich sein. @@ -102,15 +102,15 @@ Wenn Ihre Verbindung zum Server jedoch unterbrochen wird, wird der **laufende Pr Und wenn der Server neu gestartet wird (z. B. nach Updates oder Migrationen vom Cloud-Anbieter), werden Sie das wahrscheinlich **nicht bemerken**. Und deshalb wissen Sie nicht einmal, dass Sie den Prozess manuell neu starten müssen. Ihre API bleibt also einfach tot. 😱 -### Beim Hochfahren automatisch ausführen +### Beim Hochfahren automatisch ausführen { #run-automatically-on-startup } Im Allgemeinen möchten Sie wahrscheinlich, dass das Serverprogramm (z. B. Uvicorn) beim Hochfahren des Servers automatisch gestartet wird und kein **menschliches Eingreifen** erforderlich ist, sodass immer ein Prozess mit Ihrer API ausgeführt wird (z. B. Uvicorn, welches Ihre FastAPI-Anwendung ausführt). -### Separates Programm +### Separates Programm { #separate-program } Um dies zu erreichen, haben Sie normalerweise ein **separates Programm**, welches sicherstellt, dass Ihre Anwendung beim Hochfahren ausgeführt wird. Und in vielen Fällen würde es auch sicherstellen, dass auch andere Komponenten oder Anwendungen ausgeführt werden, beispielsweise eine Datenbank. -### Beispieltools zur Ausführung beim Hochfahren +### Beispieltools zur Ausführung beim Hochfahren { #example-tools-to-run-at-startup } Einige Beispiele für Tools, die diese Aufgabe übernehmen können, sind: @@ -125,29 +125,29 @@ Einige Beispiele für Tools, die diese Aufgabe übernehmen können, sind: In den nächsten Kapiteln werde ich Ihnen konkretere Beispiele geben. -## Neustart +## Neustart { #restarts } Ähnlich wie Sie sicherstellen möchten, dass Ihre Anwendung beim Hochfahren ausgeführt wird, möchten Sie wahrscheinlich auch sicherstellen, dass diese nach Fehlern **neu gestartet** wird. -### Wir machen Fehler +### Wir machen Fehler { #we-make-mistakes } Wir, als Menschen, machen ständig **Fehler**. Software hat fast *immer* **Bugs**, die an verschiedenen Stellen versteckt sind. 🐛 Und wir als Entwickler verbessern den Code ständig, wenn wir diese Bugs finden und neue Funktionen implementieren (und möglicherweise auch neue Bugs hinzufügen 😅). -### Kleine Fehler automatisch handhaben +### Kleine Fehler automatisch handhaben { #small-errors-automatically-handled } -Wenn beim Erstellen von Web-APIs mit FastAPI ein Fehler in unserem Code auftritt, wird FastAPI ihn normalerweise dem einzelnen Request zurückgeben, der den Fehler ausgelöst hat. 🛡 +Wenn beim Erstellen von Web-APIs mit FastAPI ein Fehler in unserem Code auftritt, wird FastAPI ihn normalerweise dem einzelnen Request zurückgeben, der den Fehler ausgelöst hat. 🛡 Der Client erhält für diesen Request einen **500 Internal Server Error**, aber die Anwendung arbeitet bei den nächsten Requests weiter, anstatt einfach komplett abzustürzen. -### Größere Fehler – Abstürze +### Größere Fehler – Abstürze { #bigger-errors-crashes } Dennoch kann es vorkommen, dass wir Code schreiben, der **die gesamte Anwendung zum Absturz bringt** und so zum Absturz von Uvicorn und Python führt. 💥 Und dennoch möchten Sie wahrscheinlich nicht, dass die Anwendung tot bleibt, weil an einer Stelle ein Fehler aufgetreten ist. Sie möchten wahrscheinlich, dass sie zumindest für die *Pfadoperationen*, die nicht fehlerhaft sind, **weiterläuft**. -### Neustart nach Absturz +### Neustart nach Absturz { #restart-after-crash } Aber in den Fällen mit wirklich schwerwiegenden Fehlern, die den laufenden **Prozess** zum Absturz bringen, benötigen Sie eine externe Komponente, die den Prozess **neu startet**, zumindest ein paar Mal ... @@ -161,7 +161,7 @@ Konzentrieren wir uns also auf die Hauptfälle, in denen die Anwendung in bestim Sie möchten wahrscheinlich, dass eine **externe Komponente** für den Neustart Ihrer Anwendung verantwortlich ist, da zu diesem Zeitpunkt dieselbe Anwendung mit Uvicorn und Python bereits abgestürzt ist und es daher nichts im selben Code derselben Anwendung gibt, was etwas dagegen tun kann. -### Beispieltools zum automatischen Neustart +### Beispieltools zum automatischen Neustart { #example-tools-to-restart-automatically } In den meisten Fällen wird dasselbe Tool, das zum **Ausführen des Programms beim Hochfahren** verwendet wird, auch für automatische **Neustarts** verwendet. @@ -176,19 +176,19 @@ Dies könnte zum Beispiel erledigt werden durch: * Intern von einem Cloud-Anbieter im Rahmen seiner Dienste * Andere ... -## Replikation – Prozesse und Arbeitsspeicher +## Replikation – Prozesse und Arbeitsspeicher { #replication-processes-and-memory } -Wenn Sie eine FastAPI-Anwendung verwenden und ein Serverprogramm wie Uvicorn verwenden, kann **ein einzelner Prozess** mehrere Clients gleichzeitig bedienen. +Wenn Sie eine FastAPI-Anwendung verwenden und ein Serverprogramm wie den `fastapi`-Befehl, der Uvicorn ausführt, kann **ein einzelner Prozess** an mehrere Clients gleichzeitig ausliefern. -In vielen Fällen möchten Sie jedoch mehrere Prozesse gleichzeitig ausführen. +In vielen Fällen möchten Sie jedoch mehrere Workerprozesse gleichzeitig ausführen. -### Mehrere Prozesse – Worker +### Mehrere Prozesse – Worker { #multiple-processes-workers } Wenn Sie mehr Clients haben, als ein einzelner Prozess verarbeiten kann (z. B. wenn die virtuelle Maschine nicht sehr groß ist) und die CPU des Servers **mehrere Kerne** hat, dann könnten **mehrere Prozesse** gleichzeitig mit derselben Anwendung laufen und alle Requests unter sich verteilen. -Wenn Sie mit **mehreren Prozessen** dasselbe API-Programm ausführen, werden diese üblicherweise als **Worker** bezeichnet. +Wenn Sie mit **mehreren Prozessen** dasselbe API-Programm ausführen, werden diese üblicherweise als **Worker** bezeichnet. -### Workerprozesse und Ports +### Workerprozesse und Ports { #worker-processes-and-ports } Erinnern Sie sich aus der Dokumentation [Über HTTPS](https.md){.internal-link target=_blank}, dass nur ein Prozess auf einer Kombination aus Port und IP-Adresse auf einem Server lauschen kann? @@ -196,35 +196,35 @@ Das ist immer noch wahr. Um also **mehrere Prozesse** gleichzeitig zu haben, muss es einen **einzelnen Prozess geben, der einen Port überwacht**, welcher dann die Kommunikation auf irgendeine Weise an jeden Workerprozess überträgt. -### Arbeitsspeicher pro Prozess +### Arbeitsspeicher pro Prozess { #memory-per-process } Wenn das Programm nun Dinge in den Arbeitsspeicher lädt, zum Beispiel ein Modell für maschinelles Lernen in einer Variablen oder den Inhalt einer großen Datei in einer Variablen, verbraucht das alles **einen Teil des Arbeitsspeichers (RAM – Random Access Memory)** des Servers. Und mehrere Prozesse teilen sich normalerweise keinen Speicher. Das bedeutet, dass jeder laufende Prozess seine eigenen Dinge, eigenen Variablen und eigenen Speicher hat. Und wenn Sie in Ihrem Code viel Speicher verbrauchen, verbraucht **jeder Prozess** die gleiche Menge Speicher. -### Serverspeicher +### Serverspeicher { #server-memory } Wenn Ihr Code beispielsweise ein Machine-Learning-Modell mit **1 GB Größe** lädt und Sie einen Prozess mit Ihrer API ausführen, verbraucht dieser mindestens 1 GB RAM. Und wenn Sie **4 Prozesse** (4 Worker) starten, verbraucht jeder 1 GB RAM. Insgesamt verbraucht Ihre API also **4 GB RAM**. Und wenn Ihr entfernter Server oder Ihre virtuelle Maschine nur über 3 GB RAM verfügt, führt der Versuch, mehr als 4 GB RAM zu laden, zu Problemen. 🚨 -### Mehrere Prozesse – Ein Beispiel +### Mehrere Prozesse – Ein Beispiel { #multiple-processes-an-example } Im folgenden Beispiel gibt es einen **Manager-Prozess**, welcher zwei **Workerprozesse** startet und steuert. Dieser Manager-Prozess wäre wahrscheinlich derjenige, welcher der IP am **Port** lauscht. Und er würde die gesamte Kommunikation an die Workerprozesse weiterleiten. -Diese Workerprozesse würden Ihre Anwendung ausführen, sie würden die Hauptberechnungen durchführen, um einen **Request** entgegenzunehmen und eine **Response** zurückzugeben, und sie würden alles, was Sie in Variablen einfügen, in den RAM laden. +Diese Workerprozesse würden Ihre Anwendung ausführen, sie würden die Hauptberechnungen durchführen, um einen **Request** entgegenzunehmen und eine **Response** zurückzugeben, und sie würden alles, was Sie in Variablen einfügen, in den RAM laden. -Und natürlich würden auf derselben Maschine neben Ihrer Anwendung wahrscheinlich auch **andere Prozesse** laufen. +Und natürlich würden auf derselben Maschine neben Ihrer Anwendung wahrscheinlich **andere Prozesse** laufen. Ein interessantes Detail ist dabei, dass der Prozentsatz der von jedem Prozess verwendeten **CPU** im Laufe der Zeit stark **variieren** kann, der **Arbeitsspeicher (RAM)** jedoch normalerweise mehr oder weniger **stabil** bleibt. Wenn Sie eine API haben, die jedes Mal eine vergleichbare Menge an Berechnungen durchführt, und Sie viele Clients haben, dann wird die **CPU-Auslastung** wahrscheinlich *ebenfalls stabil sein* (anstatt ständig schnell zu steigen und zu fallen). -### Beispiele für Replikation-Tools und -Strategien +### Beispiele für Replikation-Tools und -Strategien { #examples-of-replication-tools-and-strategies } Es gibt mehrere Ansätze, um dies zu erreichen, und ich werde Ihnen in den nächsten Kapiteln mehr über bestimmte Strategien erzählen, beispielsweise wenn es um Docker und Container geht. @@ -232,9 +232,7 @@ Die wichtigste zu berücksichtigende Einschränkung besteht darin, dass es eine Hier sind einige mögliche Kombinationen und Strategien: -* **Gunicorn**, welches **Uvicorn-Worker** managt - * Gunicorn wäre der **Prozessmanager**, der die **IP** und den **Port** überwacht, die Replikation würde durch **mehrere Uvicorn-Workerprozesse** erfolgen -* **Uvicorn**, welches **Uvicorn-Worker** managt +* **Uvicorn** mit `--workers` * Ein Uvicorn-**Prozessmanager** würde der **IP** am **Port** lauschen, und er würde **mehrere Uvicorn-Workerprozesse** starten. * **Kubernetes** und andere verteilte **Containersysteme** * Etwas in der **Kubernetes**-Ebene würde die **IP** und den **Port** abhören. Die Replikation hätte **mehrere Container**, in jedem wird jeweils **ein Uvicorn-Prozess** ausgeführt. @@ -249,7 +247,7 @@ Ich werde Ihnen in einem zukünftigen Kapitel mehr über Container-Images, Docke /// -## Schritte vor dem Start +## Schritte vor dem Start { #previous-steps-before-starting } Es gibt viele Fälle, in denen Sie, **bevor Sie Ihre Anwendung starten**, einige Schritte ausführen möchten. @@ -271,7 +269,7 @@ In diesem Fall müssen Sie sich darüber keine Sorgen machen. 🤷 /// -### Beispiele für Strategien für Vorab-Schritte +### Beispiele für Strategien für Vorab-Schritte { #examples-of-previous-steps-strategies } Es hängt **stark** davon ab, wie Sie **Ihr System bereitstellen**, und hängt wahrscheinlich mit der Art und Weise zusammen, wie Sie Programme starten, Neustarts durchführen, usw. @@ -287,7 +285,7 @@ Konkretere Beispiele hierfür mit Containern gebe ich Ihnen in einem späteren K /// -## Ressourcennutzung +## Ressourcennutzung { #resource-utilization } Ihr(e) Server ist (sind) eine **Ressource**, welche Sie mit Ihren Programmen, der Rechenzeit auf den CPUs und dem verfügbaren RAM-Speicher verbrauchen oder **nutzen** können. @@ -303,11 +301,11 @@ In diesem Fall wäre es besser, **einen zusätzlichen Server** zu besorgen und e Es besteht auch die Möglichkeit, dass es aus irgendeinem Grund zu **Spitzen** in der Nutzung Ihrer API kommt. Vielleicht ist diese viral gegangen, oder vielleicht haben andere Dienste oder Bots damit begonnen, sie zu nutzen. Und vielleicht möchten Sie in solchen Fällen über zusätzliche Ressourcen verfügen, um auf der sicheren Seite zu sein. -Sie können eine **beliebige Zahl** festlegen, um beispielsweise eine Ressourcenauslastung zwischen **50 % und 90 %** anzustreben. Der Punkt ist, dass dies wahrscheinlich die wichtigen Dinge sind, die Sie messen und verwenden sollten, um Ihre Deployments zu optimieren. +Sie können eine **beliebige Zahl** festlegen, um beispielsweise eine Ressourcenauslastung zwischen **50 % und 90 %** anzustreben. Der Punkt ist, dass dies wahrscheinlich die wichtigen Dinge sind, die Sie messen und verwenden sollten, um Ihre Deployments zu optimieren. Sie können einfache Tools wie `htop` verwenden, um die in Ihrem Server verwendete CPU und den RAM oder die von jedem Prozess verwendete Menge anzuzeigen. Oder Sie können komplexere Überwachungstools verwenden, die möglicherweise auf mehrere Server usw. verteilt sind. -## Zusammenfassung +## Zusammenfassung { #recap } Sie haben hier einige der wichtigsten Konzepte gelesen, die Sie wahrscheinlich berücksichtigen müssen, wenn Sie entscheiden, wie Sie Ihre Anwendung bereitstellen: diff --git a/docs/de/docs/deployment/docker.md b/docs/de/docs/deployment/docker.md index a2734e068..52ac99913 100644 --- a/docs/de/docs/deployment/docker.md +++ b/docs/de/docs/deployment/docker.md @@ -1,4 +1,4 @@ -# FastAPI in Containern – Docker +# FastAPI in Containern – Docker { #fastapi-in-containers-docker } Beim Deployment von FastAPI-Anwendungen besteht ein gängiger Ansatz darin, ein **Linux-Containerimage** zu erstellen. Normalerweise erfolgt dies mit **Docker**. Sie können dieses Containerimage dann auf eine von mehreren möglichen Arten bereitstellen. @@ -6,11 +6,11 @@ Die Verwendung von Linux-Containern bietet mehrere Vorteile, darunter **Sicherhe /// tip | Tipp -Sie haben es eilig und kennen sich bereits aus? Springen Sie zum [`Dockerfile` unten 👇](#ein-docker-image-fur-fastapi-erstellen). +Sie haben es eilig und kennen sich bereits aus? Springen Sie zum [`Dockerfile` unten 👇](#build-a-docker-image-for-fastapi). /// -
+
Dockerfile-Vorschau 👀 ```Dockerfile @@ -24,15 +24,15 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt COPY ./app /code/app -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +CMD ["fastapi", "run", "app/main.py", "--port", "80"] # Wenn Sie hinter einem Proxy wie Nginx oder Traefik sind, fügen Sie --proxy-headers hinzu -# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"] +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ```
-## Was ist ein Container? +## Was ist ein Container { #what-is-a-container } Container (hauptsächlich Linux-Container) sind eine sehr **leichtgewichtige** Möglichkeit, Anwendungen einschließlich aller ihrer Abhängigkeiten und erforderlichen Dateien zu verpacken und sie gleichzeitig von anderen Containern (anderen Anwendungen oder Komponenten) im selben System isoliert zu halten. @@ -42,7 +42,7 @@ Auf diese Weise verbrauchen Container **wenig Ressourcen**, eine Menge vergleich Container verfügen außerdem über ihre eigenen **isoliert** laufenden Prozesse (üblicherweise nur einen Prozess), über ihr eigenes Dateisystem und ihr eigenes Netzwerk, was die Bereitstellung, Sicherheit, Entwicklung usw. vereinfacht. -## Was ist ein Containerimage? +## Was ist ein Containerimage { #what-is-a-container-image } Ein **Container** wird von einem **Containerimage** ausgeführt. @@ -50,17 +50,17 @@ Ein Containerimage ist eine **statische** Version aller Dateien, Umgebungsvariab Im Gegensatz zu einem „**Containerimage**“, bei dem es sich um den gespeicherten statischen Inhalt handelt, bezieht sich ein „**Container**“ normalerweise auf die laufende Instanz, das Ding, das **ausgeführt** wird. -Wenn der **Container** gestartet und ausgeführt wird (gestartet von einem **Containerimage**), kann er Dateien, Umgebungsvariablen usw. erstellen oder ändern. Diese Änderungen sind nur in diesem Container vorhanden, nicht im zugrunde liegenden bestehen Containerimage (werden nicht auf der Festplatte gespeichert). +Wenn der **Container** gestartet und ausgeführt wird (gestartet von einem **Containerimage**), kann er Dateien, Umgebungsvariablen usw. erstellen oder ändern. Diese Änderungen sind nur in diesem Container vorhanden, nicht im zugrunde liegenden Containerimage (werden nicht auf der Festplatte gespeichert). Ein Containerimage ist vergleichbar mit der **Programmdatei** und ihrem Inhalt, z. B. `python` und eine Datei `main.py`. Und der **Container** selbst (im Gegensatz zum **Containerimage**) ist die tatsächlich laufende Instanz des Images, vergleichbar mit einem **Prozess**. Tatsächlich läuft ein Container nur, wenn er einen **laufenden Prozess** hat (und normalerweise ist es nur ein einzelner Prozess). Der Container stoppt, wenn kein Prozess darin ausgeführt wird. -## Containerimages +## Containerimages { #container-images } Docker ist eines der wichtigsten Tools zum Erstellen und Verwalten von **Containerimages** und **Containern**. -Und es gibt einen öffentlichen Docker Hub mit vorgefertigten **offiziellen Containerimages** für viele Tools, Umgebungen, Datenbanken und Anwendungen. +Und es gibt einen öffentlichen Docker Hub mit vorgefertigten **offiziellen Containerimages** für viele Tools, Umgebungen, Datenbanken und Anwendungen. Beispielsweise gibt es ein offizielles Python-Image. @@ -79,7 +79,7 @@ Sie würden also **mehrere Container** mit unterschiedlichen Dingen ausführen, In alle Containerverwaltungssysteme (wie Docker oder Kubernetes) sind diese Netzwerkfunktionen integriert. -## Container und Prozesse +## Container und Prozesse { #containers-and-processes } Ein **Containerimage** enthält normalerweise in seinen Metadaten das Standardprogramm oder den Standardbefehl, der ausgeführt werden soll, wenn der **Container** gestartet wird, sowie die Parameter, die an dieses Programm übergeben werden sollen. Sehr ähnlich zu dem, was wäre, wenn es über die Befehlszeile gestartet werden würde. @@ -91,7 +91,7 @@ Ein Container hat normalerweise einen **einzelnen Prozess**, aber es ist auch m Es ist jedoch nicht möglich, einen laufenden Container, ohne **mindestens einen laufenden Prozess** zu haben. Wenn der Hauptprozess stoppt, stoppt der Container. -## Ein Docker-Image für FastAPI erstellen +## Ein Docker-Image für FastAPI erstellen { #build-a-docker-image-for-fastapi } Okay, wollen wir jetzt etwas bauen! 🚀 @@ -103,7 +103,7 @@ Das ist, was Sie in **den meisten Fällen** tun möchten, zum Beispiel: * Beim Betrieb auf einem **Raspberry Pi** * Bei Verwendung eines Cloud-Dienstes, der ein Containerimage für Sie ausführt, usw. -### Paketanforderungen +### Paketanforderungen { #package-requirements } Normalerweise befinden sich die **Paketanforderungen** für Ihre Anwendung in einer Datei. @@ -116,9 +116,8 @@ Sie würden natürlich die gleichen Ideen verwenden, die Sie in [Über FastAPI-V Ihre `requirements.txt` könnte beispielsweise so aussehen: ``` -fastapi>=0.68.0,<0.69.0 -pydantic>=1.8.0,<2.0.0 -uvicorn>=0.15.0,<0.16.0 +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 ``` Und normalerweise würden Sie diese Paketabhängigkeiten mit `pip` installieren, zum Beispiel: @@ -128,20 +127,18 @@ Und normalerweise würden Sie diese Paketabhängigkeiten mit `pip` installieren, ```console $ pip install -r requirements.txt ---> 100% -Successfully installed fastapi pydantic uvicorn +Successfully installed fastapi pydantic ```
-/// info +/// info | Info Es gibt andere Formate und Tools zum Definieren und Installieren von Paketabhängigkeiten. -Ich zeige Ihnen später in einem Abschnitt unten ein Beispiel unter Verwendung von Poetry. 👇 - /// -### Den **FastAPI**-Code erstellen +### Den **FastAPI**-Code erstellen { #create-the-fastapi-code } * Erstellen Sie ein `app`-Verzeichnis und betreten Sie es. * Erstellen Sie eine leere Datei `__init__.py`. @@ -165,35 +162,35 @@ def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` -### Dockerfile +### Dockerfile { #dockerfile } Erstellen Sie nun im selben Projektverzeichnis eine Datei `Dockerfile` mit: ```{ .dockerfile .annotate } -# (1) +# (1)! FROM python:3.9 -# (2) +# (2)! WORKDIR /code -# (3) +# (3)! COPY ./requirements.txt /code/requirements.txt -# (4) +# (4)! RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt -# (5) +# (5)! COPY ./app /code/app -# (6) -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` 1. Beginne mit dem offiziellen Python-Basisimage. 2. Setze das aktuelle Arbeitsverzeichnis auf `/code`. - Hier plazieren wir die Datei `requirements.txt` und das Verzeichnis `app`. + Hier platzieren wir die Datei `requirements.txt` und das Verzeichnis `app`. 3. Kopiere die Datei mit den Paketanforderungen in das Verzeichnis `/code`. @@ -223,20 +220,50 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] Daher ist es wichtig, dies **nahe dem Ende** des `Dockerfile`s zu platzieren, um die Erstellungszeiten des Containerimages zu optimieren. -6. Lege den **Befehl** fest, um den `uvicorn`-Server zu starten. +6. Lege den **Befehl** fest, um `fastapi run` zu nutzen, welches Uvicorn darunter verwendet. `CMD` nimmt eine Liste von Zeichenfolgen entgegen. Jede dieser Zeichenfolgen entspricht dem, was Sie durch Leerzeichen getrennt in die Befehlszeile eingeben würden. Dieser Befehl wird aus dem **aktuellen Arbeitsverzeichnis** ausgeführt, dem gleichen `/code`-Verzeichnis, das Sie oben mit `WORKDIR /code` festgelegt haben. - Da das Programm unter `/code` gestartet wird und sich darin das Verzeichnis `./app` mit Ihrem Code befindet, kann **Uvicorn** `app` sehen und aus `app.main` **importieren**. - /// tip | Tipp Lernen Sie, was jede Zeile bewirkt, indem Sie auf die Zahlenblasen im Code klicken. 👆 /// +/// warning | Achtung + +Stellen Sie sicher, dass Sie **immer** die **exec form** der Anweisung `CMD` verwenden, wie unten erläutert. + +/// + +#### `CMD` – Exec Form verwenden { #use-cmd-exec-form } + +Die `CMD` Docker-Anweisung kann in zwei Formen geschrieben werden: + +✅ **Exec** form: + +```Dockerfile +# ✅ Tun Sie das +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +⛔️ **Shell** form: + +```Dockerfile +# ⛔️ Tun Sie das nicht +CMD fastapi run app/main.py --port 80 +``` + +Achten Sie darauf, stets die **exec** form zu verwenden, um sicherzustellen, dass FastAPI ordnungsgemäß heruntergefahren wird und [Lifespan-Events](../advanced/events.md){.internal-link target=_blank} ausgelöst werden. + +Sie können mehr darüber in der Docker-Dokumentation für Shell und Exec Form lesen. + +Dies kann insbesondere bei der Verwendung von `docker compose` deutlich spürbar sein. Sehen Sie sich diesen Abschnitt in der Docker Compose-FAQ für technische Details an: Warum benötigen meine Dienste 10 Sekunden, um neu erstellt oder gestoppt zu werden?. + +#### Verzeichnisstruktur { #directory-structure } + Sie sollten jetzt eine Verzeichnisstruktur wie diese haben: ``` @@ -248,15 +275,15 @@ Sie sollten jetzt eine Verzeichnisstruktur wie diese haben: └── requirements.txt ``` -#### Hinter einem TLS-Terminierungsproxy +#### Hinter einem TLS-Terminierungsproxy { #behind-a-tls-termination-proxy } -Wenn Sie Ihren Container hinter einem TLS-Terminierungsproxy (Load Balancer) wie Nginx oder Traefik ausführen, fügen Sie die Option `--proxy-headers` hinzu. Das sagt Uvicorn, den von diesem Proxy gesendeten Headern zu vertrauen und dass die Anwendung hinter HTTPS ausgeführt wird, usw. +Wenn Sie Ihren Container hinter einem TLS-Terminierungsproxy (Load Balancer) wie Nginx oder Traefik ausführen, fügen Sie die Option `--proxy-headers` hinzu. Das sagt Uvicorn (durch das FastAPI CLI), den von diesem Proxy gesendeten Headern zu vertrauen und dass die Anwendung hinter HTTPS ausgeführt wird, usw. ```Dockerfile -CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] ``` -#### Docker-Cache +#### Docker-Cache { #docker-cache } In diesem `Dockerfile` gibt es einen wichtigen Trick: Wir kopieren zuerst die **Datei nur mit den Abhängigkeiten**, nicht den Rest des Codes. Lassen Sie mich Ihnen erklären, warum. @@ -288,7 +315,7 @@ Dann, gegen Ende des `Dockerfile`s, kopieren wir den gesamten Code. Da sich der COPY ./app /code/app ``` -### Das Docker-Image erstellen +### Das Docker-Image erstellen { #build-the-docker-image } Nachdem nun alle Dateien vorhanden sind, erstellen wir das Containerimage. @@ -313,7 +340,7 @@ In diesem Fall handelt es sich um dasselbe aktuelle Verzeichnis (`.`). /// -### Den Docker-Container starten +### Den Docker-Container starten { #start-the-docker-container } * Führen Sie einen Container basierend auf Ihrem Image aus: @@ -325,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage
-## Es überprüfen +## Es testen { #check-it } Sie sollten es in der URL Ihres Docker-Containers überprüfen können, zum Beispiel: http://192.168.99.100/items/5?q=somequery oder http://127.0.0.1/items/5?q=somequery (oder gleichwertig, unter Verwendung Ihres Docker-Hosts). @@ -335,7 +362,7 @@ Sie werden etwas sehen wie: {"item_id": 5, "q": "somequery"} ``` -## Interaktive API-Dokumentation +## Interaktive API-Dokumentation { #interactive-api-docs } Jetzt können Sie auf http://192.168.99.100/docs oder http://127.0.0.1/docs gehen (oder ähnlich, unter Verwendung Ihres Docker-Hosts). @@ -343,7 +370,7 @@ Sie sehen die automatische interaktive API-Dokumentation (bereitgestellt von http://192.168.99.100/redoc oder http://127.0.0.1/redoc gehen (oder ähnlich, unter Verwendung Ihres Docker-Hosts). @@ -351,7 +378,7 @@ Sie sehen die alternative automatische Dokumentation (bereitgestellt von Cluster von Maschinen mit **Kubernetes**, Docker Swarm Mode, Nomad verwenden, oder einem anderen, ähnlich komplexen System zur Verwaltung verteilter Container auf mehreren Maschinen, möchten Sie wahrscheinlich die **Replikation auf Cluster-Ebene abwickeln**, anstatt in jedem Container einen **Prozessmanager** (wie Gunicorn mit Workern) zu verwenden. +Wenn Sie einen Cluster von Maschinen mit **Kubernetes**, Docker Swarm Mode, Nomad verwenden, oder einem anderen, ähnlich komplexen System zur Verwaltung verteilter Container auf mehreren Maschinen, möchten Sie wahrscheinlich die **Replikation auf Cluster-Ebene abwickeln**, anstatt in jedem Container einen **Prozessmanager** (wie Uvicorn mit Workern) zu verwenden. -Diese verteilten Containerverwaltungssysteme wie Kubernetes verfügen normalerweise über eine integrierte Möglichkeit, die **Replikation von Containern** zu handhaben und gleichzeitig **Load Balancing** für die eingehenden Requests zu unterstützen. Alles auf **Cluster-Ebene**. +Diese verteilten Containerverwaltungssysteme wie Kubernetes verfügen normalerweise über eine integrierte Möglichkeit, die **Replikation von Containern** zu handhaben und gleichzeitig **Load Balancing** für die eingehenden Requests zu unterstützen. Alles auf **Cluster-Ebene**. -In diesen Fällen möchten Sie wahrscheinlich ein **Docker-Image von Grund auf** erstellen, wie [oben erklärt](#dockerfile), Ihre Abhängigkeiten installieren und **einen einzelnen Uvicorn-Prozess** ausführen, anstatt etwas wie Gunicorn mit Uvicorn-Workern auszuführen. +In diesen Fällen möchten Sie wahrscheinlich ein **Docker-Image von Grund auf** erstellen, wie [oben erklärt](#dockerfile), Ihre Abhängigkeiten installieren und **einen einzelnen Uvicorn-Prozess** ausführen, anstatt mehrere Uvicorn-Worker zu verwenden. -### Load Balancer +### Load Balancer { #load-balancer } Bei der Verwendung von Containern ist normalerweise eine Komponente vorhanden, **die am Hauptport lauscht**. Es könnte sich um einen anderen Container handeln, der auch ein **TLS-Terminierungsproxy** ist, um **HTTPS** zu verarbeiten, oder ein ähnliches Tool. -Da diese Komponente die **Last** an Requests aufnehmen und diese (hoffentlich) **ausgewogen** auf die Worker verteilen würde, wird sie üblicherweise auch **Load Balancer** – Lastverteiler – genannt. +Da diese Komponente die **Last** an Requests aufnehmen und diese (hoffentlich) **ausgewogen** auf die Worker verteilen würde, wird sie üblicherweise auch **Load Balancer** genannt. /// tip | Tipp @@ -449,7 +476,7 @@ Die gleiche **TLS-Terminierungsproxy**-Komponente, die für HTTPS verwendet wird Und wenn Sie mit Containern arbeiten, verfügt das gleiche System, mit dem Sie diese starten und verwalten, bereits über interne Tools, um die **Netzwerkkommunikation** (z. B. HTTP-Requests) von diesem **Load Balancer** (das könnte auch ein **TLS-Terminierungsproxy** sein) zu den Containern mit Ihrer Anwendung weiterzuleiten. -### Ein Load Balancer – mehrere Workercontainer +### Ein Load Balancer – mehrere Workercontainer { #one-load-balancer-multiple-worker-containers } Bei der Arbeit mit **Kubernetes** oder ähnlichen verteilten Containerverwaltungssystemen würde die Verwendung ihrer internen Netzwerkmechanismen es dem einzelnen **Load Balancer**, der den Haupt-**Port** überwacht, ermöglichen, Kommunikation (Requests) an möglicherweise **mehrere Container** weiterzuleiten, in denen Ihre Anwendung ausgeführt wird. @@ -459,42 +486,49 @@ Und das verteilte Containersystem mit dem **Load Balancer** würde **die Request Und normalerweise wäre dieser **Load Balancer** in der Lage, Requests zu verarbeiten, die an *andere* Anwendungen in Ihrem Cluster gerichtet sind (z. B. eine andere Domain oder unter einem anderen URL-Pfad-Präfix), und würde diese Kommunikation an die richtigen Container weiterleiten für *diese andere* Anwendung, die in Ihrem Cluster ausgeführt wird. -### Ein Prozess pro Container +### Ein Prozess pro Container { #one-process-per-container } -In einem solchen Szenario möchten Sie wahrscheinlich **einen einzelnen (Uvicorn-)Prozess pro Container** haben, da Sie die Replikation bereits auf Cluster ebene durchführen würden. +In einem solchen Szenario möchten Sie wahrscheinlich **einen einzelnen (Uvicorn-)Prozess pro Container** haben, da Sie die Replikation bereits auf Cluster-Ebene durchführen würden. -In diesem Fall möchten Sie also **nicht** einen Prozessmanager wie Gunicorn mit Uvicorn-Workern oder Uvicorn mit seinen eigenen Uvicorn-Workern haben. Sie möchten nur einen **einzelnen Uvicorn-Prozess** pro Container haben (wahrscheinlich aber mehrere Container). +In diesem Fall möchten Sie also **nicht** mehrere Worker im Container haben, z. B. mit der `--workers` Befehlszeilenoption. Sie möchten nur einen **einzelnen Uvicorn-Prozess** pro Container haben (wahrscheinlich aber mehrere Container). -Ein weiterer Prozessmanager im Container (wie es bei Gunicorn oder Uvicorn der Fall wäre, welche Uvicorn-Worker verwalten) würde nur **unnötige Komplexität** hinzufügen, um welche Sie sich höchstwahrscheinlich bereits mit Ihrem Clustersystem kümmern. +Ein weiterer Prozessmanager im Container (wie es bei mehreren Workern der Fall wäre) würde nur **unnötige Komplexität** hinzufügen, um welche Sie sich höchstwahrscheinlich bereits mit Ihrem Clustersystem kümmern. -### Container mit mehreren Prozessen und Sonderfälle +### Container mit mehreren Prozessen und Sonderfälle { #containers-with-multiple-processes-and-special-cases } -Natürlich gibt es **Sonderfälle**, in denen Sie **einen Container** mit einem **Gunicorn-Prozessmanager** haben möchten, welcher mehrere **Uvicorn-Workerprozesse** darin startet. +Natürlich gibt es **Sonderfälle**, in denen Sie **einen Container** mit mehreren **Uvicorn-Workerprozessen** haben möchten. -In diesen Fällen können Sie das **offizielle Docker-Image** verwenden, welches **Gunicorn** als Prozessmanager enthält, welcher mehrere **Uvicorn-Workerprozesse** ausführt, sowie einige Standardeinstellungen, um die Anzahl der Worker basierend auf den verfügbaren CPU-Kernen automatisch anzupassen. Ich erzähle Ihnen weiter unten in [Offizielles Docker-Image mit Gunicorn – Uvicorn](#offizielles-docker-image-mit-gunicorn-uvicorn) mehr darüber. +In diesen Fällen können Sie die `--workers` Befehlszeilenoption verwenden, um die Anzahl der zu startenden Worker festzulegen: + +```{ .dockerfile .annotate } +FROM python:3.9 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. Hier verwenden wir die `--workers` Befehlszeilenoption, um die Anzahl der Worker auf 4 festzulegen. Hier sind einige Beispiele, wann das sinnvoll sein könnte: -#### Eine einfache Anwendung +#### Eine einfache Anwendung { #a-simple-app } -Sie könnten einen Prozessmanager im Container haben wollen, wenn Ihre Anwendung **einfach genug** ist, sodass Sie die Anzahl der Prozesse nicht (zumindest noch nicht) zu stark tunen müssen und Sie einfach einen automatisierten Standard verwenden können (mit dem offiziellen Docker-Image), und Sie führen es auf einem **einzelnen Server** aus, nicht auf einem Cluster. +Sie könnten einen Prozessmanager im Container haben wollen, wenn Ihre Anwendung **einfach genug** ist, sodass Sie es auf einem **einzelnen Server** ausführen können, nicht auf einem Cluster. -#### Docker Compose +#### Docker Compose { #docker-compose } Sie könnten das Deployment auf einem **einzelnen Server** (kein Cluster) mit **Docker Compose** durchführen, sodass Sie keine einfache Möglichkeit hätten, die Replikation von Containern (mit Docker Compose) zu verwalten und gleichzeitig das gemeinsame Netzwerk mit **Load Balancing** zu haben. Dann möchten Sie vielleicht **einen einzelnen Container** mit einem **Prozessmanager** haben, der darin **mehrere Workerprozesse** startet. -#### Prometheus und andere Gründe - -Sie könnten auch **andere Gründe** haben, die es einfacher machen würden, einen **einzelnen Container** mit **mehreren Prozessen** zu haben, anstatt **mehrere Container** mit **einem einzelnen Prozess** in jedem von ihnen. - -Beispielsweise könnten Sie (abhängig von Ihrem Setup) ein Tool wie einen Prometheus-Exporter im selben Container haben, welcher Zugriff auf **jeden der eingehenden Requests** haben sollte. - -Wenn Sie in hier **mehrere Container** hätten, würde Prometheus beim **Lesen der Metriken** standardmäßig jedes Mal diejenigen für **einen einzelnen Container** abrufen (für den Container, der den spezifischen Request verarbeitet hat), anstatt die **akkumulierten Metriken** für alle replizierten Container abzurufen. - -In diesem Fall könnte einfacher sein, **einen Container** mit **mehreren Prozessen** und ein lokales Tool (z. B. einen Prometheus-Exporter) in demselben Container zu haben, welches Prometheus-Metriken für alle internen Prozesse sammelt und diese Metriken für diesen einzelnen Container offenlegt. - --- Der Hauptpunkt ist, dass **keine** dieser Regeln **in Stein gemeißelt** ist, der man blind folgen muss. Sie können diese Ideen verwenden, um **Ihren eigenen Anwendungsfall zu evaluieren**, zu entscheiden, welcher Ansatz für Ihr System am besten geeignet ist und herauszufinden, wie Sie folgende Konzepte verwalten: @@ -506,25 +540,25 @@ Der Hauptpunkt ist, dass **keine** dieser Regeln **in Stein gemeißelt** ist, de * Arbeitsspeicher * Schritte vor dem Start -## Arbeitsspeicher +## Arbeitsspeicher { #memory } Wenn Sie **einen einzelnen Prozess pro Container** ausführen, wird von jedem dieser Container (mehr als einer, wenn sie repliziert werden) eine mehr oder weniger klar definierte, stabile und begrenzte Menge an Arbeitsspeicher verbraucht. -Und dann können Sie dieselben Speichergrenzen und -anforderungen in Ihren Konfigurationen für Ihr Container-Management-System festlegen (z. B. in **Kubernetes**). Auf diese Weise ist es in der Lage, die Container auf den **verfügbaren Maschinen** zu replizieren, wobei die von denen benötigte Speichermenge und die auf den Maschinen im Cluster verfügbare Menge berücksichtigt werden. +Und dann können Sie dieselben Speichergrenzen und -anforderungen in Ihren Konfigurationen für Ihr Container-Management-System festlegen (z. B. in **Kubernetes**). Auf diese Weise ist es in der Lage, die Container auf den **verfügbaren Maschinen** zu replizieren, wobei die von diesen benötigte Speichermenge und die auf den Maschinen im Cluster verfügbare Menge berücksichtigt werden. -Wenn Ihre Anwendung **einfach** ist, wird dies wahrscheinlich **kein Problem darstellen** und Sie müssen möglicherweise keine festen Speichergrenzen angeben. Wenn Sie jedoch **viel Speicher verbrauchen** (z. B. bei **Modellen für maschinelles Lernen**), sollten Sie überprüfen, wie viel Speicher Sie verbrauchen, und die **Anzahl der Container** anpassen, die in **jeder Maschine** ausgeführt werden. (und möglicherweise weitere Maschinen zu Ihrem Cluster hinzufügen). +Wenn Ihre Anwendung **einfach** ist, wird dies wahrscheinlich **kein Problem darstellen** und Sie müssen möglicherweise keine festen Speichergrenzen angeben. Wenn Sie jedoch **viel Speicher verbrauchen** (z. B. bei **Modellen für maschinelles Lernen**), sollten Sie überprüfen, wie viel Speicher Sie verbrauchen, und die **Anzahl der Container** anpassen, die in **jeder Maschine** ausgeführt werden (und möglicherweise weitere Maschinen zu Ihrem Cluster hinzufügen). -Wenn Sie **mehrere Prozesse pro Container** ausführen (zum Beispiel mit dem offiziellen Docker-Image), müssen Sie sicherstellen, dass die Anzahl der gestarteten Prozesse nicht **mehr Speicher verbraucht** als verfügbar ist. +Wenn Sie **mehrere Prozesse pro Container** ausführen, müssen Sie sicherstellen, dass die Anzahl der gestarteten Prozesse nicht **mehr Speicher verbraucht** als verfügbar ist. -## Schritte vor dem Start und Container +## Schritte vor dem Start und Container { #previous-steps-before-starting-and-containers } Wenn Sie Container (z. B. Docker, Kubernetes) verwenden, können Sie hauptsächlich zwei Ansätze verwenden. -### Mehrere Container +### Mehrere Container { #multiple-containers } -Wenn Sie **mehrere Container** haben, von denen wahrscheinlich jeder einen **einzelnen Prozess** ausführt (z. B. in einem **Kubernetes**-Cluster), dann möchten Sie wahrscheinlich einen **separaten Container** haben, welcher die Arbeit der **Vorab-Schritte** in einem einzelnen Container, mit einem einzelnenen Prozess ausführt, **bevor** die replizierten Workercontainer ausgeführt werden. +Wenn Sie **mehrere Container** haben, von denen wahrscheinlich jeder einen **einzelnen Prozess** ausführt (z. B. in einem **Kubernetes**-Cluster), dann möchten Sie wahrscheinlich einen **separaten Container** haben, welcher die Arbeit der **Vorab-Schritte** in einem einzelnen Container, mit einem einzelnen Prozess ausführt, **bevor** die replizierten Workercontainer ausgeführt werden. -/// info +/// info | Info Wenn Sie Kubernetes verwenden, wäre dies wahrscheinlich ein Init-Container. @@ -532,83 +566,29 @@ Wenn Sie Kubernetes verwenden, wäre dies wahrscheinlich ein tiangolo/uvicorn-gunicorn-fastapi. Dieses ist jedoch jetzt veraltet. ⛔️ -Dieses Image wäre vor allem in den oben beschriebenen Situationen nützlich: [Container mit mehreren Prozessen und Sonderfälle](#container-mit-mehreren-prozessen-und-sonderfalle). +Sie sollten wahrscheinlich **nicht** dieses Basis-Docker-Image (oder ein anderes ähnliches) verwenden. -* tiangolo/uvicorn-gunicorn-fastapi. +Wenn Sie **Kubernetes** (oder andere) verwenden und bereits **Replikation** auf Cluster-Ebene mit mehreren **Containern** eingerichtet haben. In diesen Fällen ist es besser, **ein Image von Grund auf neu zu erstellen**, wie oben beschrieben: [Ein Docker-Image für FastAPI erstellen](#build-a-docker-image-for-fastapi). -/// warning | Achtung +Und wenn Sie mehrere Worker benötigen, können Sie einfach die `--workers` Befehlszeilenoption verwenden. -Es besteht eine hohe Wahrscheinlichkeit, dass Sie dieses oder ein ähnliches Basisimage **nicht** benötigen und es besser wäre, wenn Sie das Image von Grund auf neu erstellen würden, wie [oben beschrieben in: Ein Docker-Image für FastAPI erstellen](#ein-docker-image-fur-fastapi-erstellen). +/// note | Technische Details + +Das Docker-Image wurde erstellt, als Uvicorn das Verwalten und Neustarten von ausgefallenen Workern noch nicht unterstützte, weshalb es notwendig war, Gunicorn mit Uvicorn zu verwenden, was zu einer erheblichen Komplexität führte, nur damit Gunicorn die Uvicorn-Workerprozesse verwaltet und neu startet. + +Aber jetzt, da Uvicorn (und der `fastapi`-Befehl) die Verwendung von `--workers` unterstützen, gibt es keinen Grund, ein Basis-Docker-Image an Stelle eines eigenen (das praktisch denselben Code enthält 😅) zu verwenden. /// -Dieses Image verfügt über einen **Auto-Tuning**-Mechanismus, um die **Anzahl der Arbeitsprozesse** basierend auf den verfügbaren CPU-Kernen festzulegen. - -Es verfügt über **vernünftige Standardeinstellungen**, aber Sie können trotzdem alle Konfigurationen mit **Umgebungsvariablen** oder Konfigurationsdateien ändern und aktualisieren. - -Es unterstützt auch die Ausführung von **Vorab-Schritten vor dem Start** mit einem Skript. - -/// tip | Tipp - -Um alle Konfigurationen und Optionen anzuzeigen, gehen Sie zur Docker-Image-Seite: tiangolo/uvicorn-gunicorn-fastapi. - -/// - -### Anzahl der Prozesse auf dem offiziellen Docker-Image - -Die **Anzahl der Prozesse** auf diesem Image wird **automatisch** anhand der verfügbaren CPU-**Kerne** berechnet. - -Das bedeutet, dass versucht wird, so viel **Leistung** wie möglich aus der CPU herauszuquetschen. - -Sie können das auch in der Konfiguration anpassen, indem Sie **Umgebungsvariablen**, usw. verwenden. - -Das bedeutet aber auch, da die Anzahl der Prozesse von der CPU abhängt, welche der Container ausführt, dass die **Menge des verbrauchten Speichers** ebenfalls davon abhängt. - -Wenn Ihre Anwendung also viel Speicher verbraucht (z. B. bei Modellen für maschinelles Lernen) und Ihr Server über viele CPU-Kerne, **aber wenig Speicher** verfügt, könnte Ihr Container am Ende versuchen, mehr Speicher als vorhanden zu verwenden, was zu erheblichen Leistungseinbußen (oder sogar zum Absturz) führen kann. 🚨 - -### Ein `Dockerfile` erstellen - -So würden Sie ein `Dockerfile` basierend auf diesem Image erstellen: - -```Dockerfile -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 - -COPY ./requirements.txt /app/requirements.txt - -RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt - -COPY ./app /app -``` - -### Größere Anwendungen - -Wenn Sie dem Abschnitt zum Erstellen von [größeren Anwendungen mit mehreren Dateien](../tutorial/bigger-applications.md){.internal-link target=_blank} gefolgt sind, könnte Ihr `Dockerfile` stattdessen wie folgt aussehen: - -```Dockerfile hl_lines="7" -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 - -COPY ./requirements.txt /app/requirements.txt - -RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt - -COPY ./app /app/app -``` - -### Wann verwenden - -Sie sollten dieses offizielle Basisimage (oder ein ähnliches) wahrscheinlich **nicht** benutzen, wenn Sie **Kubernetes** (oder andere) verwenden und Sie bereits **Replikation** auf Cluster ebene mit mehreren **Containern** eingerichtet haben. In diesen Fällen ist es besser, **ein Image von Grund auf zu erstellen**, wie oben beschrieben: [Ein Docker-Image für FastAPI erstellen](#ein-docker-image-fur-fastapi-erstellen). - -Dieses Image wäre vor allem in den oben in [Container mit mehreren Prozessen und Sonderfälle](#container-mit-mehreren-prozessen-und-sonderfalle) beschriebenen Sonderfällen nützlich. Wenn Ihre Anwendung beispielsweise **einfach genug** ist, dass das Festlegen einer Standardanzahl von Prozessen basierend auf der CPU gut funktioniert, möchten Sie sich nicht mit der manuellen Konfiguration der Replikation auf Cluster ebene herumschlagen und führen nicht mehr als einen Container mit Ihrer Anwendung aus. Oder wenn Sie das Deployment mit **Docker Compose** durchführen und auf einem einzelnen Server laufen, usw. - -## Deployment des Containerimages +## Deployment des Containerimages { #deploy-the-container-image } Nachdem Sie ein Containerimage (Docker) haben, gibt es mehrere Möglichkeiten, es bereitzustellen. @@ -620,100 +600,11 @@ Zum Beispiel: * Mit einem anderen Tool wie Nomad * Mit einem Cloud-Dienst, der Ihr Containerimage nimmt und es bereitstellt -## Docker-Image mit Poetry +## Docker-Image mit `uv` { #docker-image-with-uv } -Wenn Sie Poetry verwenden, um die Abhängigkeiten Ihres Projekts zu verwalten, können Sie Dockers mehrphasige Builds verwenden: +Wenn Sie uv verwenden, um Ihr Projekt zu installieren und zu verwalten, können Sie deren uv-Docker-Leitfaden befolgen. -```{ .dockerfile .annotate } -# (1) -FROM python:3.9 as requirements-stage - -# (2) -WORKDIR /tmp - -# (3) -RUN pip install poetry - -# (4) -COPY ./pyproject.toml ./poetry.lock* /tmp/ - -# (5) -RUN poetry export -f requirements.txt --output requirements.txt --without-hashes - -# (6) -FROM python:3.9 - -# (7) -WORKDIR /code - -# (8) -COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt - -# (9) -RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt - -# (10) -COPY ./app /code/app - -# (11) -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] -``` - -1. Dies ist die erste Phase, genannt `requirements-stage` – „Anforderungsphase“. - -2. Setze `/tmp` als aktuelles Arbeitsverzeichnis. - - Hier werden wir die Datei `requirements.txt` generieren. - -3. Installiere Poetry in dieser Docker-Phase. - -4. Kopiere die Dateien `pyproject.toml` und `poetry.lock` in das Verzeichnis `/tmp`. - - Da es `./poetry.lock*` verwendet (endet mit einem `*`), stürzt es nicht ab, wenn diese Datei noch nicht verfügbar ist. - -5. Generiere die Datei `requirements.txt`. - -6. Dies ist die letzte Phase. Alles hier bleibt im endgültigen Containerimage erhalten. - -7. Setze das aktuelle Arbeitsverzeichnis auf `/code`. - -8. Kopiere die Datei `requirements.txt` in das Verzeichnis `/code`. - - Diese Datei existiert nur in der vorherigen Docker-Phase, deshalb verwenden wir `--from-requirements-stage`, um sie zu kopieren. - -9. Installiere die Paketabhängigkeiten von der generierten Datei `requirements.txt`. - -10. Kopiere das Verzeichnis `app` in das Verzeichnis `/code`. - -11. Führe den Befehl `uvicorn` aus und weise ihn an, das aus `app.main` importierte `app`-Objekt zu verwenden. - -/// tip | Tipp - -Klicken Sie auf die Zahlenblasen, um zu sehen, was jede Zeile bewirkt. - -/// - -Eine **Docker-Phase** ist ein Teil eines `Dockerfile`s, welcher als **temporäres Containerimage** fungiert und nur zum Generieren einiger Dateien für die spätere Verwendung verwendet wird. - -Die erste Phase wird nur zur **Installation von Poetry** und zur **Generierung der `requirements.txt`** mit deren Projektabhängigkeiten aus der Datei `pyproject.toml` von Poetry verwendet. - -Diese `requirements.txt`-Datei wird später in der **nächsten Phase** mit `pip` verwendet. - -Im endgültigen Containerimage bleibt **nur die letzte Stufe** erhalten. Die vorherigen Stufen werden verworfen. - -Bei der Verwendung von Poetry wäre es sinnvoll, **mehrstufige Docker-Builds** zu verwenden, da Poetry und seine Abhängigkeiten nicht wirklich im endgültigen Containerimage installiert sein müssen, sondern Sie brauchen **nur** die Datei `requirements.txt`, um Ihre Projektabhängigkeiten zu installieren. - -Dann würden Sie im nächsten (und letzten) Schritt das Image mehr oder weniger auf die gleiche Weise wie zuvor beschrieben erstellen. - -### Hinter einem TLS-Terminierungsproxy – Poetry - -Auch hier gilt: Wenn Sie Ihren Container hinter einem TLS-Terminierungsproxy (Load Balancer) wie Nginx oder Traefik ausführen, fügen Sie dem Befehl die Option `--proxy-headers` hinzu: - -```Dockerfile -CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"] -``` - -## Zusammenfassung +## Zusammenfassung { #recap } Mithilfe von Containersystemen (z. B. mit **Docker** und **Kubernetes**) ist es ziemlich einfach, alle **Deployment-Konzepte** zu handhaben: @@ -727,5 +618,3 @@ Mithilfe von Containersystemen (z. B. mit **Docker** und **Kubernetes**) ist es In den meisten Fällen möchten Sie wahrscheinlich kein Basisimage verwenden und stattdessen **ein Containerimage von Grund auf erstellen**, eines basierend auf dem offiziellen Python-Docker-Image. Indem Sie auf die **Reihenfolge** der Anweisungen im `Dockerfile` und den **Docker-Cache** achten, können Sie **die Build-Zeiten minimieren**, um Ihre Produktivität zu erhöhen (und Langeweile zu vermeiden). 😎 - -In bestimmten Sonderfällen möchten Sie möglicherweise das offizielle Docker-Image für FastAPI verwenden. 🤓 diff --git a/docs/de/docs/deployment/https.md b/docs/de/docs/deployment/https.md index a216f44af..1c4ce6b44 100644 --- a/docs/de/docs/deployment/https.md +++ b/docs/de/docs/deployment/https.md @@ -1,4 +1,4 @@ -# Über HTTPS +# Über HTTPS { #about-https } Es ist leicht anzunehmen, dass HTTPS etwas ist, was einfach nur „aktiviert“ wird oder nicht. @@ -22,19 +22,19 @@ Aus **Sicht des Entwicklers** sollten Sie beim Nachdenken über HTTPS Folgendes * Die Verschlüsselung der Verbindung erfolgt auf **TCP-Ebene**. * Das ist eine Schicht **unter HTTP**. * Die Handhabung von **Zertifikaten und Verschlüsselung** erfolgt also **vor HTTP**. -* **TCP weiß nichts über „Domains“**. Nur über IP-Adressen. +* **TCP weiß nichts über „Domains“**. Nur über IP-Adressen. * Die Informationen über die angeforderte **spezifische Domain** befinden sich in den **HTTP-Daten**. * Die **HTTPS-Zertifikate** „zertifizieren“ eine **bestimmte Domain**, aber das Protokoll und die Verschlüsselung erfolgen auf TCP-Ebene, **ohne zu wissen**, um welche Domain es sich handelt. * **Standardmäßig** bedeutet das, dass Sie nur **ein HTTPS-Zertifikat pro IP-Adresse** haben können. * Ganz gleich, wie groß Ihr Server ist oder wie klein die einzelnen Anwendungen darauf sind. * Hierfür gibt es jedoch eine **Lösung**. -* Es gibt eine **Erweiterung** zum **TLS**-Protokoll (dasjenige, das die Verschlüsselung auf TCP-Ebene, vor HTTP, verwaltet) namens **SNI**. - * Mit dieser SNI-Erweiterung kann ein einzelner Server (mit einer **einzelnen IP-Adresse**) über **mehrere HTTPS-Zertifikate** verfügen und **mehrere HTTPS-Domains/Anwendungen** bedienen. +* Es gibt eine **Erweiterung** zum **TLS**-Protokoll (dasjenige, das die Verschlüsselung auf TCP-Ebene, vor HTTP, verwaltet) namens **SNI**. + * Mit dieser SNI-Erweiterung kann ein einzelner Server (mit einer **einzelnen IP-Adresse**) über **mehrere HTTPS-Zertifikate** verfügen und **mehrere HTTPS-Domains/Anwendungen bereitstellen**. * Damit das funktioniert, muss eine **einzelne** Komponente (Programm), die auf dem Server ausgeführt wird und welche die **öffentliche IP-Adresse** überwacht, **alle HTTPS-Zertifikate** des Servers haben. * **Nachdem** eine sichere Verbindung hergestellt wurde, ist das Kommunikationsprotokoll **immer noch HTTP**. * Die Inhalte sind **verschlüsselt**, auch wenn sie mit dem **HTTP-Protokoll** gesendet werden. -Es ist eine gängige Praxis, **ein Programm/HTTP-Server** auf dem Server (der Maschine, dem Host usw.) laufen zu lassen, welches **alle HTTPS-Aspekte verwaltet**: Empfangen der **verschlüsselten HTTPS-Requests**, Senden der **entschlüsselten HTTP-Requests** an die eigentliche HTTP-Anwendung die auf demselben Server läuft (in diesem Fall die **FastAPI**-Anwendung), entgegennehmen der **HTTP-Response** von der Anwendung, **verschlüsseln derselben** mithilfe des entsprechenden **HTTPS-Zertifikats** und Zurücksenden zum Client über **HTTPS**. Dieser Server wird oft als **TLS-Terminierungsproxy** bezeichnet. +Es ist eine gängige Praxis, **ein Programm/HTTP-Server** auf dem Server (der Maschine, dem Host usw.) laufen zu lassen, welches **alle HTTPS-Aspekte verwaltet**: Empfangen der **verschlüsselten HTTPS-Requests**, Senden der **entschlüsselten HTTP-Requests** an die eigentliche HTTP-Anwendung die auf demselben Server läuft (in diesem Fall die **FastAPI**-Anwendung), entgegennehmen der **HTTP-Response** von der Anwendung, **verschlüsseln derselben** mithilfe des entsprechenden **HTTPS-Zertifikats** und Zurücksenden zum Client über **HTTPS**. Dieser Server wird oft als **TLS-Terminierungsproxy** bezeichnet. Einige der Optionen, die Sie als TLS-Terminierungsproxy verwenden können, sind: @@ -43,7 +43,7 @@ Einige der Optionen, die Sie als TLS-Terminierungsproxy verwenden können, sind: * Nginx * HAProxy -## Let's Encrypt +## Let's Encrypt { #lets-encrypt } Vor Let's Encrypt wurden diese **HTTPS-Zertifikate** von vertrauenswürdigen Dritten verkauft. @@ -57,13 +57,13 @@ Die Domains werden sicher verifiziert und die Zertifikate werden automatisch gen Die Idee besteht darin, den Erwerb und die Erneuerung der Zertifikate zu automatisieren, sodass Sie **sicheres HTTPS, kostenlos und für immer** haben können. -## HTTPS für Entwickler +## HTTPS für Entwickler { #https-for-developers } Hier ist ein Beispiel, wie eine HTTPS-API aussehen könnte, Schritt für Schritt, wobei vor allem die für Entwickler wichtigen Ideen berücksichtigt werden. -### Domainname +### Domainname { #domain-name } -Alles beginnt wahrscheinlich damit, dass Sie einen **Domainnamen erwerben**. Anschließend konfigurieren Sie ihn in einem DNS-Server (wahrscheinlich beim selben Cloud-Anbieter). +Alles beginnt wahrscheinlich damit, dass Sie einen **Domainnamen erwerben**. Anschließend konfigurieren Sie ihn in einem DNS-Server (wahrscheinlich beim selben Cloudanbieter). Sie würden wahrscheinlich einen Cloud-Server (eine virtuelle Maschine) oder etwas Ähnliches bekommen, und dieser hätte eine feste **öffentliche IP-Adresse**. @@ -77,17 +77,17 @@ Dieser Domainnamen-Aspekt liegt weit vor HTTPS, aber da alles von der Domain und /// -### DNS +### DNS { #dns } Konzentrieren wir uns nun auf alle tatsächlichen HTTPS-Aspekte. -Zuerst würde der Browser mithilfe der **DNS-Server** herausfinden, welches die **IP für die Domain** ist, in diesem Fall für `someapp.example.com`. +Zuerst würde der Browser mithilfe der **DNS-Server** herausfinden, welches die **IP für die Domain** ist, in diesem Fall `someapp.example.com`. Die DNS-Server geben dem Browser eine bestimmte **IP-Adresse** zurück. Das wäre die von Ihrem Server verwendete öffentliche IP-Adresse, die Sie in den DNS-Servern konfiguriert haben. -### TLS-Handshake-Start +### TLS-Handshake-Start { #tls-handshake-start } Der Browser kommuniziert dann mit dieser IP-Adresse über **Port 443** (den HTTPS-Port). @@ -97,7 +97,7 @@ Der erste Teil der Kommunikation besteht lediglich darin, die Verbindung zwische Diese Interaktion zwischen dem Client und dem Server zum Aufbau der TLS-Verbindung wird als **TLS-Handshake** bezeichnet. -### TLS mit SNI-Erweiterung +### TLS mit SNI-Erweiterung { #tls-with-sni-extension } **Nur ein Prozess** im Server kann an einem bestimmten **Port** einer bestimmten **IP-Adresse** lauschen. Möglicherweise gibt es andere Prozesse, die an anderen Ports dieselbe IP-Adresse abhören, jedoch nur einen für jede Kombination aus IP-Adresse und Port. @@ -127,7 +127,7 @@ Beachten Sie, dass die Verschlüsselung der Kommunikation auf der **TCP-Ebene** /// -### HTTPS-Request +### HTTPS-Request { #https-request } Da Client und Server (sprich, der Browser und der TLS-Terminierungsproxy) nun über eine **verschlüsselte TCP-Verbindung** verfügen, können sie die **HTTP-Kommunikation** starten. @@ -135,19 +135,19 @@ Der Client sendet also einen **HTTPS-Request**. Das ist einfach ein HTTP-Request -### Den Request entschlüsseln +### Den Request entschlüsseln { #decrypt-the-request } Der TLS-Terminierungsproxy würde die vereinbarte Verschlüsselung zum **Entschlüsseln des Requests** verwenden und den **einfachen (entschlüsselten) HTTP-Request** an den Prozess weiterleiten, der die Anwendung ausführt (z. B. einen Prozess, bei dem Uvicorn die FastAPI-Anwendung ausführt). -### HTTP-Response +### HTTP-Response { #http-response } Die Anwendung würde den Request verarbeiten und eine **einfache (unverschlüsselte) HTTP-Response** an den TLS-Terminierungsproxy senden. -### HTTPS-Response +### HTTPS-Response { #https-response } Der TLS-Terminierungsproxy würde dann die Response mithilfe der zuvor vereinbarten Kryptografie (als das Zertifikat für `someapp.example.com` verhandelt wurde) **verschlüsseln** und sie an den Browser zurücksenden. @@ -157,7 +157,7 @@ Als Nächstes überprüft der Browser, ob die Response gültig und mit dem richt Der Client (Browser) weiß, dass die Response vom richtigen Server kommt, da dieser die Kryptografie verwendet, die zuvor mit dem **HTTPS-Zertifikat** vereinbart wurde. -### Mehrere Anwendungen +### Mehrere Anwendungen { #multiple-applications } Auf demselben Server (oder denselben Servern) könnten sich **mehrere Anwendungen** befinden, beispielsweise andere API-Programme oder eine Datenbank. @@ -167,7 +167,7 @@ Nur ein Prozess kann diese spezifische IP und den Port verarbeiten (in unserem B Auf diese Weise könnte der TLS-Terminierungsproxy HTTPS und Zertifikate für **mehrere Domains**, für mehrere Anwendungen, verarbeiten und die Requests dann jeweils an die richtige Anwendung weiterleiten. -### Verlängerung des Zertifikats +### Verlängerung des Zertifikats { #certificate-renewal } Irgendwann in der Zukunft würde jedes Zertifikat **ablaufen** (etwa 3 Monate nach dem Erwerb). @@ -190,7 +190,39 @@ Um dies zu erreichen und den unterschiedlichen Anwendungsanforderungen gerecht z Dieser ganze Erneuerungsprozess, während die Anwendung weiterhin bereitgestellt wird, ist einer der Hauptgründe, warum Sie ein **separates System zur Verarbeitung von HTTPS** mit einem TLS-Terminierungsproxy haben möchten, anstatt einfach die TLS-Zertifikate direkt mit dem Anwendungsserver zu verwenden (z. B. Uvicorn). -## Zusammenfassung +## Proxy-Forwarded-Header { #proxy-forwarded-headers } + +Wenn Sie einen Proxy zur Verarbeitung von HTTPS verwenden, weiß Ihr **Anwendungsserver** (z. B. Uvicorn über das FastAPI CLI) nichts über den HTTPS-Prozess, er kommuniziert per einfachem HTTP mit dem **TLS-Terminierungsproxy**. + +Dieser **Proxy** würde normalerweise unmittelbar vor dem Übermitteln der Anfrage an den **Anwendungsserver** einige HTTP-Header dynamisch setzen, um dem Anwendungsserver mitzuteilen, dass der Request vom Proxy **weitergeleitet** wird. + +/// note | Technische Details + +Die Proxy-Header sind: + +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Host + +/// + +Trotzdem, da der **Anwendungsserver** nicht weiß, dass er sich hinter einem vertrauenswürdigen **Proxy** befindet, würde er diesen Headern standardmäßig nicht vertrauen. + +Sie können den **Anwendungsserver** jedoch so konfigurieren, dass er den vom **Proxy** gesendeten *Forwarded*-Headern vertraut. Wenn Sie das FastAPI CLI verwenden, können Sie die *CLI-Option* `--forwarded-allow-ips` nutzen, um anzugeben, von welchen IPs er diesen *Forwarded*-Headern vertrauen soll. + +Wenn der **Anwendungsserver** beispielsweise nur Kommunikation vom vertrauenswürdigen **Proxy** empfängt, können Sie `--forwarded-allow-ips="*"` setzen, um allen eingehenden IPs zu vertrauen, da er nur Requests von der vom **Proxy** verwendeten IP erhalten wird. + +Auf diese Weise kann die Anwendung ihre eigene öffentliche URL, ob sie HTTPS verwendet, die Domain, usw. erkennen. + +Das ist z. B. nützlich, um Redirects korrekt zu handhaben. + +/// tip | Tipp + +Mehr dazu finden Sie in der Dokumentation zu [Hinter einem Proxy – Proxy-Forwarded-Header aktivieren](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers){.internal-link target=_blank} + +/// + +## Zusammenfassung { #recap } **HTTPS** zu haben ist sehr wichtig und in den meisten Fällen eine **kritische Anforderung**. Die meiste Arbeit, die Sie als Entwickler in Bezug auf HTTPS aufwenden müssen, besteht lediglich darin, **diese Konzepte zu verstehen** und wie sie funktionieren. diff --git a/docs/de/docs/deployment/index.md b/docs/de/docs/deployment/index.md index 1aa131097..65c76edce 100644 --- a/docs/de/docs/deployment/index.md +++ b/docs/de/docs/deployment/index.md @@ -1,18 +1,18 @@ -# Deployment +# Deployment { #deployment } Das Deployment einer **FastAPI**-Anwendung ist relativ einfach. -## Was bedeutet Deployment? +## Was bedeutet Deployment { #what-does-deployment-mean } -**Deployment** (Deutsch etwa: **Bereitstellen der Anwendung**) bedeutet, die notwendigen Schritte durchzuführen, um die Anwendung **für die Endbenutzer verfügbar** zu machen. +**Deployment** bedeutet, die notwendigen Schritte durchzuführen, um die Anwendung **für die Endbenutzer verfügbar** zu machen. Bei einer **Web-API** bedeutet das normalerweise, diese auf einem **entfernten Rechner** zu platzieren, mit einem **Serverprogramm**, welches gute Leistung, Stabilität, usw. bietet, damit Ihre **Benutzer** auf die Anwendung effizient und ohne Unterbrechungen oder Probleme **zugreifen** können. Das steht im Gegensatz zu den **Entwicklungsphasen**, in denen Sie ständig den Code ändern, kaputt machen, reparieren, den Entwicklungsserver stoppen und neu starten, usw. -## Deployment-Strategien +## Deployment-Strategien { #deployment-strategies } -Abhängig von Ihrem spezifischen Anwendungsfall und den von Ihnen verwendeten Tools gibt es mehrere Möglichkeiten, das zu tun. +Es gibt mehrere Möglichkeiten, dies zu tun, abhängig von Ihrem spezifischen Anwendungsfall und den von Ihnen verwendeten Tools. Sie könnten mithilfe einer Kombination von Tools selbst **einen Server bereitstellen**, Sie könnten einen **Cloud-Dienst** nutzen, der einen Teil der Arbeit für Sie erledigt, oder andere mögliche Optionen. diff --git a/docs/de/docs/deployment/manually.md b/docs/de/docs/deployment/manually.md index fdb33f7fe..6393f8ebc 100644 --- a/docs/de/docs/deployment/manually.md +++ b/docs/de/docs/deployment/manually.md @@ -1,30 +1,82 @@ -# Einen Server manuell ausführen – Uvicorn +# Einen Server manuell ausführen { #run-a-server-manually } -Das Wichtigste, was Sie zum Ausführen einer **FastAPI**-Anwendung auf einer entfernten Servermaschine benötigen, ist ein ASGI-Serverprogramm, wie **Uvicorn**. +## Den `fastapi run` Befehl verwenden { #use-the-fastapi-run-command } -Es gibt 3 Hauptalternativen: +Kurz gesagt, nutzen Sie `fastapi run`, um Ihre FastAPI-Anwendung bereitzustellen: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +Das würde in den meisten Fällen funktionieren. 😎 + +Sie könnten diesen Befehl beispielsweise verwenden, um Ihre **FastAPI**-App in einem Container, auf einem Server usw. zu starten. + +## ASGI-Server { #asgi-servers } + +Lassen Sie uns ein wenig tiefer in die Details eintauchen. + +FastAPI verwendet einen Standard zum Erstellen von Python-Webframeworks und -Servern, der als ASGI bekannt ist. FastAPI ist ein ASGI-Webframework. + +Das Wichtigste, was Sie benötigen, um eine **FastAPI**-Anwendung (oder eine andere ASGI-Anwendung) auf einer entfernten Servermaschine auszuführen, ist ein ASGI-Serverprogramm wie **Uvicorn**, der standardmäßig im `fastapi`-Kommando enthalten ist. + +Es gibt mehrere Alternativen, einschließlich: * Uvicorn: ein hochperformanter ASGI-Server. -* Hypercorn: ein ASGI-Server, der unter anderem mit HTTP/2 und Trio kompatibel ist. -* Daphne: Der für Django Channels entwickelte ASGI-Server. +* Hypercorn: ein ASGI-Server, der unter anderem kompatibel mit HTTP/2 und Trio ist. +* Daphne: der für Django Channels entwickelte ASGI-Server. +* Granian: Ein Rust HTTP-Server für Python-Anwendungen. +* NGINX Unit: NGINX Unit ist eine leichte und vielseitige Laufzeitumgebung für Webanwendungen. -## Servermaschine und Serverprogramm +## Servermaschine und Serverprogramm { #server-machine-and-server-program } -Bei den Benennungen gibt es ein kleines Detail, das Sie beachten sollten. 💡 +Es gibt ein kleines Detail bei den Namen, das Sie beachten sollten. 💡 -Das Wort „**Server**“ bezieht sich häufig sowohl auf den entfernten-/Cloud-Computer (die physische oder virtuelle Maschine) als auch auf das Programm, das auf dieser Maschine ausgeführt wird (z. B. Uvicorn). +Das Wort „**Server**“ wird häufig verwendet, um sowohl den entfernten/Cloud-Computer (die physische oder virtuelle Maschine) als auch das Programm zu bezeichnen, das auf dieser Maschine läuft (z. B. Uvicorn). -Denken Sie einfach daran, wenn Sie „Server“ im Allgemeinen lesen, dass es sich auf eines dieser beiden Dinge beziehen kann. +Denken Sie einfach daran, dass sich „Server“ im Allgemeinen auf eines dieser beiden Dinge beziehen kann. Wenn man sich auf die entfernte Maschine bezieht, wird sie üblicherweise als **Server**, aber auch als **Maschine**, **VM** (virtuelle Maschine) oder **Knoten** bezeichnet. Diese Begriffe beziehen sich auf irgendeine Art von entfernten Rechner, normalerweise unter Linux, auf dem Sie Programme ausführen. -## Das Serverprogramm installieren +## Das Serverprogramm installieren { #install-the-server-program } -Sie können einen ASGI-kompatiblen Server installieren mit: +Wenn Sie FastAPI installieren, wird es mit einem Produktionsserver, Uvicorn, geliefert, und Sie können ihn mit dem `fastapi run` Befehl starten. -//// tab | Uvicorn +Aber Sie können auch ein ASGI-Serverprogramm manuell installieren. -* Uvicorn, ein blitzschneller ASGI-Server, basierend auf uvloop und httptools. +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann die Serveranwendung installieren. + +Zum Beispiel, um Uvicorn zu installieren:
@@ -36,39 +88,21 @@ $ pip install "uvicorn[standard]"
+Ein ähnlicher Prozess würde für jedes andere ASGI-Serverprogramm gelten. + /// tip | Tipp Durch das Hinzufügen von `standard` installiert und verwendet Uvicorn einige empfohlene zusätzliche Abhängigkeiten. -Inklusive `uvloop`, einen hochperformanten Drop-in-Ersatz für `asyncio`, welcher für einen großen Leistungsschub bei der Nebenläufigkeit sorgt. +Dazu gehört `uvloop`, der hochperformante Drop-in-Ersatz für `asyncio`, der den großen Nebenläufigkeits-Performanz-Schub bietet. + +Wenn Sie FastAPI mit etwas wie `pip install "fastapi[standard]"` installieren, erhalten Sie auch `uvicorn[standard]`. /// -//// +## Das Serverprogramm ausführen { #run-the-server-program } -//// tab | Hypercorn - -* Hypercorn, ein ASGI-Server, der auch mit HTTP/2 kompatibel ist. - -
- -```console -$ pip install hypercorn - ----> 100% -``` - -
- -... oder jeden anderen ASGI-Server. - -//// - -## Das Serverprogramm ausführen - -Anschließend können Sie Ihre Anwendung auf die gleiche Weise ausführen, wie Sie es in den Tutorials getan haben, jedoch ohne die Option `--reload`, z. B.: - -//// tab | Uvicorn +Wenn Sie einen ASGI-Server manuell installiert haben, müssen Sie normalerweise einen Importstring in einem speziellen Format übergeben, damit er Ihre FastAPI-Anwendung importiert:
@@ -80,72 +114,36 @@ $ uvicorn main:app --host 0.0.0.0 --port 80
-//// +/// note | Hinweis -//// tab | Hypercorn +Der Befehl `uvicorn main:app` bezieht sich auf: -
+* `main`: die Datei `main.py` (das Python-„Modul“). +* `app`: das Objekt, das innerhalb von `main.py` mit der Zeile `app = FastAPI()` erstellt wurde. -```console -$ hypercorn main:app --bind 0.0.0.0:80 +Es ist äquivalent zu: -Running on 0.0.0.0:8080 over http (CTRL + C to quit) +```Python +from main import app ``` -
- -//// - -/// warning | Achtung - -Denken Sie daran, die Option `--reload` zu entfernen, wenn Sie diese verwendet haben. - -Die Option `--reload` verbraucht viel mehr Ressourcen, ist instabiler, usw. - -Sie hilft sehr während der **Entwicklung**, aber Sie sollten sie **nicht** in der **Produktion** verwenden. - /// -## Hypercorn mit Trio +Jedes alternative ASGI-Serverprogramm hätte einen ähnlichen Befehl, Sie können in deren jeweiligen Dokumentationen mehr lesen. -Starlette und **FastAPI** basieren auf AnyIO, welches diese sowohl mit der Python-Standardbibliothek asyncio, als auch mit Trio kompatibel macht. +/// warning | Achtung -Dennoch ist Uvicorn derzeit nur mit asyncio kompatibel und verwendet normalerweise `uvloop`, den leistungsstarken Drop-in-Ersatz für `asyncio`. +Uvicorn und andere Server unterstützen eine `--reload`-Option, die während der Entwicklung nützlich ist. -Wenn Sie jedoch **Trio** direkt verwenden möchten, können Sie **Hypercorn** verwenden, da dieses es unterstützt. ✨ +Die `--reload`-Option verbraucht viel mehr Ressourcen, ist instabiler, usw. -### Hypercorn mit Trio installieren +Sie hilft während der **Entwicklung**, Sie sollten sie jedoch **nicht** in der **Produktion** verwenden. -Zuerst müssen Sie Hypercorn mit Trio-Unterstützung installieren: +/// -
+## Deployment-Konzepte { #deployment-concepts } -```console -$ pip install "hypercorn[trio]" ----> 100% -``` - -
- -### Mit Trio ausführen - -Dann können Sie die Befehlszeilenoption `--worker-class` mit dem Wert `trio` übergeben: - -
- -```console -$ hypercorn main:app --worker-class trio -``` - -
- -Und das startet Hypercorn mit Ihrer Anwendung und verwendet Trio als Backend. - -Jetzt können Sie Trio intern in Ihrer Anwendung verwenden. Oder noch besser: Sie können AnyIO verwenden, sodass Ihr Code sowohl mit Trio als auch asyncio kompatibel ist. 🎉 - -## Konzepte des Deployments - -Obige Beispiele führen das Serverprogramm (z. B. Uvicorn) aus, starten **einen einzelnen Prozess** und überwachen alle IPs (`0.0.0.0`) an einem vordefinierten Port (z. B. `80`). +Diese Beispiele führen das Serverprogramm (z. B. Uvicorn) aus, starten **einen einzelnen Prozess** und überwachen alle IPs (`0.0.0.0`) an einem vordefinierten Port (z. B. `80`). Das ist die Grundidee. Aber Sie möchten sich wahrscheinlich um einige zusätzliche Dinge kümmern, wie zum Beispiel: @@ -153,7 +151,7 @@ Das ist die Grundidee. Aber Sie möchten sich wahrscheinlich um einige zusätzli * Beim Hochfahren ausführen * Neustarts * Replikation (die Anzahl der laufenden Prozesse) -* Arbeitsspeicher +* Speicher * Schritte vor dem Start In den nächsten Kapiteln erzähle ich Ihnen mehr über jedes dieser Konzepte, wie Sie über diese nachdenken, und gebe Ihnen einige konkrete Beispiele mit Strategien für den Umgang damit. 🚀 diff --git a/docs/de/docs/deployment/server-workers.md b/docs/de/docs/deployment/server-workers.md index 5cd282b4b..169ed822b 100644 --- a/docs/de/docs/deployment/server-workers.md +++ b/docs/de/docs/deployment/server-workers.md @@ -1,4 +1,4 @@ -# Serverworker – Gunicorn mit Uvicorn +# Serverworker – Uvicorn mit Workern { #server-workers-uvicorn-with-workers } Schauen wir uns die Deployment-Konzepte von früher noch einmal an: @@ -9,123 +9,79 @@ Schauen wir uns die Deployment-Konzepte von früher noch einmal an: * Arbeitsspeicher * Schritte vor dem Start -Bis zu diesem Punkt, in allen Tutorials in der Dokumentation, haben Sie wahrscheinlich ein **Serverprogramm** wie Uvicorn ausgeführt, in einem **einzelnen Prozess**. +Bis zu diesem Punkt, in allen Tutorials in der Dokumentation, haben Sie wahrscheinlich ein **Serverprogramm** ausgeführt, zum Beispiel mit dem `fastapi`-Befehl, der Uvicorn startet, und einen **einzelnen Prozess** ausführt. -Wenn Sie Anwendungen bereitstellen, möchten Sie wahrscheinlich eine gewisse **Replikation von Prozessen**, um **mehrere CPU-Kerne** zu nutzen und mehr Requests bearbeiten zu können. +Wenn Sie Anwendungen bereitstellen, möchten Sie wahrscheinlich eine gewisse **Replikation von Prozessen**, um **mehrere Kerne** zu nutzen und mehr Requests bearbeiten zu können. Wie Sie im vorherigen Kapitel über [Deployment-Konzepte](concepts.md){.internal-link target=_blank} gesehen haben, gibt es mehrere Strategien, die Sie anwenden können. -Hier zeige ich Ihnen, wie Sie **Gunicorn** mit **Uvicorn Workerprozessen** verwenden. +Hier zeige ich Ihnen, wie Sie **Uvicorn** mit **Workerprozessen** verwenden, indem Sie den `fastapi`-Befehl oder den `uvicorn`-Befehl direkt verwenden. -/// info +/// info | Info Wenn Sie Container verwenden, beispielsweise mit Docker oder Kubernetes, erzähle ich Ihnen mehr darüber im nächsten Kapitel: [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank}. -Insbesondere wenn die Anwendung auf **Kubernetes** läuft, werden Sie Gunicorn wahrscheinlich **nicht** verwenden wollen und stattdessen **einen einzelnen Uvicorn-Prozess pro Container** ausführen wollen, aber ich werde Ihnen später in diesem Kapitel mehr darüber erzählen. +Insbesondere wenn die Anwendung auf **Kubernetes** läuft, werden Sie wahrscheinlich **keine** Worker verwenden wollen, und stattdessen **einen einzelnen Uvicorn-Prozess pro Container** ausführen wollen, aber ich werde Ihnen später in diesem Kapitel mehr darüber erzählen. /// -## Gunicorn mit Uvicorn-Workern +## Mehrere Worker { #multiple-workers } -**Gunicorn** ist hauptsächlich ein Anwendungsserver, der den **WSGI-Standard** verwendet. Das bedeutet, dass Gunicorn Anwendungen wie Flask und Django ausliefern kann. Gunicorn selbst ist nicht mit **FastAPI** kompatibel, da FastAPI den neuesten **ASGI-Standard** verwendet. +Sie können mehrere Worker mit der `--workers`-Befehlszeilenoption starten: -Aber Gunicorn kann als **Prozessmanager** arbeiten und Benutzer können ihm mitteilen, welche bestimmte **Workerprozessklasse** verwendet werden soll. Dann würde Gunicorn einen oder mehrere **Workerprozesse** starten, diese Klasse verwendend. +//// tab | `fastapi` -Und **Uvicorn** hat eine **Gunicorn-kompatible Workerklasse**. - -Mit dieser Kombination würde Gunicorn als **Prozessmanager** fungieren und den **Port** und die **IP** abhören. Und er würde die Kommunikation an die Workerprozesse **weiterleiten**, welche die **Uvicorn-Klasse** ausführen. - -Und dann wäre die Gunicorn-kompatible **Uvicorn-Worker**-Klasse dafür verantwortlich, die von Gunicorn gesendeten Daten in den ASGI-Standard zu konvertieren, damit FastAPI diese verwenden kann. - -## Gunicorn und Uvicorn installieren +Wenn Sie den `fastapi`-Befehl verwenden:
```console -$ pip install "uvicorn[standard]" gunicorn +$ fastapi run --workers 4 main.py ----> 100% + FastAPI Starting production server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. ```
-Dadurch wird sowohl Uvicorn mit zusätzlichen `standard`-Packages (um eine hohe Leistung zu erzielen) als auch Gunicorn installiert. +//// -## Gunicorn mit Uvicorn-Workern ausführen +//// tab | `uvicorn` -Dann können Sie Gunicorn ausführen mit: - -
- -```console -$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80 - -[19499] [INFO] Starting gunicorn 20.1.0 -[19499] [INFO] Listening at: http://0.0.0.0:80 (19499) -[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker -[19511] [INFO] Booting worker with pid: 19511 -[19513] [INFO] Booting worker with pid: 19513 -[19514] [INFO] Booting worker with pid: 19514 -[19515] [INFO] Booting worker with pid: 19515 -[19511] [INFO] Started server process [19511] -[19511] [INFO] Waiting for application startup. -[19511] [INFO] Application startup complete. -[19513] [INFO] Started server process [19513] -[19513] [INFO] Waiting for application startup. -[19513] [INFO] Application startup complete. -[19514] [INFO] Started server process [19514] -[19514] [INFO] Waiting for application startup. -[19514] [INFO] Application startup complete. -[19515] [INFO] Started server process [19515] -[19515] [INFO] Waiting for application startup. -[19515] [INFO] Application startup complete. -``` - -
- -Sehen wir uns an, was jede dieser Optionen bedeutet: - -* `main:app`: Das ist die gleiche Syntax, die auch von Uvicorn verwendet wird. `main` bedeutet das Python-Modul mit dem Namen `main`, also eine Datei `main.py`. Und `app` ist der Name der Variable, welche die **FastAPI**-Anwendung ist. - * Stellen Sie sich einfach vor, dass `main:app` einer Python-`import`-Anweisung wie der folgenden entspricht: - - ```Python - from main import app - ``` - - * Der Doppelpunkt in `main:app` entspricht also dem Python-`import`-Teil in `from main import app`. - -* `--workers`: Die Anzahl der zu verwendenden Workerprozesse, jeder führt einen Uvicorn-Worker aus, in diesem Fall 4 Worker. - -* `--worker-class`: Die Gunicorn-kompatible Workerklasse zur Verwendung in den Workerprozessen. - * Hier übergeben wir die Klasse, die Gunicorn etwa so importiert und verwendet: - - ```Python - import uvicorn.workers.UvicornWorker - ``` - -* `--bind`: Das teilt Gunicorn die IP und den Port mit, welche abgehört werden sollen, wobei ein Doppelpunkt (`:`) verwendet wird, um die IP und den Port zu trennen. - * Wenn Sie Uvicorn direkt ausführen würden, würden Sie anstelle von `--bind 0.0.0.0:80` (die Gunicorn-Option) stattdessen `--host 0.0.0.0` und `--port 80` verwenden. - -In der Ausgabe können Sie sehen, dass die **PID** (Prozess-ID) jedes Prozesses angezeigt wird (es ist nur eine Zahl). - -Sie können sehen, dass: - -* Der Gunicorn **Prozessmanager** beginnt, mit der PID `19499` (in Ihrem Fall ist es eine andere Nummer). -* Dann beginnt er zu lauschen: `Listening at: http://0.0.0.0:80`. -* Dann erkennt er, dass er die Workerklasse `uvicorn.workers.UvicornWorker` verwenden muss. -* Und dann werden **4 Worker** gestartet, jeder mit seiner eigenen PID: `19511`, `19513`, `19514` und `19515`. - -Gunicorn würde sich bei Bedarf auch um die Verwaltung **beendeter Prozesse** und den **Neustart** von Prozessen kümmern, um die Anzahl der Worker aufrechtzuerhalten. Das hilft also teilweise beim **Neustarts**-Konzept aus der obigen Liste. - -Dennoch möchten Sie wahrscheinlich auch etwas außerhalb haben, um sicherzustellen, dass Gunicorn bei Bedarf **neu gestartet wird**, und er auch **beim Hochfahren ausgeführt wird**, usw. - -## Uvicorn mit Workern - -Uvicorn bietet ebenfalls die Möglichkeit, mehrere **Workerprozesse** zu starten und auszuführen. - -Dennoch sind die Fähigkeiten von Uvicorn zur Abwicklung von Workerprozessen derzeit eingeschränkter als die von Gunicorn. Wenn Sie also einen Prozessmanager auf dieser Ebene (auf der Python-Ebene) haben möchten, ist es vermutlich besser, es mit Gunicorn als Prozessmanager zu versuchen. - -Wie auch immer, Sie würden es so ausführen: +Wenn Sie den `uvicorn`-Befehl direkt verwenden möchten:
@@ -149,15 +105,17 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
+//// + Die einzige neue Option hier ist `--workers`, die Uvicorn anweist, 4 Workerprozesse zu starten. Sie können auch sehen, dass die **PID** jedes Prozesses angezeigt wird, `27365` für den übergeordneten Prozess (dies ist der **Prozessmanager**) und eine für jeden Workerprozess: `27368`, `27369`, `27370` und `27367`. -## Deployment-Konzepte +## Deployment-Konzepte { #deployment-concepts } -Hier haben Sie gesehen, wie Sie mit **Gunicorn** (oder Uvicorn) **Uvicorn-Workerprozesse** verwalten, um die Ausführung der Anwendung zu **parallelisieren**, **mehrere Kerne** der CPU zu nutzen und in der Lage zu sein, **mehr Requests** zu bedienen. +Hier haben Sie gesehen, wie Sie mehrere **Worker** verwenden, um die Ausführung der Anwendung zu **parallelisieren**, **mehrere Kerne** der CPU zu nutzen und in der Lage zu sein, **mehr Requests** zu bearbeiten. -In der Liste der Deployment-Konzepte von oben würde die Verwendung von Workern hauptsächlich beim **Replikation**-Teil und ein wenig bei **Neustarts** helfen, aber Sie müssen sich trotzdem um die anderen kümmern: +In der Liste der Deployment-Konzepte von oben würde die Verwendung von Workern hauptsächlich bei der **Replikation** und ein wenig bei **Neustarts** helfen, aber Sie müssen sich trotzdem um die anderen kümmern: * **Sicherheit – HTTPS** * **Beim Hochfahren ausführen** @@ -166,18 +124,16 @@ In der Liste der Deployment-Konzepte von oben würde die Verwendung von Workern * **Arbeitsspeicher** * **Schritte vor dem Start** -## Container und Docker +## Container und Docker { #containers-and-docker } Im nächsten Kapitel über [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank} werde ich einige Strategien erläutern, die Sie für den Umgang mit den anderen **Deployment-Konzepten** verwenden können. -Ich zeige Ihnen auch das **offizielle Docker-Image**, welches **Gunicorn mit Uvicorn-Workern** und einige Standardkonfigurationen enthält, die für einfache Fälle nützlich sein können. +Ich zeige Ihnen, wie Sie **Ihr eigenes Image von Grund auf erstellen**, um einen einzelnen Uvicorn-Prozess auszuführen. Es ist ein einfacher Vorgang und wahrscheinlich das, was Sie tun möchten, wenn Sie ein verteiltes Containerverwaltungssystem wie **Kubernetes** verwenden. -Dort zeige ich Ihnen auch, wie Sie **Ihr eigenes Image von Grund auf erstellen**, um einen einzelnen Uvicorn-Prozess (ohne Gunicorn) auszuführen. Es ist ein einfacher Vorgang und wahrscheinlich das, was Sie tun möchten, wenn Sie ein verteiltes Containerverwaltungssystem wie **Kubernetes** verwenden. +## Zusammenfassung { #recap } -## Zusammenfassung +Sie können mehrere Workerprozesse mit der `--workers`-CLI-Option über die `fastapi`- oder `uvicorn`-Befehle nutzen, um **Multikern-CPUs** auszunutzen und **mehrere Prozesse parallel** auszuführen. -Sie können **Gunicorn** (oder auch Uvicorn) als Prozessmanager mit Uvicorn-Workern verwenden, um **Multikern-CPUs** zu nutzen und **mehrere Prozesse parallel** auszuführen. - -Sie können diese Tools und Ideen nutzen, wenn Sie **Ihr eigenes Deployment-System** einrichten und sich dabei selbst um die anderen Deployment-Konzepte kümmern. +Sie könnten diese Tools und Ideen nutzen, wenn Sie **Ihr eigenes Deployment-System** einrichten und sich dabei selbst um die anderen Deployment-Konzepte kümmern. Schauen Sie sich das nächste Kapitel an, um mehr über **FastAPI** mit Containern (z. B. Docker und Kubernetes) zu erfahren. Sie werden sehen, dass diese Tools auch einfache Möglichkeiten bieten, die anderen **Deployment-Konzepte** zu lösen. ✨ diff --git a/docs/de/docs/deployment/versions.md b/docs/de/docs/deployment/versions.md index 5b8c69754..d7ecb762e 100644 --- a/docs/de/docs/deployment/versions.md +++ b/docs/de/docs/deployment/versions.md @@ -1,4 +1,4 @@ -# Über FastAPI-Versionen +# Über FastAPI-Versionen { #about-fastapi-versions } **FastAPI** wird bereits in vielen Anwendungen und Systemen produktiv eingesetzt. Und die Testabdeckung wird bei 100 % gehalten. Aber seine Entwicklung geht immer noch schnell voran. @@ -8,35 +8,35 @@ Aus diesem Grund sind die aktuellen Versionen immer noch `0.x.x`, was darauf hin Sie können jetzt Produktionsanwendungen mit **FastAPI** erstellen (und das tun Sie wahrscheinlich schon seit einiger Zeit), Sie müssen nur sicherstellen, dass Sie eine Version verwenden, die korrekt mit dem Rest Ihres Codes funktioniert. -## `fastapi`-Version pinnen +## Ihre `fastapi`-Version pinnen { #pin-your-fastapi-version } Als Erstes sollten Sie die Version von **FastAPI**, die Sie verwenden, an die höchste Version „pinnen“, von der Sie wissen, dass sie für Ihre Anwendung korrekt funktioniert. -Angenommen, Sie verwenden in Ihrer Anwendung die Version `0.45.0`. +Angenommen, Sie verwenden in Ihrer App die Version `0.112.0`. Wenn Sie eine `requirements.txt`-Datei verwenden, können Sie die Version wie folgt angeben: ```txt -fastapi==0.45.0 +fastapi[standard]==0.112.0 ``` -Das würde bedeuten, dass Sie genau die Version `0.45.0` verwenden. +Das würde bedeuten, dass Sie genau die Version `0.112.0` verwenden. Oder Sie können sie auch anpinnen mit: ```txt -fastapi>=0.45.0,<0.46.0 +fastapi[standard]>=0.112.0,<0.113.0 ``` -Das würde bedeuten, dass Sie eine Version `0.45.0` oder höher verwenden würden, aber kleiner als `0.46.0`, beispielsweise würde eine Version `0.45.2` immer noch akzeptiert. +Das würde bedeuten, dass Sie eine Version `0.112.0` oder höher verwenden würden, aber kleiner als `0.113.0`, beispielsweise würde eine Version `0.112.2` immer noch akzeptiert. -Wenn Sie zum Verwalten Ihrer Installationen andere Tools wie Poetry, Pipenv oder andere verwenden, sie verfügen alle über eine Möglichkeit, bestimmte Versionen für Ihre Packages zu definieren. +Wenn Sie zum Verwalten Ihrer Installationen andere Tools wie `uv`, Poetry, Pipenv oder andere verwenden, sie verfügen alle über eine Möglichkeit, bestimmte Versionen für Ihre Packages zu definieren. -## Verfügbare Versionen +## Verfügbare Versionen { #available-versions } -Die verfügbaren Versionen können Sie in den [Release Notes](../release-notes.md){.internal-link target=_blank} einsehen (z. B. um zu überprüfen, welches die neueste Version ist). +Die verfügbaren Versionen können Sie in den [Versionshinweisen](../release-notes.md){.internal-link target=_blank} einsehen (z. B. um zu überprüfen, welches die neueste Version ist). -## Über Versionen +## Über Versionen { #about-versions } Gemäß den Konventionen zur semantischen Versionierung könnte jede Version unter `1.0.0` potenziell nicht abwärtskompatible Änderungen hinzufügen. @@ -62,9 +62,9 @@ Nicht abwärtskompatible Änderungen und neue Funktionen werden in „MINOR“-V /// -## Upgrade der FastAPI-Versionen +## Upgrade der FastAPI-Versionen { #upgrading-the-fastapi-versions } -Sie sollten Tests für Ihre Anwendung hinzufügen. +Sie sollten Tests für Ihre App hinzufügen. Mit **FastAPI** ist das sehr einfach (dank Starlette), schauen Sie sich die Dokumentation an: [Testen](../tutorial/testing.md){.internal-link target=_blank} @@ -72,7 +72,7 @@ Nachdem Sie Tests erstellt haben, können Sie die **FastAPI**-Version auf eine n Wenn alles funktioniert oder nachdem Sie die erforderlichen Änderungen vorgenommen haben und alle Ihre Tests bestehen, können Sie Ihr `fastapi` an die neue aktuelle Version pinnen. -## Über Starlette +## Über Starlette { #about-starlette } Sie sollten die Version von `starlette` nicht pinnen. @@ -80,13 +80,14 @@ Verschiedene Versionen von **FastAPI** verwenden eine bestimmte neuere Version v Sie können **FastAPI** also einfach die korrekte Starlette-Version verwenden lassen. -## Über Pydantic +## Über Pydantic { #about-pydantic } Pydantic integriert die Tests für **FastAPI** in seine eigenen Tests, sodass neue Versionen von Pydantic (über `1.0.0`) immer mit FastAPI kompatibel sind. -Sie können Pydantic an jede für Sie geeignete Version über `1.0.0` und unter `2.0.0` anpinnen. +Sie können Pydantic an jede für Sie geeignete Version über `1.0.0` anpinnen. Zum Beispiel: + ```txt -pydantic>=1.2.0,<2.0.0 +pydantic>=2.7.0,<3.0.0 ``` diff --git a/docs/de/docs/environment-variables.md b/docs/de/docs/environment-variables.md new file mode 100644 index 000000000..9d8c9f75c --- /dev/null +++ b/docs/de/docs/environment-variables.md @@ -0,0 +1,298 @@ +# Umgebungsvariablen { #environment-variables } + +/// tip | Tipp + +Wenn Sie bereits wissen, was „Umgebungsvariablen“ sind und wie man sie verwendet, können Sie dies überspringen. + +/// + +Eine Umgebungsvariable (auch bekannt als „**env var**“) ist eine Variable, die **außerhalb** des Python-Codes im **Betriebssystem** lebt und von Ihrem Python-Code (oder auch von anderen Programmen) gelesen werden kann. + +Umgebungsvariablen können nützlich sein, um **Einstellungen** der Anwendung zu handhaben, als Teil der **Installation** von Python usw. + +## Umgebungsvariablen erstellen und verwenden { #create-and-use-env-vars } + +Sie können Umgebungsvariablen in der **Shell (Terminal)** erstellen und verwenden, ohne Python zu benötigen: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Sie können eine Umgebungsvariable MY_NAME erstellen mit +$ export MY_NAME="Wade Wilson" + +// Dann können Sie sie mit anderen Programmen verwenden, etwa +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Erstellen Sie eine Umgebungsvariable MY_NAME +$ $Env:MY_NAME = "Wade Wilson" + +// Verwenden Sie sie mit anderen Programmen, etwa +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## Umgebungsvariablen in Python lesen { #read-env-vars-in-python } + +Sie können auch Umgebungsvariablen **außerhalb** von Python erstellen, im Terminal (oder mit jeder anderen Methode) und sie dann **in Python** lesen. + +Zum Beispiel könnten Sie eine Datei `main.py` haben mit: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip | Tipp + +Das zweite Argument von `os.getenv()` ist der Defaultwert, der zurückgegeben wird. + +Wenn er nicht angegeben wird, ist er standardmäßig `None`. Hier geben wir `"World"` als den zu verwendenden Defaultwert an. + +/// + +Dann könnten Sie das Python-Programm aufrufen: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Hier setzen wir die Umgebungsvariable noch nicht +$ python main.py + +// Da wir die Umgebungsvariable nicht gesetzt haben, erhalten wir den Defaultwert + +Hello World from Python + +// Aber wenn wir zuerst eine Umgebungsvariable erstellen +$ export MY_NAME="Wade Wilson" + +// Und dann das Programm erneut aufrufen +$ python main.py + +// Jetzt kann es die Umgebungsvariable lesen + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Hier setzen wir die Umgebungsvariable noch nicht +$ python main.py + +// Da wir die Umgebungsvariable nicht gesetzt haben, erhalten wir den Defaultwert + +Hello World from Python + +// Aber wenn wir zuerst eine Umgebungsvariable erstellen +$ $Env:MY_NAME = "Wade Wilson" + +// Und dann das Programm erneut aufrufen +$ python main.py + +// Jetzt kann es die Umgebungsvariable lesen + +Hello Wade Wilson from Python +``` + +
+ +//// + +Da Umgebungsvariablen außerhalb des Codes gesetzt werden können, aber vom Code gelesen werden können und nicht mit den restlichen Dateien gespeichert (in `git` committet) werden müssen, werden sie häufig für Konfigurationen oder **Einstellungen** verwendet. + +Sie können auch eine Umgebungsvariable nur für einen **spezifischen Programmaufruf** erstellen, die nur für dieses Programm und nur für dessen Dauer verfügbar ist. + +Um dies zu tun, erstellen Sie sie direkt vor dem Programmaufruf, in derselben Zeile: + +
+ +```console +// Erstellen Sie eine Umgebungsvariable MY_NAME in der Zeile für diesen Programmaufruf +$ MY_NAME="Wade Wilson" python main.py + +// Jetzt kann es die Umgebungsvariable lesen + +Hello Wade Wilson from Python + +// Die Umgebungsvariable existiert danach nicht mehr +$ python main.py + +Hello World from Python +``` + +
+ +/// tip | Tipp + +Sie können mehr darüber lesen auf The Twelve-Factor App: Config. + +/// + +## Typen und Validierung { #types-and-validation } + +Diese Umgebungsvariablen können nur **Textstrings** handhaben, da sie extern zu Python sind und kompatibel mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen, wie Linux, Windows, macOS) sein müssen. + +Das bedeutet, dass **jeder Wert**, der in Python von einer Umgebungsvariable gelesen wird, **ein `str` sein wird**, und jede Konvertierung in einen anderen Typ oder jede Validierung muss im Code vorgenommen werden. + +Sie werden mehr darüber lernen, wie man Umgebungsvariablen zur Handhabung von **Anwendungseinstellungen** verwendet, im [Handbuch für fortgeschrittene Benutzer – Einstellungen und Umgebungsvariablen](./advanced/settings.md){.internal-link target=_blank}. + +## `PATH`-Umgebungsvariable { #path-environment-variable } + +Es gibt eine **spezielle** Umgebungsvariable namens **`PATH`**, die von den Betriebssystemen (Linux, macOS, Windows) verwendet wird, um Programme zu finden, die ausgeführt werden sollen. + +Der Wert der Variable `PATH` ist ein langer String, der aus Verzeichnissen besteht, die auf Linux und macOS durch einen Doppelpunkt `:` und auf Windows durch ein Semikolon `;` getrennt sind. + +Zum Beispiel könnte die `PATH`-Umgebungsvariable so aussehen: + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Das bedeutet, dass das System nach Programmen in den Verzeichnissen suchen sollte: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +Das bedeutet, dass das System nach Programmen in den Verzeichnissen suchen sollte: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +Wenn Sie einen **Befehl** im Terminal eingeben, **sucht** das Betriebssystem nach dem Programm in **jedem dieser Verzeichnisse**, die in der `PATH`-Umgebungsvariablen aufgeführt sind. + +Zum Beispiel, wenn Sie `python` im Terminal eingeben, sucht das Betriebssystem nach einem Programm namens `python` im **ersten Verzeichnis** in dieser Liste. + +Wenn es es findet, wird es **benutzt**. Andernfalls sucht es weiter in den **anderen Verzeichnissen**. + +### Python installieren und den `PATH` aktualisieren { #installing-python-and-updating-the-path } + +Wenn Sie Python installieren, könnten Sie gefragt werden, ob Sie die `PATH`-Umgebungsvariable aktualisieren möchten. + +//// tab | Linux, macOS + +Angenommen, Sie installieren Python und es landet in einem Verzeichnis `/opt/custompython/bin`. + +Wenn Sie erlauben, die `PATH`-Umgebungsvariable zu aktualisieren, fügt der Installer `/opt/custompython/bin` zur `PATH`-Umgebungsvariable hinzu. + +Das könnte so aussehen: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +Auf diese Weise, wenn Sie `python` im Terminal eingeben, findet das System das Python-Programm in `/opt/custompython/bin` (das letzte Verzeichnis) und verwendet dieses. + +//// + +//// tab | Windows + +Angenommen, Sie installieren Python und es landet in einem Verzeichnis `C:\opt\custompython\bin`. + +Wenn Sie erlauben, die `PATH`-Umgebungsvariable zu aktualisieren, fügt der Installer `C:\opt\custompython\bin` zur `PATH`-Umgebungsvariable hinzu. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +Auf diese Weise, wenn Sie `python` im Terminal eingeben, findet das System das Python-Programm in `C:\opt\custompython\bin` (das letzte Verzeichnis) und verwendet dieses. + +//// + +Also, wenn Sie tippen: + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +Das System wird das `python` Programm in `/opt/custompython/bin` **finden** und es ausführen. + +Es wäre ungefähr gleichbedeutend mit der Eingabe von: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +Das System wird das `python` Programm in `C:\opt\custompython\bin\python` **finden** und es ausführen. + +Es wäre ungefähr gleichbedeutend mit der Eingabe von: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +Diese Informationen werden nützlich sein, wenn Sie über [Virtuelle Umgebungen](virtual-environments.md){.internal-link target=_blank} lernen. + +## Fazit { #conclusion } + +Mit diesem Wissen sollten Sie ein grundlegendes Verständnis davon haben, was **Umgebungsvariablen** sind und wie man sie in Python verwendet. + +Sie können auch mehr darüber in der Wikipedia zu Umgebungsvariablen lesen. + +In vielen Fällen ist es nicht sehr offensichtlich, wie Umgebungsvariablen nützlich und sofort anwendbar sein könnten. Aber sie tauchen immer wieder in vielen verschiedenen Szenarien auf, wenn Sie entwickeln, deshalb ist es gut, darüber Bescheid zu wissen. + +Zum Beispiel werden Sie diese Informationen im nächsten Abschnitt über [Virtuelle Umgebungen](virtual-environments.md) benötigen. diff --git a/docs/de/docs/fastapi-cli.md b/docs/de/docs/fastapi-cli.md new file mode 100644 index 000000000..d41ed598e --- /dev/null +++ b/docs/de/docs/fastapi-cli.md @@ -0,0 +1,75 @@ +# FastAPI CLI { #fastapi-cli } + +**FastAPI CLI** ist ein Kommandozeilenprogramm, mit dem Sie Ihre FastAPI-App bereitstellen, Ihr FastAPI-Projekt verwalten und mehr. + +Wenn Sie FastAPI installieren (z. B. mit `pip install "fastapi[standard]"`), wird ein Package namens `fastapi-cli` mitgeliefert, das den Befehl `fastapi` im Terminal bereitstellt. + +Um Ihre FastAPI-App für die Entwicklung auszuführen, können Sie den Befehl `fastapi dev` verwenden: + +
+ +```console +$ fastapi dev main.py + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +Das Kommandozeilenprogramm namens `fastapi` ist das **FastAPI CLI**. + +FastAPI CLI nimmt den Pfad zu Ihrem Python-Programm (z. B. `main.py`), erkennt automatisch die `FastAPI`-Instanz (häufig `app` genannt), bestimmt den korrekten Importprozess und stellt sie dann bereit. + +Für die Produktion würden Sie stattdessen `fastapi run` verwenden. 🚀 + +Intern verwendet das **FastAPI CLI** Uvicorn, einen leistungsstarken, produktionsreifen, ASGI-Server. 😎 + +## `fastapi dev` { #fastapi-dev } + +Das Ausführen von `fastapi dev` startet den Entwicklermodus. + +Standardmäßig ist **Autoreload** aktiviert, das den Server automatisch neu lädt, wenn Sie Änderungen an Ihrem Code vornehmen. Dies ist ressourcenintensiv und könnte weniger stabil sein als wenn es deaktiviert ist. Sie sollten es nur für die Entwicklung verwenden. Es horcht auch auf der IP-Adresse `127.0.0.1`, die die IP für Ihre Maschine ist, um nur mit sich selbst zu kommunizieren (`localhost`). + +## `fastapi run` { #fastapi-run } + +Das Ausführen von `fastapi run` startet FastAPI standardmäßig im Produktionsmodus. + +Standardmäßig ist **Autoreload** deaktiviert. Es horcht auch auf der IP-Adresse `0.0.0.0`, was alle verfügbaren IP-Adressen bedeutet, so wird es öffentlich zugänglich für jeden, der mit der Maschine kommunizieren kann. So würden Sie es normalerweise in der Produktion ausführen, beispielsweise in einem Container. + +In den meisten Fällen würden (und sollten) Sie einen „Terminierungsproxy“ haben, der HTTPS für Sie verwaltet. Dies hängt davon ab, wie Sie Ihre Anwendung bereitstellen. Ihr Anbieter könnte dies für Sie erledigen, oder Sie müssen es selbst einrichten. + +/// tip | Tipp + +Sie können mehr darüber in der [Deployment-Dokumentation](deployment/index.md){.internal-link target=_blank} erfahren. + +/// diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md index 8fdf42622..c52f6733e 100644 --- a/docs/de/docs/features.md +++ b/docs/de/docs/features.md @@ -1,21 +1,21 @@ -# Merkmale +# Merkmale { #features } -## FastAPI Merkmale +## FastAPI Merkmale { #fastapi-features } **FastAPI** ermöglicht Ihnen Folgendes: -### Basiert auf offenen Standards +### Basiert auf offenen Standards { #based-on-open-standards } -* OpenAPI für die Erstellung von APIs, inklusive Deklarationen von Pfad-Operationen, Parametern, Requestbodys, Sicherheit, usw. +* OpenAPI für die Erstellung von APIs, inklusive Deklarationen von Pfad-Operationen, Parametern, Requestbodys, Sicherheit, usw. * Automatische Dokumentation der Datenmodelle mit JSON Schema (da OpenAPI selbst auf JSON Schema basiert). * Um diese Standards herum entworfen, nach sorgfältigem Studium. Statt einer nachträglichen Schicht darüber. * Dies ermöglicht auch automatische **Client-Code-Generierung** in vielen Sprachen. -### Automatische Dokumentation +### Automatische Dokumentation { #automatic-docs } Interaktive API-Dokumentation und erkundbare Web-Benutzeroberflächen. Da das Framework auf OpenAPI basiert, gibt es mehrere Optionen, zwei sind standardmäßig vorhanden. -* Swagger UI, bietet interaktive Erkundung, testen und rufen Sie ihre API direkt im Webbrowser auf. +* Swagger UI, bietet interaktive Erkundung, testen und rufen Sie Ihre API direkt im Webbrowser auf. ![Swagger UI Interaktion](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) @@ -23,22 +23,21 @@ Interaktive API-Dokumentation und erkundbare Web-Benutzeroberflächen. Da das Fr ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### Nur modernes Python +### Nur modernes Python { #just-modern-python } -Alles basiert auf **Python 3.8 Typ**-Deklarationen (dank Pydantic). Es muss keine neue Syntax gelernt werden, nur standardisiertes modernes Python. +Alles basiert auf Standard-**Python-Typ**deklarationen (dank Pydantic). Es muss keine neue Syntax gelernt werden, nur standardisiertes modernes Python. Wenn Sie eine zweiminütige Auffrischung benötigen, wie man Python-Typen verwendet (auch wenn Sie FastAPI nicht benutzen), schauen Sie sich das kurze Tutorial an: [Einführung in Python-Typen](python-types.md){.internal-link target=_blank}. Sie schreiben Standard-Python mit Typen: ```Python -from typing import List, Dict from datetime import date from pydantic import BaseModel -# Deklarieren Sie eine Variable als ein `str` -# und bekommen Sie Editor-Unterstütung innerhalb der Funktion +# Deklarieren Sie eine Variable als ein str +# und bekommen Sie Editor-Unterstützung innerhalb der Funktion def main(user_id: str): return user_id @@ -64,25 +63,25 @@ second_user_data = { my_second_user: User = User(**second_user_data) ``` -/// info +/// info | Info `**second_user_data` bedeutet: -Nimm die Schlüssel-Wert-Paare des `second_user_data` Dicts und übergib sie direkt als Schlüsselwort-Argumente. Äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")`. +Nimm die Schlüssel-Wert-Paare des `second_user_data` Dicts und übergebe sie direkt als Schlüsselwort-Argumente. Äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")` /// -### Editor Unterstützung +### Editor Unterstützung { #editor-support } Das ganze Framework wurde so entworfen, dass es einfach und intuitiv zu benutzen ist; alle Entscheidungen wurden auf mehreren Editoren getestet, sogar vor der Implementierung, um die bestmögliche Entwicklererfahrung zu gewährleisten. -In der letzten Python-Entwickler-Umfrage wurde klar, dass die meist genutzte Funktion die „Autovervollständigung“ ist. +In den Python-Entwickler-Umfragen wird klar, dass die meist genutzte Funktion die „Autovervollständigung“ ist. Das gesamte **FastAPI**-Framework ist darauf ausgelegt, das zu erfüllen. Autovervollständigung funktioniert überall. Sie werden selten noch mal in der Dokumentation nachschauen müssen. -So kann ihr Editor Sie unterstützen: +So kann Ihr Editor Sie unterstützen: * in Visual Studio Code: @@ -92,23 +91,23 @@ So kann ihr Editor Sie unterstützen: ![Editor Unterstützung](https://fastapi.tiangolo.com/img/pycharm-completion.png) -Sie bekommen sogar Autovervollständigung an Stellen, an denen Sie dies vorher nicht für möglich gehalten hätten. Zum Beispiel der `price` Schlüssel in einem JSON Datensatz (dieser könnte auch verschachtelt sein), der aus einer Anfrage kommt. +Sie bekommen sogar Autovervollständigung an Stellen, an denen Sie dies vorher nicht für möglich gehalten hätten. Zum Beispiel der `price` Schlüssel in einem JSON Datensatz (dieser könnte auch verschachtelt sein), der aus einem Request kommt. Nie wieder falsche Schlüsselnamen tippen, Hin und Herhüpfen zwischen der Dokumentation, Hoch- und Runterscrollen, um herauszufinden, ob es `username` oder `user_name` war. -### Kompakt +### Kompakt { #short } Es gibt für alles sensible **Defaultwerte**, mit optionaler Konfiguration überall. Alle Parameter können feinjustiert werden, damit sie tun, was Sie benötigen, und die API definieren, die Sie brauchen. Aber standardmäßig **„funktioniert einfach alles“**. -### Validierung +### Validierung { #validation } * Validierung für die meisten (oder alle?) Python-**Datentypen**, hierzu gehören: * JSON Objekte (`dict`). * JSON Listen (`list`), die den Typ ihrer Elemente definieren. * Strings (`str`) mit definierter minimaler und maximaler Länge. - * Zahlen (`int`, `float`) mit Mindest- und Maximal-Werten, usw. + * Zahlen (`int`, `float`) mit Mindest- und Maximalwerten, usw. * Validierung für mehr exotische Typen, wie: * URL. @@ -118,47 +117,47 @@ Aber standardmäßig **„funktioniert einfach alles“**. Die gesamte Validierung übernimmt das gut etablierte und robuste **Pydantic**. -### Sicherheit und Authentifizierung +### Sicherheit und Authentifizierung { #security-and-authentication } -Sicherheit und Authentifizierung ist integriert. Ohne Kompromisse bei Datenbanken oder Datenmodellen. +Sicherheit und Authentifizierung sind integriert. Ohne Kompromisse bei Datenbanken oder Datenmodellen. Alle in OpenAPI definierten Sicherheitsschemas, inklusive: -* HTTP Basic Authentifizierung. +* HTTP Basic. * **OAuth2** (auch mit **JWT Tokens**). Siehe dazu das Tutorial zu [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. * API Schlüssel in: - * Header-Feldern. - * Anfrageparametern. + * Headern. + * Query-Parametern. * Cookies, usw. Zusätzlich alle Sicherheitsfunktionen von Starlette (inklusive **Session Cookies**). -Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in ihre Systeme, Datenspeicher, relationalen und nicht-relationalen Datenbanken, usw., integriert werden können. +Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in Ihre Systeme, Datenspeicher, relationale und nicht-relationale Datenbanken, usw., integriert werden können. -### Einbringen von Abhängigkeiten (Dependency Injection) +### Dependency Injection { #dependency-injection } -FastAPI enthält ein extrem einfach zu verwendendes, aber extrem mächtiges Dependency Injection System. +FastAPI enthält ein extrem einfach zu verwendendes, aber extrem mächtiges Dependency Injection System. * Selbst Abhängigkeiten können Abhängigkeiten haben, woraus eine Hierarchie oder ein **„Graph“ von Abhängigkeiten** entsteht. * Alles **automatisch gehandhabt** durch das Framework. -* Alle Abhängigkeiten können Daten von Anfragen anfordern und das Verhalten von **Pfadoperationen** und der automatisierten Dokumentation **modifizieren**. +* Alle Abhängigkeiten können Daten von Requests anfordern und das Verhalten von **Pfadoperationen** und der automatisierten Dokumentation **modifizieren**. * **Automatische Validierung** selbst für solche Parameter von *Pfadoperationen*, welche in Abhängigkeiten definiert sind. * Unterstützung für komplexe Authentifizierungssysteme, **Datenbankverbindungen**, usw. * **Keine Kompromisse** bei Datenbanken, Frontends, usw., sondern einfache Integration mit allen. -### Unbegrenzte Erweiterungen +### Unbegrenzte Erweiterungen { #unlimited-plug-ins } Oder mit anderen Worten, sie werden nicht benötigt. Importieren und nutzen Sie den Code, den Sie brauchen. Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abhängigkeiten), dass Sie eine Erweiterung für Ihre Anwendung mit nur zwei Zeilen Code erstellen können. Hierbei nutzen Sie die gleiche Struktur und Syntax, wie bei *Pfadoperationen*. -### Getestet +### Getestet { #tested } * 100 % Testabdeckung. -* 100 % Typen annotiert. +* 100 % Typen annotiert. * Verwendet in Produktionsanwendungen. -## Starlette's Merkmale +## Starlette Merkmale { #starlette-features } **FastAPI** ist vollkommen kompatibel (und basiert auf) Starlette. Das bedeutet, wenn Sie eigenen Starlette Quellcode haben, funktioniert der. @@ -168,31 +167,31 @@ Mit **FastAPI** bekommen Sie alles von **Starlette** (da FastAPI nur Starlette a * Schwer beeindruckende Performanz. Es ist eines der schnellsten Python-Frameworks, auf Augenhöhe mit **NodeJS** und **Go**. * **WebSocket**-Unterstützung. -* Hintergrundaufgaben im selben Prozess. -* Ereignisse beim Starten und Herunterfahren. -* Testclient baut auf HTTPX auf. +* Hintergrundtasks im selben Prozess. +* Startup- und Shutdown-Events. +* Testclient basierend auf HTTPX. * **CORS**, GZip, statische Dateien, Responses streamen. * **Sitzungs- und Cookie**-Unterstützung. * 100 % Testabdeckung. * 100 % Typen annotierte Codebasis. -## Pydantic's Merkmale +## Pydantic Merkmale { #pydantic-features } **FastAPI** ist vollkommen kompatibel (und basiert auf) Pydantic. Das bedeutet, wenn Sie eigenen Pydantic Quellcode haben, funktioniert der. -Inklusive externer Bibliotheken, die auf Pydantic basieren, wie ORMs, ODMs für Datenbanken. +Inklusive externer Bibliotheken, die auf Pydantic basieren, wie ORMs, ODMs für Datenbanken. -Daher können Sie in vielen Fällen das Objekt einer Anfrage **direkt zur Datenbank** schicken, weil alles automatisch validiert wird. +Daher können Sie in vielen Fällen das Objekt eines Requests **direkt zur Datenbank** schicken, weil alles automatisch validiert wird. -Das gleiche gilt auch für die andere Richtung: Sie können in vielen Fällen das Objekt aus der Datenbank **direkt zum Client** schicken. +Das gleiche gilt auch für die andere Richtung: Sie können in vielen Fällen das Objekt aus der Datenbank **direkt zum Client** senden. Mit **FastAPI** bekommen Sie alle Funktionen von **Pydantic** (da FastAPI für die gesamte Datenverarbeitung Pydantic nutzt): * **Kein Kopfzerbrechen**: * Keine neue Schemadefinition-Mikrosprache zu lernen. * Wenn Sie Pythons Typen kennen, wissen Sie, wie man Pydantic verwendet. -* Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/Linter/Gehirn**: - * Weil Pydantics Datenstrukturen einfach nur Instanzen ihrer definierten Klassen sind; Autovervollständigung, Linting, mypy und ihre Intuition sollten alle einwandfrei mit ihren validierten Daten funktionieren. +* Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/Linter/Gehirn**: + * Weil Pydantics Datenstrukturen einfach nur Instanzen ihrer definierten Klassen sind; Autovervollständigung, Linting, mypy und Ihre Intuition sollten alle einwandfrei mit Ihren validierten Daten funktionieren. * Validierung von **komplexen Strukturen**: * Benutzung von hierarchischen Pydantic-Modellen, Python-`typing`s `List` und `Dict`, etc. * Die Validierer erlauben es, komplexe Datenschemen klar und einfach zu definieren, überprüft und dokumentiert als JSON Schema. diff --git a/docs/de/docs/help-fastapi.md b/docs/de/docs/help-fastapi.md index f3a2c77b8..6cbafca0b 100644 --- a/docs/de/docs/help-fastapi.md +++ b/docs/de/docs/help-fastapi.md @@ -1,74 +1,75 @@ -# FastAPI helfen – Hilfe erhalten +# FastAPI helfen – Hilfe erhalten { #help-fastapi-get-help } -Gefällt Ihnen **FastAPI**? +Mögen Sie **FastAPI**? Möchten Sie FastAPI, anderen Benutzern und dem Autor helfen? Oder möchten Sie Hilfe zu **FastAPI** erhalten? -Es gibt sehr einfache Möglichkeiten zu helfen (manche erfordern nur ein oder zwei Klicks). +Es gibt sehr einfache Möglichkeiten zu helfen (einige erfordern nur ein oder zwei Klicks). -Und es gibt auch viele Möglichkeiten, Hilfe zu bekommen. +Und es gibt auch mehrere Möglichkeiten, Hilfe zu bekommen. -## Newsletter abonnieren +## Newsletter abonnieren { #subscribe-to-the-newsletter } -Sie können den (unregelmäßig erscheinenden) [**FastAPI and Friends**-Newsletter](newsletter.md){.internal-link target=_blank} abonnieren, um auf dem Laufenden zu bleiben: +Sie können den (unregelmäßigen) [**FastAPI and friends**-Newsletter](newsletter.md){.internal-link target=_blank} abonnieren, um über folgende Themen informiert zu bleiben: -* Neuigkeiten über FastAPI and Friends 🚀 +* Neuigkeiten über FastAPI und Freunde 🚀 * Anleitungen 📝 * Funktionen ✨ * Breaking Changes 🚨 * Tipps und Tricks ✅ -## FastAPI auf X (Twitter) folgen + +## FastAPI auf X (Twitter) folgen { #follow-fastapi-on-x-twitter } Folgen Sie @fastapi auf **X (Twitter)**, um die neuesten Nachrichten über **FastAPI** zu erhalten. 🐦 -## **FastAPI** auf GitHub einen Stern geben +## **FastAPI** auf GitHub einen Stern geben { #star-fastapi-in-github } -Sie können FastAPI auf GitHub „starren“ (durch Klicken auf den Stern-Button oben rechts): https://github.com/fastapi/fastapi. ⭐️ +Sie können FastAPI auf GitHub „starren“ (klicken Sie auf den Stern-Button oben rechts): https://github.com/fastapi/fastapi. ⭐️ Durch das Hinzufügen eines Sterns können andere Benutzer es leichter finden und sehen, dass es für andere bereits nützlich war. -## Das GitHub-Repository auf Releases beobachten +## Das GitHub-Repository auf Releases überwachen { #watch-the-github-repository-for-releases } -Sie können FastAPI in GitHub beobachten (Klicken Sie oben rechts auf den Button „watch“): https://github.com/fastapi/fastapi. 👀 +Sie können FastAPI auf GitHub „beobachten“ (klicken Sie auf den „watch“-Button oben rechts): https://github.com/fastapi/fastapi. 👀 Dort können Sie „Releases only“ auswählen. -Auf diese Weise erhalten Sie Benachrichtigungen (per E-Mail), wenn es einen neuen Release (eine neue Version) von **FastAPI** mit Fehlerbehebungen und neuen Funktionen gibt. +Auf diese Weise erhalten Sie Benachrichtigungen (per E-Mail), wenn es ein neues Release (eine neue Version) von **FastAPI** mit Bugfixes und neuen Funktionen gibt. -## Mit dem Autor vernetzen +## Mit dem Autor vernetzen { #connect-with-the-author } -Sie können sich mit mir (Sebastián Ramírez / `tiangolo`), dem Autor, verbinden. +Sie können sich mit mir (Sebastián Ramírez / `tiangolo`), dem Autor, vernetzen. -Insbesondere: +Sie können: -* Folgen Sie mir auf **GitHub**. - * Finden Sie andere Open-Source-Projekte, die ich erstellt habe und die Ihnen helfen könnten. - * Folgen Sie mir, um mitzubekommen, wenn ich ein neues Open-Source-Projekt erstelle. -* Folgen Sie mir auf **X (Twitter)** oder Mastodon. - * Berichten Sie mir, wie Sie FastAPI verwenden (das höre ich gerne). - * Bekommen Sie mit, wenn ich Ankündigungen mache oder neue Tools veröffentliche. +* Mir auf **GitHub** folgen. + * Andere Open-Source-Projekte sehen, die ich erstellt habe und die Ihnen helfen könnten. + * Mir folgen, um zu sehen, wenn ich ein neues Open-Source-Projekt erstelle. +* Mir auf **X (Twitter)** folgen oder Mastodon. + * Mir mitteilen, wie Sie FastAPI verwenden (ich höre das gerne). + * Mitbekommen, wenn ich Ankündigungen mache oder neue Tools veröffentliche. * Sie können auch @fastapi auf X (Twitter) folgen (ein separates Konto). -* Folgen Sie mir auf **LinkedIn**. - * Bekommen Sie mit, wenn ich Ankündigungen mache oder neue Tools veröffentliche (obwohl ich X (Twitter) häufiger verwende 🤷‍♂). -* Lesen Sie, was ich schreibe (oder folgen Sie mir) auf **Dev.to** oder **Medium**. - * Lesen Sie andere Ideen, Artikel, und erfahren Sie mehr über die von mir erstellten Tools. - * Folgen Sie mir, um zu lesen, wenn ich etwas Neues veröffentliche. +* Mir auf **LinkedIn** folgen. + * Mitbekommen, wenn ich Ankündigungen mache oder neue Tools veröffentliche (obwohl ich X (Twitter) häufiger verwende 🤷‍♂). +* Lesen, was ich schreibe (oder mir folgen) auf **Dev.to** oder **Medium**. + * Andere Ideen, Artikel lesen und mehr über die von mir erstellten Tools erfahren. + * Mir folgen, um zu lesen, wenn ich etwas Neues veröffentliche. -## Über **FastAPI** tweeten +## Über **FastAPI** tweeten { #tweet-about-fastapi } -Tweeten Sie über **FastAPI** und teilen Sie mir und anderen mit, warum es Ihnen gefällt. 🎉 +Tweeten Sie über **FastAPI** und teilen Sie mir und anderen mit, warum es Ihnen gefällt. 🎉 Ich höre gerne, wie **FastAPI** verwendet wird, was Ihnen daran gefallen hat, in welchem Projekt/Unternehmen Sie es verwenden, usw. -## Für FastAPI abstimmen +## Für FastAPI abstimmen { #vote-for-fastapi } -* Stimmen Sie für **FastAPI** auf Slant. +* Stimmen Sie für **FastAPI** auf Slant. * Stimmen Sie für **FastAPI** auf AlternativeTo. -* Berichten Sie auf StackShare, dass Sie **FastAPI** verwenden. +* Sagen Sie auf StackShare, dass Sie **FastAPI** verwenden. -## Anderen bei Fragen auf GitHub helfen +## Anderen bei Fragen auf GitHub helfen { #help-others-with-questions-in-github } Sie können versuchen, anderen bei ihren Fragen zu helfen: @@ -77,19 +78,19 @@ Sie können versuchen, anderen bei ihren Fragen zu helfen: In vielen Fällen kennen Sie möglicherweise bereits die Antwort auf diese Fragen. 🤓 -Wenn Sie vielen Menschen bei ihren Fragen helfen, werden Sie offizieller [FastAPI-Experte](fastapi-people.md#experten){.internal-link target=_blank}. 🎉 +Wenn Sie vielen Menschen bei ihren Fragen helfen, werden Sie offizieller [FastAPI-Experte](fastapi-people.md#fastapi-experts){.internal-link target=_blank}. 🎉 -Denken Sie aber daran, der wichtigste Punkt ist: Versuchen Sie, freundlich zu sein. Die Leute bringen ihre Frustrationen mit und fragen in vielen Fällen nicht auf die beste Art und Weise, aber versuchen Sie dennoch so gut wie möglich, freundlich zu sein. 🤗 +Denken Sie daran, der wichtigste Punkt ist: Versuchen Sie, freundlich zu sein. Die Leute bringen ihre Frustrationen mit und fragen in vielen Fällen nicht auf die beste Art und Weise, aber versuchen Sie dennoch so gut wie möglich, freundlich zu sein. 🤗 -Die **FastAPI**-Community soll freundlich und einladend sein. Und auch kein Mobbing oder respektloses Verhalten gegenüber anderen akzeptieren. Wir müssen uns umeinander kümmern. +Die **FastAPI**-Community soll freundlich und einladend sein. Akzeptieren Sie gleichzeitig kein Mobbing oder respektloses Verhalten gegenüber anderen. Wir müssen uns umeinander kümmern. --- -So helfen Sie anderen bei Fragen (in Diskussionen oder Problemen): +So helfen Sie anderen bei Fragen (in Diskussionen oder Issues): -### Die Frage verstehen +### Die Frage verstehen { #understand-the-question } -* Fragen Sie sich, ob Sie verstehen, was das **Ziel** und der Anwendungsfall der fragenden Person ist. +* Prüfen Sie, ob Sie verstehen können, was der **Zweck** und der Anwendungsfall der fragenden Person ist. * Überprüfen Sie dann, ob die Frage (die überwiegende Mehrheit sind Fragen) **klar** ist. @@ -97,23 +98,23 @@ So helfen Sie anderen bei Fragen (in Diskussionen oder Problemen): * Wenn Sie die Frage nicht verstehen können, fragen Sie nach weiteren **Details**. -### Das Problem reproduzieren +### Das Problem reproduzieren { #reproduce-the-problem } -In den meisten Fällen und bei den meisten Fragen ist etwas mit dem von der Person erstellten **eigenen Quellcode** los. +In den meisten Fällen und bei den meisten Fragen gibt es etwas in Bezug auf den **originalen Code** der Person. In vielen Fällen wird nur ein Fragment des Codes gepostet, aber das reicht nicht aus, um **das Problem zu reproduzieren**. -* Sie können die Person darum bitten, ein minimales, reproduzierbares Beispiel bereitzustellen, welches Sie **kopieren, einfügen** und lokal ausführen können, um den gleichen Fehler oder das gleiche Verhalten zu sehen, das die Person sieht, oder um ihren Anwendungsfall besser zu verstehen. +* Sie können die Person bitten, ein minimales, reproduzierbares Beispiel bereitzustellen, welches Sie **kopieren, einfügen** und lokal ausführen können, um den gleichen Fehler oder das gleiche Verhalten zu sehen, das die Person sieht, oder um ihren Anwendungsfall besser zu verstehen. -* Wenn Sie in Geberlaune sind, können Sie versuchen, selbst ein solches Beispiel zu erstellen, nur basierend auf der Beschreibung des Problems. Denken Sie jedoch daran, dass dies viel Zeit in Anspruch nehmen kann und dass es besser sein kann, zunächst um eine Klärung des Problems zu bitten. +* Wenn Sie in Geberlaune sind, können Sie ein solches Beispiel selbst erstellen, nur basierend auf der Beschreibung des Problems. Denken Sie jedoch daran, dass dies viel Zeit in Anspruch nehmen kann und dass es besser sein kann, zunächst um eine Klärung des Problems zu bitten. -### Lösungen vorschlagen +### Lösungen vorschlagen { #suggest-solutions } * Nachdem Sie die Frage verstanden haben, können Sie eine mögliche **Antwort** geben. * In vielen Fällen ist es besser, das **zugrunde liegende Problem oder den Anwendungsfall** zu verstehen, da es möglicherweise einen besseren Weg zur Lösung gibt als das, was die Person versucht. -### Um Schließung bitten +### Um Schließung bitten { #ask-to-close } Wenn die Person antwortet, besteht eine hohe Chance, dass Sie ihr Problem gelöst haben. Herzlichen Glückwunsch, **Sie sind ein Held**! 🦸 @@ -122,15 +123,15 @@ Wenn die Person antwortet, besteht eine hohe Chance, dass Sie ihr Problem gelös * In GitHub-Diskussionen: den Kommentar als **Antwort** zu markieren. * In GitHub-Issues: Das Issue zu **schließen**. -## Das GitHub-Repository beobachten +## Das GitHub-Repository beobachten { #watch-the-github-repository } -Sie können FastAPI auf GitHub „beobachten“ (Klicken Sie oben rechts auf die Schaltfläche „watch“): https://github.com/fastapi/fastapi. 👀 +Sie können FastAPI auf GitHub „beobachten“ (klicken Sie auf den „watch“-Button oben rechts): https://github.com/fastapi/fastapi. 👀 -Wenn Sie dann „Watching“ statt „Releases only“ auswählen, erhalten Sie Benachrichtigungen, wenn jemand ein neues Issue eröffnet oder eine neue Frage stellt. Sie können auch spezifizieren, dass Sie nur über neue Issues, Diskussionen, PRs, usw. benachrichtigt werden möchten. +Wenn Sie dann „Watching“ statt „Releases only“ auswählen, erhalten Sie Benachrichtigungen, wenn jemand ein neues Issue eröffnet oder eine neue Frage stellt. Sie können auch spezifizieren, dass Sie nur über neue Issues, Diskussionen, PRs usw. benachrichtigt werden möchten. Dann können Sie versuchen, bei der Lösung solcher Fragen zu helfen. -## Fragen stellen +## Fragen stellen { #ask-questions } Sie können im GitHub-Repository eine neue Frage erstellen, zum Beispiel: @@ -139,9 +140,9 @@ Sie können im GitHub-Repository diese Datei bearbeiten. * Stellen Sie sicher, dass Sie Ihren Link am Anfang des entsprechenden Abschnitts einfügen. -* Um zu helfen, [die Dokumentation in Ihre Sprache zu übersetzen](contributing.md#ubersetzungen){.internal-link target=_blank}. +* Um zu helfen, [die Dokumentation in Ihre Sprache zu übersetzen](contributing.md#translations){.internal-link target=_blank}. * Sie können auch dabei helfen, die von anderen erstellten Übersetzungen zu überprüfen (Review). * Um neue Dokumentationsabschnitte vorzuschlagen. -* Um ein bestehendes Problem / einen bestehenden Bug zu beheben. +* Um ein bestehendes Problem/Bug zu beheben. * Stellen Sie sicher, dass Sie Tests hinzufügen. * Um eine neue Funktionalität hinzuzufügen. * Stellen Sie sicher, dass Sie Tests hinzufügen. * Stellen Sie sicher, dass Sie Dokumentation hinzufügen, falls das notwendig ist. -## FastAPI pflegen +## FastAPI pflegen { #help-maintain-fastapi } -Helfen Sie mir, **FastAPI** instand zu halten! 🤓 +Helfen Sie mir, **FastAPI** zu pflegen! 🤓 Es gibt viel zu tun, und das meiste davon können **SIE** tun. Die Hauptaufgaben, die Sie jetzt erledigen können, sind: -* [Helfen Sie anderen bei Fragen auf GitHub](#anderen-bei-fragen-auf-github-helfen){.internal-link target=_blank} (siehe Abschnitt oben). -* [Prüfen Sie Pull Requests](#pull-requests-prufen){.internal-link target=_blank} (siehe Abschnitt oben). +* [Anderen bei Fragen auf GitHub helfen](#help-others-with-questions-in-github){.internal-link target=_blank} (siehe Abschnitt oben). +* [Pull Requests prüfen](#review-pull-requests){.internal-link target=_blank} (siehe Abschnitt oben). -Diese beiden Dinge sind es, die **die meiste Zeit in Anspruch nehmen**. Das ist die Hauptarbeit bei der Wartung von FastAPI. +Diese beiden Aufgaben sind die Dinge, die **am meisten Zeit verbrauchen**. Das ist die Hauptarbeit bei der Wartung von FastAPI. -Wenn Sie mir dabei helfen können, **helfen Sie mir, FastAPI am Laufen zu erhalten** und sorgen dafür, dass es weiterhin **schneller und besser voranschreitet**. 🚀 +Wenn Sie mir dabei helfen können, **helfen Sie mir, FastAPI zu pflegen** und Sie stellen sicher, dass es weiterhin **schneller und besser voranschreitet**. 🚀 -## Beim Chat mitmachen +## Am Chat teilnehmen { #join-the-chat } Treten Sie dem 👥 Discord-Chatserver 👥 bei und treffen Sie sich mit anderen Mitgliedern der FastAPI-Community. /// tip | Tipp -Wenn Sie Fragen haben, stellen Sie sie bei GitHub Diskussionen, es besteht eine viel bessere Chance, dass Sie hier Hilfe von den [FastAPI-Experten](fastapi-people.md#experten){.internal-link target=_blank} erhalten. +Bei Fragen stellen Sie sie in GitHub-Diskussionen, dort besteht eine viel größere Chance, dass Sie Hilfe von den [FastAPI-Experten](fastapi-people.md#fastapi-experts){.internal-link target=_blank} erhalten. Nutzen Sie den Chat nur für andere allgemeine Gespräche. /// -### Den Chat nicht für Fragen verwenden +### Den Chat nicht für Fragen verwenden { #dont-use-the-chat-for-questions } -Bedenken Sie, da Chats mehr „freie Konversation“ ermöglichen, dass es verlockend ist, Fragen zu stellen, die zu allgemein und schwierig zu beantworten sind, sodass Sie möglicherweise keine Antworten erhalten. +Bedenken Sie, dass Sie in Chats, die „freie Konversation“ erlauben, leicht Fragen stellen können, die zu allgemein und schwer zu beantworten sind, sodass Sie möglicherweise keine Antworten erhalten. -Auf GitHub hilft Ihnen die Vorlage dabei, die richtige Frage zu schreiben, sodass Sie leichter eine gute Antwort erhalten oder das Problem sogar selbst lösen können, noch bevor Sie fragen. Und auf GitHub kann ich sicherstellen, dass ich immer alles beantworte, auch wenn es einige Zeit dauert. Ich persönlich kann das mit den Chat-Systemen nicht machen. 😅 +Auf GitHub hilft Ihnen die Vorlage dabei, die richtige Frage zu stellen, sodass Sie leichter eine gute Antwort erhalten können, oder sogar das Problem selbst lösen, bevor Sie überhaupt fragen. Und auf GitHub kann ich sicherstellen, dass ich immer alles beantworte, auch wenn es einige Zeit dauert. Persönlich kann ich das mit den Chat-Systemen nicht machen. 😅 -Unterhaltungen in den Chat-Systemen sind außerdem nicht so leicht durchsuchbar wie auf GitHub, sodass Fragen und Antworten möglicherweise im Gespräch verloren gehen. Und nur die auf GitHub machen einen [FastAPI-Experten](fastapi-people.md#experten){.internal-link target=_blank}, Sie werden also höchstwahrscheinlich mehr Aufmerksamkeit auf GitHub erhalten. +Unterhaltungen in den Chat-Systemen sind auch nicht so leicht durchsuchbar wie auf GitHub, sodass Fragen und Antworten möglicherweise im Gespräch verloren gehen. Und nur die auf GitHub machen einen [FastAPI-Experten](fastapi-people.md#fastapi-experts){.internal-link target=_blank}, Sie werden also höchstwahrscheinlich mehr Aufmerksamkeit auf GitHub erhalten. Auf der anderen Seite gibt es Tausende von Benutzern in den Chat-Systemen, sodass die Wahrscheinlichkeit hoch ist, dass Sie dort fast immer jemanden zum Reden finden. 😄 -## Den Autor sponsern +## Den Autor sponsern { #sponsor-the-author } -Sie können den Autor (mich) auch über GitHub-Sponsoren finanziell unterstützen. - -Dort könnten Sie mir als Dankeschön einen Kaffee spendieren ☕️. 😄 - -Und Sie können auch Silber- oder Gold-Sponsor für FastAPI werden. 🏅🎉 - -## Die Tools sponsern, die FastAPI unterstützen - -Wie Sie in der Dokumentation gesehen haben, steht FastAPI auf den Schultern von Giganten, Starlette und Pydantic. - -Sie können auch sponsern: - -* Samuel Colvin (Pydantic) -* Encode (Starlette, Uvicorn) +Wenn Ihr **Produkt/Firma** auf **FastAPI** angewiesen ist oder in Zusammenhang steht und Sie seine Benutzer erreichen möchten, können Sie den Autor (mich) über GitHub-Sponsoren unterstützen. Je nach Stufe können Sie einige zusätzliche Vorteile erhalten, wie z. B. ein Abzeichen in der Dokumentation. 🎁 --- diff --git a/docs/de/docs/history-design-future.md b/docs/de/docs/history-design-future.md index ee917608e..40a7a8286 100644 --- a/docs/de/docs/history-design-future.md +++ b/docs/de/docs/history-design-future.md @@ -1,12 +1,12 @@ -# Geschichte, Design und Zukunft +# Geschichte, Design und Zukunft { #history-design-and-future } Vor einiger Zeit fragte ein **FastAPI**-Benutzer: -> Was ist die Geschichte dieses Projekts? Es scheint, als wäre es in ein paar Wochen aus dem Nichts zu etwas Großartigem geworden [...] +> Was ist die Geschichte dieses Projekts? Es scheint aus dem Nichts in ein paar Wochen zu etwas Großartigem geworden zu sein [...] Hier ist ein wenig über diese Geschichte. -## Alternativen +## Alternativen { #alternatives } Ich habe seit mehreren Jahren APIs mit komplexen Anforderungen (maschinelles Lernen, verteilte Systeme, asynchrone Jobs, NoSQL-Datenbanken, usw.) erstellt und leitete mehrere Entwicklerteams. @@ -28,7 +28,7 @@ Aber irgendwann gab es keine andere Möglichkeit, als etwas zu schaffen, das all -## Investigation +## Untersuchung { #investigation } Durch die Nutzung all dieser vorherigen Alternativen hatte ich die Möglichkeit, von allen zu lernen, Ideen aufzunehmen und sie auf die beste Weise zu kombinieren, die ich für mich und die Entwicklerteams, mit denen ich zusammengearbeitet habe, finden konnte. @@ -38,13 +38,13 @@ Der beste Ansatz bestand außerdem darin, bereits bestehende Standards zu nutzen Bevor ich also überhaupt angefangen habe, **FastAPI** zu schreiben, habe ich mehrere Monate damit verbracht, die Spezifikationen für OpenAPI, JSON Schema, OAuth2, usw. zu studieren und deren Beziehungen, Überschneidungen und Unterschiede zu verstehen. -## Design +## Design { #design } Dann habe ich einige Zeit damit verbracht, die Entwickler-„API“ zu entwerfen, die ich als Benutzer haben wollte (als Entwickler, welcher FastAPI verwendet). Ich habe mehrere Ideen in den beliebtesten Python-Editoren getestet: PyCharm, VS Code, Jedi-basierte Editoren. -Laut der letzten Python-Entwickler-Umfrage, deckt das etwa 80 % der Benutzer ab. +Laut der letzten Python-Entwickler-Umfrage deckt das etwa 80 % der Benutzer ab. Das bedeutet, dass **FastAPI** speziell mit den Editoren getestet wurde, die von 80 % der Python-Entwickler verwendet werden. Und da die meisten anderen Editoren in der Regel ähnlich funktionieren, sollten alle diese Vorteile für praktisch alle Editoren funktionieren. @@ -52,19 +52,19 @@ Auf diese Weise konnte ich die besten Möglichkeiten finden, die Codeverdoppelun Alles auf eine Weise, die allen Entwicklern das beste Entwicklungserlebnis bot. -## Anforderungen +## Anforderungen { #requirements } -Nachdem ich mehrere Alternativen getestet hatte, entschied ich, dass ich **Pydantic** wegen seiner Vorteile verwenden würde. +Nachdem ich mehrere Alternativen getestet hatte, entschied ich, dass ich **Pydantic** wegen seiner Vorteile verwenden würde. Dann habe ich zu dessen Code beigetragen, um es vollständig mit JSON Schema kompatibel zu machen, und so verschiedene Möglichkeiten zum Definieren von einschränkenden Deklarationen (Constraints) zu unterstützen, und die Editorunterstützung (Typprüfungen, Codevervollständigung) zu verbessern, basierend auf den Tests in mehreren Editoren. Während der Entwicklung habe ich auch zu **Starlette** beigetragen, der anderen Schlüsselanforderung. -## Entwicklung +## Entwicklung { #development } Als ich mit der Erstellung von **FastAPI** selbst begann, waren die meisten Teile bereits vorhanden, das Design definiert, die Anforderungen und Tools bereit und das Wissen über die Standards und Spezifikationen klar und frisch. -## Zukunft +## Zukunft { #future } Zu diesem Zeitpunkt ist bereits klar, dass **FastAPI** mit seinen Ideen für viele Menschen nützlich ist. diff --git a/docs/de/docs/how-to/conditional-openapi.md b/docs/de/docs/how-to/conditional-openapi.md index 50ae11f90..0f0b2d297 100644 --- a/docs/de/docs/how-to/conditional-openapi.md +++ b/docs/de/docs/how-to/conditional-openapi.md @@ -1,8 +1,8 @@ -# Bedingte OpenAPI +# Bedingte OpenAPI { #conditional-openapi } Bei Bedarf können Sie OpenAPI mithilfe von Einstellungen und Umgebungsvariablen abhängig von der Umgebung bedingt konfigurieren und sogar vollständig deaktivieren. -## Über Sicherheit, APIs und Dokumentation +## Über Sicherheit, APIs und Dokumentation { #about-security-apis-and-docs } Das Verstecken Ihrer Dokumentationsoberflächen in der Produktion *sollte nicht* die Methode sein, Ihre API zu schützen. @@ -10,11 +10,11 @@ Dadurch wird Ihrer API keine zusätzliche Sicherheit hinzugefügt, die *Pfadoper Wenn Ihr Code eine Sicherheitslücke aufweist, ist diese weiterhin vorhanden. -Das Verstecken der Dokumentation macht es nur schwieriger zu verstehen, wie mit Ihrer API interagiert werden kann, und könnte es auch schwieriger machen, diese in der Produktion zu debuggen. Man könnte es einfach als eine Form von Security through obscurity betrachten. +Das Verstecken der Dokumentation macht es nur schwieriger zu verstehen, wie mit Ihrer API interagiert werden kann, und könnte es auch schwieriger machen, diese in der Produktion zu debuggen. Man könnte es einfach als eine Form von Sicherheit durch Verschleierung betrachten. Wenn Sie Ihre API sichern möchten, gibt es mehrere bessere Dinge, die Sie tun können, zum Beispiel: -* Stellen Sie sicher, dass Sie über gut definierte Pydantic-Modelle für Ihre Requestbodys und Responses verfügen. +* Stellen Sie sicher, dass Sie über gut definierte Pydantic-Modelle für Ihre Requestbodys und Responses verfügen. * Konfigurieren Sie alle erforderlichen Berechtigungen und Rollen mithilfe von Abhängigkeiten. * Speichern Sie niemals Klartext-Passwörter, sondern nur Passwort-Hashes. * Implementieren und verwenden Sie gängige kryptografische Tools wie Passlib und JWT-Tokens, usw. @@ -23,7 +23,7 @@ Wenn Sie Ihre API sichern möchten, gibt es mehrere bessere Dinge, die Sie tun k Dennoch kann es sein, dass Sie einen ganz bestimmten Anwendungsfall haben, bei dem Sie die API-Dokumentation für eine bestimmte Umgebung (z. B. für die Produktion) oder abhängig von Konfigurationen aus Umgebungsvariablen wirklich deaktivieren müssen. -## Bedingte OpenAPI aus Einstellungen und Umgebungsvariablen +## Bedingte OpenAPI aus Einstellungen und Umgebungsvariablen { #conditional-openapi-from-settings-and-env-vars } Sie können problemlos dieselben Pydantic-Einstellungen verwenden, um Ihre generierte OpenAPI und die Dokumentationsoberflächen zu konfigurieren. @@ -33,7 +33,7 @@ Zum Beispiel: Hier deklarieren wir die Einstellung `openapi_url` mit dem gleichen Defaultwert `"/openapi.json"`. -Und dann verwenden wir das beim Erstellen der `FastAPI`-App. +Und dann verwenden wir es beim Erstellen der `FastAPI`-App. Dann könnten Sie OpenAPI (einschließlich der Dokumentationsoberflächen) deaktivieren, indem Sie die Umgebungsvariable `OPENAPI_URL` auf einen leeren String setzen, wie zum Beispiel: diff --git a/docs/de/docs/how-to/configure-swagger-ui.md b/docs/de/docs/how-to/configure-swagger-ui.md index 1ee72d205..351cb996c 100644 --- a/docs/de/docs/how-to/configure-swagger-ui.md +++ b/docs/de/docs/how-to/configure-swagger-ui.md @@ -1,14 +1,14 @@ -# Swagger-Oberfläche konfigurieren +# Swagger-Oberfläche konfigurieren { #configure-swagger-ui } Sie können einige zusätzliche Parameter der Swagger-Oberfläche konfigurieren. Um diese zu konfigurieren, übergeben Sie das Argument `swagger_ui_parameters` beim Erstellen des `FastAPI()`-App-Objekts oder an die Funktion `get_swagger_ui_html()`. -`swagger_ui_parameters` empfängt ein Dict mit den Konfigurationen, die direkt an die Swagger-Oberfläche übergeben werden. +`swagger_ui_parameters` empfängt ein Dictionary mit den Konfigurationen, die direkt an die Swagger-Oberfläche übergeben werden. FastAPI konvertiert die Konfigurationen nach **JSON**, um diese mit JavaScript kompatibel zu machen, da die Swagger-Oberfläche das benötigt. -## Syntaxhervorhebung deaktivieren +## Syntaxhervorhebung deaktivieren { #disable-syntax-highlighting } Sie könnten beispielsweise die Syntaxhervorhebung in der Swagger-Oberfläche deaktivieren. @@ -24,9 +24,9 @@ Sie können sie jedoch deaktivieren, indem Sie `syntaxHighlight` auf `False` set -## Das Theme ändern +## Das Theme ändern { #change-the-theme } -Auf die gleiche Weise könnten Sie das Theme der Syntaxhervorhebung mit dem Schlüssel `syntaxHighlight.theme` festlegen (beachten Sie, dass er einen Punkt in der Mitte hat): +Auf die gleiche Weise könnten Sie das Theme der Syntaxhervorhebung mit dem Schlüssel `"syntaxHighlight.theme"` festlegen (beachten Sie, dass er einen Punkt in der Mitte hat): {* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *} @@ -34,13 +34,13 @@ Obige Konfiguration würde das Theme für die Farbe der Syntaxhervorhebung ände -## Defaultparameter der Swagger-Oberfläche ändern +## Defaultparameter der Swagger-Oberfläche ändern { #change-default-swagger-ui-parameters } FastAPI enthält einige Defaultkonfigurationsparameter, die für die meisten Anwendungsfälle geeignet sind. Es umfasst die folgenden Defaultkonfigurationen: -{* ../../fastapi/openapi/docs.py ln[7:23] *} +{* ../../fastapi/openapi/docs.py ln[8:23] hl[17:23] *} Sie können jede davon überschreiben, indem Sie im Argument `swagger_ui_parameters` einen anderen Wert festlegen. @@ -48,13 +48,13 @@ Um beispielsweise `deepLinking` zu deaktivieren, könnten Sie folgende Einstellu {* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *} -## Andere Parameter der Swagger-Oberfläche +## Andere Parameter der Swagger-Oberfläche { #other-swagger-ui-parameters } Um alle anderen möglichen Konfigurationen zu sehen, die Sie verwenden können, lesen Sie die offizielle Dokumentation für die Parameter der Swagger-Oberfläche. -## JavaScript-basierte Einstellungen +## Nur-JavaScript-Einstellungen { #javascript-only-settings } -Die Swagger-Oberfläche erlaubt, dass andere Konfigurationen auch **JavaScript**-Objekte sein können (z. B. JavaScript-Funktionen). +Die Swagger-Oberfläche erlaubt, dass andere Konfigurationen auch **Nur-JavaScript**-Objekte sein können (z. B. JavaScript-Funktionen). FastAPI umfasst auch diese Nur-JavaScript-`presets`-Einstellungen: diff --git a/docs/de/docs/how-to/custom-docs-ui-assets.md b/docs/de/docs/how-to/custom-docs-ui-assets.md index f68902b99..6b8b1a176 100644 --- a/docs/de/docs/how-to/custom-docs-ui-assets.md +++ b/docs/de/docs/how-to/custom-docs-ui-assets.md @@ -1,18 +1,18 @@ -# Statische Assets der Dokumentationsoberfläche (selbst hosten) +# Statische Assets der Dokumentationsoberfläche (Selbst-Hosting) { #custom-docs-ui-static-assets-self-hosting } Die API-Dokumentation verwendet **Swagger UI** und **ReDoc**, und jede dieser Dokumentationen benötigt einige JavaScript- und CSS-Dateien. -Standardmäßig werden diese Dateien von einem CDN bereitgestellt. +Standardmäßig werden diese Dateien von einem CDN bereitgestellt. Es ist jedoch möglich, das anzupassen, ein bestimmtes CDN festzulegen oder die Dateien selbst bereitzustellen. -## Benutzerdefiniertes CDN für JavaScript und CSS +## Benutzerdefiniertes CDN für JavaScript und CSS { #custom-cdn-for-javascript-and-css } -Nehmen wir an, Sie möchten ein anderes CDN verwenden, zum Beispiel möchten Sie `https://unpkg.com/` verwenden. +Nehmen wir an, Sie möchten ein anderes CDN verwenden, zum Beispiel möchten Sie `https://unpkg.com/` verwenden. Das kann nützlich sein, wenn Sie beispielsweise in einem Land leben, in dem bestimmte URLs eingeschränkt sind. -### Die automatischen Dokumentationen deaktivieren +### Die automatischen Dokumentationen deaktivieren { #disable-the-automatic-docs } Der erste Schritt besteht darin, die automatischen Dokumentationen zu deaktivieren, da diese standardmäßig das Standard-CDN verwenden. @@ -20,7 +20,7 @@ Um diese zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-A {* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *} -### Die benutzerdefinierten Dokumentationen hinzufügen +### Die benutzerdefinierten Dokumentationen hinzufügen { #include-the-custom-docs } Jetzt können Sie die *Pfadoperationen* für die benutzerdefinierten Dokumentationen erstellen. @@ -32,7 +32,7 @@ Sie können die internen Funktionen von FastAPI wiederverwenden, um die HTML-Sei * `swagger_js_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **JavaScript**-Datei abrufen kann. Dies ist die benutzerdefinierte CDN-URL. * `swagger_css_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **CSS**-Datei abrufen kann. Dies ist die benutzerdefinierte CDN-URL. -Und genau so für ReDoc ... +Und ähnlich für ReDoc ... {* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *} @@ -46,23 +46,23 @@ Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „U /// -### Eine *Pfadoperation* erstellen, um es zu testen +### Eine *Pfadoperation* erstellen, um es zu testen { #create-a-path-operation-to-test-it } Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: {* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} -### Es ausprobieren +### Es testen { #test-it } -Jetzt sollten Sie in der Lage sein, zu Ihrer Dokumentation auf http://127.0.0.1:8000/docs zu gehen und die Seite neu zuladen, die Assets werden nun vom neuen CDN geladen. +Jetzt sollten Sie in der Lage sein, zu Ihrer Dokumentation auf http://127.0.0.1:8000/docs zu gehen und die Seite neu zu laden, die Assets werden nun vom neuen CDN geladen. -## JavaScript und CSS für die Dokumentation selbst hosten +## JavaScript und CSS für die Dokumentation selbst hosten { #self-hosting-javascript-and-css-for-docs } -Das Selbst Hosten von JavaScript und CSS kann nützlich sein, wenn Sie beispielsweise möchten, dass Ihre Anwendung auch offline, ohne bestehenden Internetzugang oder in einem lokalen Netzwerk weiter funktioniert. +Das Selbst-Hosting von JavaScript und CSS kann nützlich sein, wenn Sie beispielsweise möchten, dass Ihre Anwendung auch offline, ohne bestehenden Internetzugang oder in einem lokalen Netzwerk weiter funktioniert. Hier erfahren Sie, wie Sie diese Dateien selbst in derselben FastAPI-App bereitstellen und die Dokumentation für deren Verwendung konfigurieren. -### Projektdateistruktur +### Projektdateistruktur { #project-file-structure } Nehmen wir an, die Dateistruktur Ihres Projekts sieht folgendermaßen aus: @@ -85,11 +85,11 @@ Ihre neue Dateistruktur könnte so aussehen: └── static/ ``` -### Die Dateien herunterladen +### Die Dateien herunterladen { #download-the-files } Laden Sie die für die Dokumentation benötigten statischen Dateien herunter und legen Sie diese im Verzeichnis `static/` ab. -Sie können wahrscheinlich mit der rechten Maustaste auf jeden Link klicken und eine Option wie etwa `Link speichern unter...` auswählen. +Sie können wahrscheinlich mit der rechten Maustaste auf jeden Link klicken und eine Option wie etwa „Link speichern unter ...“ auswählen. **Swagger UI** verwendet folgende Dateien: @@ -113,14 +113,14 @@ Danach könnte Ihre Dateistruktur wie folgt aussehen: └── swagger-ui.css ``` -### Die statischen Dateien bereitstellen +### Die statischen Dateien bereitstellen { #serve-the-static-files } * Importieren Sie `StaticFiles`. * „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad. {* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *} -### Die statischen Dateien testen +### Die statischen Dateien testen { #test-the-static-files } Starten Sie Ihre Anwendung und gehen Sie auf http://127.0.0.1:8000/static/redoc.standalone.js. @@ -138,19 +138,19 @@ Das zeigt, dass Sie statische Dateien aus Ihrer Anwendung bereitstellen können Jetzt können wir die Anwendung so konfigurieren, dass sie diese statischen Dateien für die Dokumentation verwendet. -### Die automatischen Dokumentationen deaktivieren, für statische Dateien +### Die automatischen Dokumentationen für statische Dateien deaktivieren { #disable-the-automatic-docs-for-static-files } Wie bei der Verwendung eines benutzerdefinierten CDN besteht der erste Schritt darin, die automatischen Dokumentationen zu deaktivieren, da diese standardmäßig das CDN verwenden. -Um diese zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`: +Um sie zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`: {* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *} -### Die benutzerdefinierten Dokumentationen, mit statischen Dateien, hinzufügen +### Die benutzerdefinierten Dokumentationen für statische Dateien hinzufügen { #include-the-custom-docs-for-static-files } Und genau wie bei einem benutzerdefinierten CDN können Sie jetzt die *Pfadoperationen* für die benutzerdefinierten Dokumentationen erstellen. -Auch hier können Sie die internen Funktionen von FastAPI wiederverwenden, um die HTML-Seiten für die Dokumentationen zu erstellen, und diesen die erforderlichen Argumente übergeben: +Auch hier können Sie die internen Funktionen von FastAPI wiederverwenden, um die HTML-Seiten für die Dokumentationen zu erstellen und ihnen die erforderlichen Argumente zu übergeben: * `openapi_url`: die URL, unter der die HTML-Seite für die Dokumentation das OpenAPI-Schema für Ihre API abrufen kann. Sie können hier das Attribut `app.openapi_url` verwenden. * `title`: der Titel Ihrer API. @@ -158,7 +158,7 @@ Auch hier können Sie die internen Funktionen von FastAPI wiederverwenden, um di * `swagger_js_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **JavaScript**-Datei abrufen kann. **Das ist die, welche jetzt von Ihrer eigenen Anwendung bereitgestellt wird**. * `swagger_css_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **CSS**-Datei abrufen kann. **Das ist die, welche jetzt von Ihrer eigenen Anwendung bereitgestellt wird**. -Und genau so für ReDoc ... +Und ähnlich für ReDoc ... {* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *} @@ -172,14 +172,14 @@ Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „U /// -### Eine *Pfadoperation* erstellen, um statische Dateien zu testen +### Eine *Pfadoperation* erstellen, um statische Dateien zu testen { #create-a-path-operation-to-test-static-files } Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: {* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} -### Benutzeroberfläche, mit statischen Dateien, testen +### Benutzeroberfläche mit statischen Dateien testen { #test-static-files-ui } Jetzt sollten Sie in der Lage sein, Ihr WLAN zu trennen, gehen Sie zu Ihrer Dokumentation unter http://127.0.0.1:8000/docs und laden Sie die Seite neu. -Und selbst ohne Internet könnten Sie die Dokumentation für Ihre API sehen und damit interagieren. +Und selbst ohne Internet können Sie die Dokumentation für Ihre API sehen und mit ihr interagieren. diff --git a/docs/de/docs/how-to/custom-request-and-route.md b/docs/de/docs/how-to/custom-request-and-route.md index 3e6f709b6..41a85f832 100644 --- a/docs/de/docs/how-to/custom-request-and-route.md +++ b/docs/de/docs/how-to/custom-request-and-route.md @@ -1,10 +1,10 @@ -# Benutzerdefinierte Request- und APIRoute-Klasse +# Benutzerdefinierte Request- und APIRoute-Klasse { #custom-request-and-apiroute-class } In einigen Fällen möchten Sie möglicherweise die von den Klassen `Request` und `APIRoute` verwendete Logik überschreiben. Das kann insbesondere eine gute Alternative zur Logik in einer Middleware sein. -Wenn Sie beispielsweise den Requestbody lesen oder manipulieren möchten, bevor er von Ihrer Anwendung verarbeitet wird. +Wenn Sie beispielsweise den Requestbody lesen oder manipulieren möchten, bevor er von Ihrer Anwendung verarbeitet wird. /// danger | Gefahr @@ -14,7 +14,7 @@ Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie diesen Abschnitt vie /// -## Anwendungsfälle +## Anwendungsfälle { #use-cases } Einige Anwendungsfälle sind: @@ -22,13 +22,13 @@ Einige Anwendungsfälle sind: * Dekomprimierung gzip-komprimierter Requestbodys. * Automatisches Loggen aller Requestbodys. -## Handhaben von benutzerdefinierten Requestbody-Kodierungen +## Handhaben von benutzerdefinierten Requestbody-Kodierungen { #handling-custom-request-body-encodings } Sehen wir uns an, wie Sie eine benutzerdefinierte `Request`-Unterklasse verwenden, um gzip-Requests zu dekomprimieren. Und eine `APIRoute`-Unterklasse zur Verwendung dieser benutzerdefinierten Requestklasse. -### Eine benutzerdefinierte `GzipRequest`-Klasse erstellen +### Eine benutzerdefinierte `GzipRequest`-Klasse erstellen { #create-a-custom-gziprequest-class } /// tip | Tipp @@ -44,13 +44,13 @@ Auf diese Weise kann dieselbe Routenklasse gzip-komprimierte oder unkomprimierte {* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *} -### Eine benutzerdefinierte `GzipRoute`-Klasse erstellen +### Eine benutzerdefinierte `GzipRoute`-Klasse erstellen { #create-a-custom-gziproute-class } Als Nächstes erstellen wir eine benutzerdefinierte Unterklasse von `fastapi.routing.APIRoute`, welche `GzipRequest` nutzt. Dieses Mal wird die Methode `APIRoute.get_route_handler()` überschrieben. -Diese Methode gibt eine Funktion zurück. Und diese Funktion empfängt einen Request und gibt eine Response zurück. +Diese Methode gibt eine Funktion zurück. Und diese Funktion empfängt einen Request und gibt eine Response zurück. Hier verwenden wir sie, um aus dem ursprünglichen Request einen `GzipRequest` zu erstellen. @@ -58,9 +58,9 @@ Hier verwenden wir sie, um aus dem ursprünglichen Request einen `GzipRequest` z /// note | Technische Details -Ein `Request` hat ein `request.scope`-Attribut, welches einfach ein Python-`dict` ist, welches die mit dem Request verbundenen Metadaten enthält. +Ein `Request` hat ein `request.scope`-Attribut, welches einfach ein Python-`dict` ist, welches die mit dem Request verbundenen Metadaten enthält. -Ein `Request` hat auch ein `request.receive`, welches eine Funktion ist, die den Hauptteil des Requests empfängt. +Ein `Request` hat auch ein `request.receive`, welches eine Funktion ist, die den Body des Requests empfängt. Das `scope`-`dict` und die `receive`-Funktion sind beide Teil der ASGI-Spezifikation. @@ -78,11 +78,11 @@ Danach ist die gesamte Verarbeitungslogik dieselbe. Aufgrund unserer Änderungen in `GzipRequest.body` wird der Requestbody jedoch bei Bedarf automatisch dekomprimiert, wenn er von **FastAPI** geladen wird. -## Zugriff auf den Requestbody in einem Exceptionhandler +## Zugriff auf den Requestbody in einem Exceptionhandler { #accessing-the-request-body-in-an-exception-handler } /// tip | Tipp -Um dasselbe Problem zu lösen, ist es wahrscheinlich viel einfacher, den `body` in einem benutzerdefinierten Handler für `RequestValidationError` zu verwenden ([Fehlerbehandlung](../tutorial/handling-errors.md#den-requestvalidationerror-body-verwenden){.internal-link target=_blank}). +Um dasselbe Problem zu lösen, ist es wahrscheinlich viel einfacher, den `body` in einem benutzerdefinierten Handler für `RequestValidationError` zu verwenden ([Fehlerbehandlung](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}). Dieses Beispiel ist jedoch immer noch gültig und zeigt, wie mit den internen Komponenten interagiert wird. @@ -98,7 +98,7 @@ Wenn eine Exception auftritt, befindet sich die `Request`-Instanz weiterhin im G {* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *} -## Benutzerdefinierte `APIRoute`-Klasse in einem Router +## Benutzerdefinierte `APIRoute`-Klasse in einem Router { #custom-apiroute-class-in-a-router } Sie können auch den Parameter `route_class` eines `APIRouter` festlegen: diff --git a/docs/de/docs/how-to/extending-openapi.md b/docs/de/docs/how-to/extending-openapi.md index 3b1459364..146ee098b 100644 --- a/docs/de/docs/how-to/extending-openapi.md +++ b/docs/de/docs/how-to/extending-openapi.md @@ -1,24 +1,24 @@ -# OpenAPI erweitern +# OpenAPI erweitern { #extending-openapi } -In einigen Fällen müssen Sie möglicherweise das generierte OpenAPI-Schema ändern. +Es gibt einige Fälle, in denen Sie das generierte OpenAPI-Schema ändern müssen. In diesem Abschnitt erfahren Sie, wie. -## Der normale Vorgang +## Der normale Vorgang { #the-normal-process } Der normale (Standard-)Prozess ist wie folgt. -Eine `FastAPI`-Anwendung (-Instanz) verfügt über eine `.openapi()`-Methode, von der erwartet wird, dass sie das OpenAPI-Schema zurückgibt. +Eine `FastAPI`-Anwendung (Instanz) verfügt über eine `.openapi()`-Methode, von der erwartet wird, dass sie das OpenAPI-Schema zurückgibt. Als Teil der Erstellung des Anwendungsobjekts wird eine *Pfadoperation* für `/openapi.json` (oder welcher Wert für den Parameter `openapi_url` gesetzt wurde) registriert. -Diese gibt lediglich eine JSON-Response zurück, mit dem Ergebnis der Methode `.openapi()` der Anwendung. +Diese gibt lediglich eine JSON-Response zurück, mit dem Ergebnis der Methode `.openapi()` der Anwendung. Standardmäßig überprüft die Methode `.openapi()` die Eigenschaft `.openapi_schema`, um zu sehen, ob diese Inhalt hat, und gibt diesen zurück. Ist das nicht der Fall, wird der Inhalt mithilfe der Hilfsfunktion unter `fastapi.openapi.utils.get_openapi` generiert. -Und diese Funktion `get_openapi()` erhält als Parameter: +Diese Funktion `get_openapi()` erhält als Parameter: * `title`: Der OpenAPI-Titel, der in der Dokumentation angezeigt wird. * `version`: Die Version Ihrer API, z. B. `2.5.0`. @@ -27,53 +27,53 @@ Und diese Funktion `get_openapi()` erhält als Parameter: * `description`: Die Beschreibung Ihrer API. Dies kann Markdown enthalten und wird in der Dokumentation angezeigt. * `routes`: Eine Liste von Routen, dies sind alle registrierten *Pfadoperationen*. Sie stammen von `app.routes`. -/// info +/// info | Info Der Parameter `summary` ist in OpenAPI 3.1.0 und höher verfügbar und wird von FastAPI 0.99.0 und höher unterstützt. /// -## Überschreiben der Standardeinstellungen +## Überschreiben der Standardeinstellungen { #overriding-the-defaults } Mithilfe der oben genannten Informationen können Sie dieselbe Hilfsfunktion verwenden, um das OpenAPI-Schema zu generieren und jeden benötigten Teil zu überschreiben. -Fügen wir beispielsweise ReDocs OpenAPI-Erweiterung zum Einbinden eines benutzerdefinierten Logos hinzu. +Fügen wir beispielsweise ReDocs OpenAPI-Erweiterung zum Einbinden eines benutzerdefinierten Logos hinzu. -### Normales **FastAPI** +### Normales **FastAPI** { #normal-fastapi } Schreiben Sie zunächst wie gewohnt Ihre ganze **FastAPI**-Anwendung: {* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *} -### Das OpenAPI-Schema generieren +### Das OpenAPI-Schema generieren { #generate-the-openapi-schema } Verwenden Sie dann dieselbe Hilfsfunktion, um das OpenAPI-Schema innerhalb einer `custom_openapi()`-Funktion zu generieren: {* ../../docs_src/extending_openapi/tutorial001.py hl[2,15:21] *} -### Das OpenAPI-Schema ändern +### Das OpenAPI-Schema ändern { #modify-the-openapi-schema } Jetzt können Sie die ReDoc-Erweiterung hinzufügen und dem `info`-„Objekt“ im OpenAPI-Schema ein benutzerdefiniertes `x-logo` hinzufügen: {* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *} -### Zwischenspeichern des OpenAPI-Schemas +### Zwischenspeichern des OpenAPI-Schemas { #cache-the-openapi-schema } Sie können die Eigenschaft `.openapi_schema` als „Cache“ verwenden, um Ihr generiertes Schema zu speichern. Auf diese Weise muss Ihre Anwendung das Schema nicht jedes Mal generieren, wenn ein Benutzer Ihre API-Dokumentation öffnet. -Es wird nur einmal generiert und dann wird dasselbe zwischengespeicherte Schema für die nächsten Requests verwendet. +Es wird nur einmal generiert und dann wird dasselbe zwischengespeicherte Schema für die nächsten Requests verwendet. {* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *} -### Die Methode überschreiben +### Die Methode überschreiben { #override-the-method } Jetzt können Sie die Methode `.openapi()` durch Ihre neue Funktion ersetzen. {* ../../docs_src/extending_openapi/tutorial001.py hl[29] *} -### Testen +### Es testen { #check-it } Sobald Sie auf http://127.0.0.1:8000/redoc gehen, werden Sie sehen, dass Ihr benutzerdefiniertes Logo verwendet wird (in diesem Beispiel das Logo von **FastAPI**): diff --git a/docs/de/docs/how-to/general.md b/docs/de/docs/how-to/general.md index b38b5fabf..0045eab74 100644 --- a/docs/de/docs/how-to/general.md +++ b/docs/de/docs/how-to/general.md @@ -1,39 +1,39 @@ -# Allgemeines – How-To – Rezepte +# Allgemeines – How-To – Rezepte { #general-how-to-recipes } Hier finden Sie mehrere Verweise auf andere Stellen in der Dokumentation, für allgemeine oder häufige Fragen. -## Daten filtern – Sicherheit +## Daten filtern – Sicherheit { #filter-data-security } Um sicherzustellen, dass Sie nicht mehr Daten zurückgeben, als Sie sollten, lesen Sie die Dokumentation unter [Tutorial – Responsemodell – Rückgabetyp](../tutorial/response-model.md){.internal-link target=_blank}. -## Dokumentations-Tags – OpenAPI +## Dokumentations-Tags – OpenAPI { #documentation-tags-openapi } Um Tags zu Ihren *Pfadoperationen* hinzuzufügen und diese in der Oberfläche der Dokumentation zu gruppieren, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Tags](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank}. -## Zusammenfassung und Beschreibung in der Dokumentation – OpenAPI +## Zusammenfassung und Beschreibung in der Dokumentation – OpenAPI { #documentation-summary-and-description-openapi } -Um Ihren *Pfadoperationen* eine Zusammenfassung und Beschreibung hinzuzufügen und diese in der Oberfläche der Dokumentation anzuzeigen, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Zusammenfassung und Beschreibung](../tutorial/path-operation-configuration.md#zusammenfassung-und-beschreibung){.internal-link target=_blank}. +Um Ihren *Pfadoperationen* eine Zusammenfassung und Beschreibung hinzuzufügen und diese in der Oberfläche der Dokumentation anzuzeigen, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Zusammenfassung und Beschreibung](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank}. -## Beschreibung der Response in der Dokumentation – OpenAPI +## Beschreibung der Response in der Dokumentation – OpenAPI { #documentation-response-description-openapi } -Um die Beschreibung der Response zu definieren, welche in der Oberfläche der Dokumentation angezeigt wird, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Beschreibung der Response](../tutorial/path-operation-configuration.md#beschreibung-der-response){.internal-link target=_blank}. +Um die Beschreibung der Response zu definieren, welche in der Oberfläche der Dokumentation angezeigt wird, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Beschreibung der Response](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank}. -## *Pfadoperation* in der Dokumentation deprecaten – OpenAPI +## *Pfadoperation* in der Dokumentation deprecaten – OpenAPI { #documentation-deprecate-a-path-operation-openapi } -Um eine *Pfadoperation* zu deprecaten – sie als veraltet zu markieren – und das in der Oberfläche der Dokumentation anzuzeigen, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Deprecaten](../tutorial/path-operation-configuration.md#eine-pfadoperation-deprecaten){.internal-link target=_blank}. +Um eine *Pfadoperation* zu deprecaten und das in der Oberfläche der Dokumentation anzuzeigen, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Deprecaten](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank}. -## Daten in etwas JSON-kompatibles konvertieren +## Daten in etwas JSON-kompatibles konvertieren { #convert-any-data-to-json-compatible } Um Daten in etwas JSON-kompatibles zu konvertieren, lesen Sie die Dokumentation unter [Tutorial – JSON-kompatibler Encoder](../tutorial/encoder.md){.internal-link target=_blank}. -## OpenAPI-Metadaten – Dokumentation +## OpenAPI-Metadaten – Dokumentation { #openapi-metadata-docs } -Um Metadaten zu Ihrem OpenAPI-Schema hinzuzufügen, einschließlich einer Lizenz, Version, Kontakt, usw., lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentationen](../tutorial/metadata.md){.internal-link target=_blank}. +Um Metadaten zu Ihrem OpenAPI-Schema hinzuzufügen, einschließlich einer Lizenz, Version, Kontakt, usw., lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentation](../tutorial/metadata.md){.internal-link target=_blank}. -## Benutzerdefinierte OpenAPI-URL +## Benutzerdefinierte OpenAPI-URL { #openapi-custom-url } -Um die OpenAPI-URL anzupassen (oder zu entfernen), lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentationen](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. +Um die OpenAPI-URL anzupassen (oder zu entfernen), lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentation](../tutorial/metadata.md#openapi-url){.internal-link target=_blank}. -## URLs der OpenAPI-Dokumentationen +## URLs der OpenAPI-Dokumentationen { #openapi-docs-urls } -Um die URLs zu aktualisieren, die für die automatisch generierten Dokumentations-Oberflächen verwendet werden, lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentationen](../tutorial/metadata.md#urls-der-dokumentationen){.internal-link target=_blank}. +Um die URLs zu aktualisieren, die für die automatisch generierten Dokumentations-Oberflächen verwendet werden, lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentation](../tutorial/metadata.md#docs-urls){.internal-link target=_blank}. diff --git a/docs/de/docs/how-to/graphql.md b/docs/de/docs/how-to/graphql.md index 4083e66ae..d2958dcd9 100644 --- a/docs/de/docs/how-to/graphql.md +++ b/docs/de/docs/how-to/graphql.md @@ -1,4 +1,4 @@ -# GraphQL +# GraphQL { #graphql } Da **FastAPI** auf dem **ASGI**-Standard basiert, ist es sehr einfach, jede **GraphQL**-Bibliothek zu integrieren, die auch mit ASGI kompatibel ist. @@ -10,42 +10,42 @@ Sie können normale FastAPI-*Pfadoperationen* mit GraphQL in derselben Anwendung Es hat **Vorteile** und **Nachteile** im Vergleich zu gängigen **Web-APIs**. -Wiegen Sie ab, ob die **Vorteile** für Ihren Anwendungsfall die **Nachteile** ausgleichen. 🤓 +Stellen Sie sicher, dass Sie prüfen, ob die **Vorteile** für Ihren Anwendungsfall die **Nachteile** ausgleichen. 🤓 /// -## GraphQL-Bibliotheken +## GraphQL-Bibliotheken { #graphql-libraries } -Hier sind einige der **GraphQL**-Bibliotheken, welche **ASGI** unterstützen. Diese könnten Sie mit **FastAPI** verwenden: +Hier sind einige der **GraphQL**-Bibliotheken, die **ASGI**-Unterstützung haben. Sie könnten sie mit **FastAPI** verwenden: * Strawberry 🍓 * Mit Dokumentation für FastAPI * Ariadne * Mit Dokumentation für FastAPI * Tartiflette - * Mit Tartiflette ASGI, für ASGI-Integration + * Mit Tartiflette ASGI für ASGI-Integration * Graphene * Mit starlette-graphene3 -## GraphQL mit Strawberry +## GraphQL mit Strawberry { #graphql-with-strawberry } -Wenn Sie mit **GraphQL** arbeiten möchten oder müssen, ist **Strawberry** die **empfohlene** Bibliothek, da deren Design dem Design von **FastAPI** am nächsten kommt und alles auf **Typannotationen** basiert. +Wenn Sie mit **GraphQL** arbeiten möchten oder müssen, ist **Strawberry** die **empfohlene** Bibliothek, da deren Design **FastAPIs** Design am nächsten kommt und alles auf **Typannotationen** basiert. -Abhängig von Ihrem Anwendungsfall bevorzugen Sie vielleicht eine andere Bibliothek, aber wenn Sie mich fragen würden, würde ich Ihnen wahrscheinlich empfehlen, **Strawberry** auszuprobieren. +Abhängig von Ihrem Anwendungsfall könnten Sie eine andere Bibliothek vorziehen, aber wenn Sie mich fragen würden, würde ich Ihnen wahrscheinlich empfehlen, **Strawberry** auszuprobieren. Hier ist eine kleine Vorschau, wie Sie Strawberry mit FastAPI integrieren können: -{* ../../docs_src/graphql/tutorial001.py hl[3,22,25:26] *} +{* ../../docs_src/graphql/tutorial001.py hl[3,22,25] *} Weitere Informationen zu Strawberry finden Sie in der Strawberry-Dokumentation. -Und auch die Dokumentation zu Strawberry mit FastAPI. +Und auch in der Dokumentation zu Strawberry mit FastAPI. -## Ältere `GraphQLApp` von Starlette +## Ältere `GraphQLApp` von Starlette { #older-graphqlapp-from-starlette } Frühere Versionen von Starlette enthielten eine `GraphQLApp`-Klasse zur Integration mit Graphene. -Das wurde von Starlette deprecated, aber wenn Sie Code haben, der das verwendet, können Sie einfach zu starlette-graphene3 **migrieren**, welches denselben Anwendungsfall abdeckt und über eine **fast identische Schnittstelle** verfügt. +Das wurde von Starlette deprecatet, aber wenn Sie Code haben, der das verwendet, können Sie einfach zu starlette-graphene3 **migrieren**, das denselben Anwendungsfall abdeckt und eine **fast identische Schnittstelle** hat. /// tip | Tipp @@ -53,7 +53,7 @@ Wenn Sie GraphQL benötigen, würde ich Ihnen trotzdem empfehlen, sich offiziellen GraphQL-Dokumentation. diff --git a/docs/de/docs/how-to/index.md b/docs/de/docs/how-to/index.md index 84a178fc8..36229dcd7 100644 --- a/docs/de/docs/how-to/index.md +++ b/docs/de/docs/how-to/index.md @@ -1,4 +1,4 @@ -# How-To – Rezepte +# How-To – Rezepte { #how-to-recipes } Hier finden Sie verschiedene Rezepte und „How-To“-Anleitungen zu **verschiedenen Themen**. diff --git a/docs/de/docs/how-to/separate-openapi-schemas.md b/docs/de/docs/how-to/separate-openapi-schemas.md index 4f6911e79..31653590b 100644 --- a/docs/de/docs/how-to/separate-openapi-schemas.md +++ b/docs/de/docs/how-to/separate-openapi-schemas.md @@ -1,18 +1,18 @@ -# Separate OpenAPI-Schemas für Eingabe und Ausgabe oder nicht +# Separate OpenAPI-Schemas für Eingabe und Ausgabe oder nicht { #separate-openapi-schemas-for-input-and-output-or-not } Bei Verwendung von **Pydantic v2** ist die generierte OpenAPI etwas genauer und **korrekter** als zuvor. 😎 -Tatsächlich gibt es in einigen Fällen sogar **zwei JSON-Schemas** in OpenAPI für dasselbe Pydantic-Modell für Eingabe und Ausgabe, je nachdem, ob sie **Defaultwerte** haben. +Tatsächlich gibt es in einigen Fällen sogar **zwei JSON-Schemas** in OpenAPI für dasselbe Pydantic-Modell, für Eingabe und Ausgabe, je nachdem, ob sie **Defaultwerte** haben. Sehen wir uns an, wie das funktioniert und wie Sie es bei Bedarf ändern können. -## Pydantic-Modelle für Eingabe und Ausgabe +## Pydantic-Modelle für Eingabe und Ausgabe { #pydantic-models-for-input-and-output } Nehmen wir an, Sie haben ein Pydantic-Modell mit Defaultwerten wie dieses: {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} -### Modell für Eingabe +### Modell für Eingabe { #model-for-input } Wenn Sie dieses Modell wie hier als Eingabe verwenden: @@ -20,7 +20,7 @@ Wenn Sie dieses Modell wie hier als Eingabe verwenden: ... dann ist das Feld `description` **nicht erforderlich**. Weil es den Defaultwert `None` hat. -### Eingabemodell in der Dokumentation +### Eingabemodell in der Dokumentation { #input-model-in-docs } Sie können überprüfen, dass das Feld `description` in der Dokumentation kein **rotes Sternchen** enthält, es ist nicht als erforderlich markiert: @@ -28,17 +28,17 @@ Sie können überprüfen, dass das Feld `description` in der Dokumentation kein
-### Modell für die Ausgabe +### Modell für die Ausgabe { #model-for-output } Wenn Sie jedoch dasselbe Modell als Ausgabe verwenden, wie hier: {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -... dann, weil `description` einen Defaultwert hat, wird es, wenn Sie für dieses Feld **nichts zurückgeben**, immer noch diesen **Defaultwert** haben. +... dann, weil `description` einen Defaultwert hat, wird es, wenn Sie für dieses Feld **nichts zurückgeben**, immer noch diesen **Defaultwert** haben. -### Modell für Ausgabe-Responsedaten +### Modell für Ausgabe-Responsedaten { #model-for-output-response-data } -Wenn Sie mit der Dokumentation interagieren und die Response überprüfen, enthält die JSON-Response den Defaultwert (`null`), obwohl der Code nichts in eines der `description`-Felder geschrieben hat: +Wenn Sie mit der Dokumentation interagieren und die Response überprüfen, enthält die JSON-Response den Defaultwert (`null`), obwohl der Code nichts in eines der `description`-Felder geschrieben hat:
@@ -55,7 +55,7 @@ Aus diesem Grund kann das JSON-Schema für ein Modell unterschiedlich sein, je n * für die **Eingabe** ist `description` **nicht erforderlich** * für die **Ausgabe** ist es **erforderlich** (und möglicherweise `None` oder, in JSON-Begriffen, `null`) -### Ausgabemodell in der Dokumentation +### Ausgabemodell in der Dokumentation { #model-for-output-in-docs } Sie können das Ausgabemodell auch in der Dokumentation überprüfen. **Sowohl** `name` **als auch** `description` sind mit einem **roten Sternchen** als **erforderlich** markiert: @@ -63,7 +63,7 @@ Sie können das Ausgabemodell auch in der Dokumentation überprüfen. **Sowohl**
-### Eingabe- und Ausgabemodell in der Dokumentation +### Eingabe- und Ausgabemodell in der Dokumentation { #model-for-input-and-output-in-docs } Und wenn Sie alle verfügbaren Schemas (JSON-Schemas) in OpenAPI überprüfen, werden Sie feststellen, dass es zwei gibt, ein `Item-Input` und ein `Item-Output`. @@ -77,7 +77,7 @@ Aber für `Item-Output` ist `description` **erforderlich**, es hat ein rotes Ste Mit dieser Funktion von **Pydantic v2** ist Ihre API-Dokumentation **präziser**, und wenn Sie über automatisch generierte Clients und SDKs verfügen, sind diese auch präziser, mit einer besseren **Entwicklererfahrung** und Konsistenz. 🎉 -## Schemas nicht trennen +## Schemas nicht trennen { #do-not-separate-schemas } Nun gibt es einige Fälle, in denen Sie möglicherweise **dasselbe Schema für Eingabe und Ausgabe** haben möchten. @@ -85,7 +85,7 @@ Der Hauptanwendungsfall hierfür besteht wahrscheinlich darin, dass Sie das mal In diesem Fall können Sie diese Funktion in **FastAPI** mit dem Parameter `separate_input_output_schemas=False` deaktivieren. -/// info +/// info | Info Unterstützung für `separate_input_output_schemas` wurde in FastAPI `0.102.0` hinzugefügt. 🤓 @@ -93,7 +93,7 @@ Unterstützung für `separate_input_output_schemas` wurde in FastAPI `0.102.0` h {* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} -### Gleiches Schema für Eingabe- und Ausgabemodelle in der Dokumentation +### Gleiches Schema für Eingabe- und Ausgabemodelle in der Dokumentation { #same-schema-for-input-and-output-models-in-docs } Und jetzt wird es ein einziges Schema für die Eingabe und Ausgabe des Modells geben, nur `Item`, und es wird `description` als **nicht erforderlich** kennzeichnen: diff --git a/docs/de/docs/how-to/testing-database.md b/docs/de/docs/how-to/testing-database.md new file mode 100644 index 000000000..1a6095e53 --- /dev/null +++ b/docs/de/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# Eine Datenbank testen { #testing-a-database } + +Sie können sich über Datenbanken, SQL und SQLModel in der SQLModel-Dokumentation informieren. 🤓 + +Es gibt ein kurzes Tutorial zur Verwendung von SQLModel mit FastAPI. ✨ + +Dieses Tutorial enthält einen Abschnitt über das Testen von SQL-Datenbanken. 😎 diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index ecdcfbde5..edcb61b94 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -1,21 +1,21 @@ -# FastAPI +# FastAPI { #fastapi }

- FastAPI + FastAPI

- FastAPI Framework, hochperformant, leicht zu erlernen, schnell zu programmieren, einsatzbereit + FastAPI-Framework, hohe Performanz, leicht zu lernen, schnell zu entwickeln, produktionsreif

Test - Coverage + Testabdeckung Package-Version @@ -27,7 +27,7 @@ --- -**Dokumentation**: https://fastapi.tiangolo.com +**Dokumentation**: https://fastapi.tiangolo.com/de **Quellcode**: https://github.com/fastapi/fastapi @@ -37,19 +37,18 @@ FastAPI ist ein modernes, schnelles (hoch performantes) Webframework zur Erstell Seine Schlüssel-Merkmale sind: -* **Schnell**: Sehr hohe Leistung, auf Augenhöhe mit **NodeJS** und **Go** (Dank Starlette und Pydantic). [Eines der schnellsten verfügbaren Python-Frameworks](#performanz). - -* **Schnell zu programmieren**: Erhöhen Sie die Geschwindigkeit bei der Entwicklung von Funktionen um etwa 200 % bis 300 %. * +* **Schnell**: Sehr hohe Performanz, auf Augenhöhe mit **NodeJS** und **Go** (dank Starlette und Pydantic). [Eines der schnellsten verfügbaren Python-Frameworks](#performance). +* **Schnell zu entwickeln**: Erhöhen Sie die Geschwindigkeit bei der Entwicklung von Features um etwa 200 % bis 300 %. * * **Weniger Bugs**: Verringern Sie die von Menschen (Entwicklern) verursachten Fehler um etwa 40 %. * -* **Intuitiv**: Exzellente Editor-Unterstützung. Code-Vervollständigung überall. Weniger Debuggen. -* **Einfach**: So konzipiert, dass es einfach zu benutzen und zu erlernen ist. Weniger Zeit für das Lesen der Dokumentation. -* **Kurz**: Minimieren Sie die Verdoppelung von Code. Mehrere Funktionen aus jeder Parameterdeklaration. Weniger Bugs. +* **Intuitiv**: Hervorragende Editor-Unterstützung. Code-Vervollständigung überall. Weniger Zeit mit Debuggen verbringen. +* **Einfach**: So konzipiert, dass es einfach zu benutzen und zu erlernen ist. Weniger Zeit mit dem Lesen von Dokumentation verbringen. +* **Kurz**: Minimieren Sie die Verdoppelung von Code. Mehrere Features aus jeder Parameterdeklaration. Weniger Bugs. * **Robust**: Erhalten Sie produktionsreifen Code. Mit automatischer, interaktiver Dokumentation. * **Standards-basiert**: Basierend auf (und vollständig kompatibel mit) den offenen Standards für APIs: OpenAPI (früher bekannt als Swagger) und JSON Schema. -* Schätzung auf Basis von Tests in einem internen Entwicklungsteam, das Produktionsanwendungen erstellt. +* Schätzung basierend auf Tests in einem internen Entwicklungsteam, das Produktionsanwendungen erstellt. -## Sponsoren +## Sponsoren { #sponsors } @@ -64,55 +63,55 @@ Seine Schlüssel-Merkmale sind: -Andere Sponsoren +Andere Sponsoren -## Meinungen +## Meinungen { #opinions } -„_[...] Ich verwende **FastAPI** heutzutage sehr oft. [...] Ich habe tatsächlich vor, es für alle **ML-Dienste meines Teams bei Microsoft** zu verwenden. Einige davon werden in das Kernprodukt **Windows** und einige **Office**-Produkte integriert._“ +„_[...] Ich verwende **FastAPI** heutzutage sehr oft. [...] Ich habe tatsächlich vor, es für alle **ML-Services meines Teams bei Microsoft** zu verwenden. Einige davon werden in das Kernprodukt **Windows** und einige **Office**-Produkte integriert._“ -

Kabir Khan - Microsoft (Ref)
+
Kabir Khan – Microsoft (Ref.)
--- -„_Wir haben die **FastAPI**-Bibliothek genommen, um einen **REST**-Server zu erstellen, der abgefragt werden kann, um **Vorhersagen** zu erhalten. [für Ludwig]_“ +„_Wir haben die **FastAPI**-Bibliothek übernommen, um einen **REST**-Server zu erstellen, der für **Vorhersagen** abgefragt werden kann. [für Ludwig]_“ -
Piero Molino, Yaroslav Dudin, und Sai Sumanth Miryala - Uber (Ref)
+
Piero Molino, Yaroslav Dudin, und Sai Sumanth Miryala – Uber (Ref.)
--- „_**Netflix** freut sich, die Open-Source-Veröffentlichung unseres **Krisenmanagement**-Orchestrierung-Frameworks bekannt zu geben: **Dispatch**! [erstellt mit **FastAPI**]_“ -
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (Ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen – Netflix (Ref.)
--- -„_Ich bin überglücklich mit **FastAPI**. Es macht so viel Spaß!_“ +„_Ich bin hellauf begeistert von **FastAPI**. Es macht so viel Spaß!_“ -
Brian Okken - Host des Python Bytes Podcast (Ref)
+
Brian Okken – Python Bytes Podcast-Host (Ref.)
--- „_Ehrlich, was Du gebaut hast, sieht super solide und poliert aus. In vielerlei Hinsicht ist es so, wie ich **Hug** haben wollte – es ist wirklich inspirierend, jemanden so etwas bauen zu sehen._“ -
Timothy Crosley - Autor von Hug (Ref)
+
Timothy Crosley – Hug-Autor (Ref.)
--- -„_Wenn Sie ein **modernes Framework** zum Erstellen von REST-APIs erlernen möchten, schauen Sie sich **FastAPI** an. [...] Es ist schnell, einfach zu verwenden und leicht zu erlernen [...]_“ +„_Wenn Sie ein **modernes Framework** zum Erstellen von REST-APIs erlernen möchten, schauen Sie sich **FastAPI** an. [...] Es ist schnell, einfach zu verwenden und leicht zu lernen [...]_“ „_Wir haben zu **FastAPI** für unsere **APIs** gewechselt [...] Ich denke, es wird Ihnen gefallen [...]_“ -
Ines Montani - Matthew Honnibal - Gründer von Explosion AI - Autoren von spaCy (Ref) - (Ref)
+
Ines Montani – Matthew Honnibal – Explosion AI-Gründer – spaCy-Autoren (Ref.)(Ref.)
--- -„_Falls irgendjemand eine Produktions-Python-API erstellen möchte, kann ich **FastAPI** wärmstens empfehlen. Es ist **wunderschön konzipiert**, **einfach zu verwenden** und **hoch skalierbar**; es ist zu einer **Schlüsselkomponente** in unserer API-First-Entwicklungsstrategie geworden und treibt viele Automatisierungen und Dienste an, wie etwa unseren virtuellen TAC-Ingenieur._“ +„_Falls irgendjemand eine Produktions-Python-API erstellen möchte, kann ich **FastAPI** wärmstens empfehlen. Es ist **wunderschön konzipiert**, **einfach zu verwenden** und **hoch skalierbar**; es ist zu einer **Schlüsselkomponente** unserer API-First-Entwicklungsstrategie geworden und treibt viele Automatisierungen und Services an, wie etwa unseren Virtual TAC Engineer._“ -
Deon Pillsbury - Cisco (Ref)
+
Deon Pillsbury – Cisco (Ref.)
--- -## **Typer**, das FastAPI der CLIs +## **Typer**, das FastAPI der CLIs { #typer-the-fastapi-of-clis } @@ -120,42 +119,34 @@ Wenn Sie eine Starlette für die Webanteile. -* Pydantic für die Datenanteile. +* Pydantic für die Datenanteile. -## Installation +## Installation { #installation } + +Erstellen und aktivieren Sie eine virtuelle Umgebung und installieren Sie dann FastAPI:
```console -$ pip install fastapi +$ pip install "fastapi[standard]" ---> 100% ```
-Sie benötigen außerdem einen ASGI-Server. Für die Produktumgebung beispielsweise Uvicorn oder Hypercorn. +**Hinweis**: Stellen Sie sicher, dass Sie `"fastapi[standard]"` in Anführungszeichen setzen, damit es in allen Terminals funktioniert. -
+## Beispiel { #example } -```console -$ pip install "uvicorn[standard]" +### Erstellung { #create-it } ----> 100% -``` - -
- -## Beispiel - -### Erstellung - -* Erstellen Sie eine Datei `main.py` mit: +Erstellen Sie eine Datei `main.py` mit: ```Python from typing import Union @@ -198,23 +189,37 @@ async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} ``` -**Anmerkung**: +**Hinweis**: + +Wenn Sie das nicht kennen, schauen Sie sich den Abschnitt _„In Eile?“_ über `async` und `await` in der Dokumentation an. -Wenn Sie das nicht kennen, schauen Sie sich den Abschnitt _„In Eile?“_ über `async` und `await` in der Dokumentation an. -### Starten +### Starten { #run-it } -Führen Sie den Server aus: +Starten Sie den Server mit:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] INFO: Waiting for application startup. INFO: Application startup complete. ``` @@ -222,34 +227,34 @@ INFO: Application startup complete.
-Was macht der Befehl uvicorn main:app --reload ... +Was der Befehl fastapi dev main.py macht ... -Der Befehl `uvicorn main:app` bezieht sich auf: +Der Befehl `fastapi dev` liest Ihre `main.py`-Datei, erkennt die **FastAPI**-App darin und startet einen Server mit Uvicorn. -* `main`: die Datei `main.py` (das Python-„Modul“). -* `app`: das Objekt, das innerhalb von `main.py` mit der Zeile `app = FastAPI()` erzeugt wurde. -* `--reload`: lässt den Server nach Codeänderungen neu starten. Tun Sie das nur während der Entwicklung. +Standardmäßig wird `fastapi dev` mit aktiviertem Auto-Reload für die lokale Entwicklung gestartet. + +Sie können mehr darüber in der FastAPI CLI Dokumentation lesen.
-### Testen +### Es testen { #check-it } Öffnen Sie Ihren Browser unter http://127.0.0.1:8000/items/5?q=somequery. -Sie erhalten die JSON-Response: +Sie sehen die JSON-Response als: ```JSON {"item_id": 5, "q": "somequery"} ``` -Damit haben Sie bereits eine API erstellt, welche: +Sie haben bereits eine API erstellt, welche: -* HTTP-Anfragen auf den _Pfaden_ `/` und `/items/{item_id}` entgegennimmt. -* Beide _Pfade_ erhalten `GET` Operationen (auch bekannt als HTTP _Methoden_). -* Der _Pfad_ `/items/{item_id}` hat einen _Pfadparameter_ `item_id`, der ein `int` sein sollte. -* Der _Pfad_ `/items/{item_id}` hat einen optionalen `str` _Query Parameter_ `q`. +* HTTP-Requests auf den _Pfaden_ `/` und `/items/{item_id}` entgegennimmt. +* Beide _Pfade_ nehmen `GET` Operationen (auch bekannt als HTTP-_Methoden_) entgegen. +* Der _Pfad_ `/items/{item_id}` hat einen _Pfad-Parameter_ `item_id`, der ein `int` sein sollte. +* Der _Pfad_ `/items/{item_id}` hat einen optionalen `str`-_Query-Parameter_ `q`. -### Interaktive API-Dokumentation +### Interaktive API-Dokumentation { #interactive-api-docs } Gehen Sie nun auf http://127.0.0.1:8000/docs. @@ -257,19 +262,19 @@ Sie sehen die automatische interaktive API-Dokumentation (bereitgestellt von http://127.0.0.1:8000/redoc. +Und jetzt gehen Sie auf http://127.0.0.1:8000/redoc. Sie sehen die alternative automatische Dokumentation (bereitgestellt von ReDoc): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## Beispiel Aktualisierung +## Beispiel Aktualisierung { #example-upgrade } -Ändern Sie jetzt die Datei `main.py`, um den Body einer `PUT`-Anfrage zu empfangen. +Ändern Sie jetzt die Datei `main.py`, um den Body eines `PUT`-Requests zu empfangen. -Deklarieren Sie den Body mithilfe von Standard-Python-Typen, dank Pydantic. +Deklarieren Sie den Body mit Standard-Python-Typen, dank Pydantic. ```Python hl_lines="4 9-12 25-27" from typing import Union @@ -301,9 +306,9 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -Der Server sollte automatisch neu geladen werden (weil Sie oben `--reload` zum Befehl `uvicorn` hinzugefügt haben). +Der `fastapi dev`-Server sollte automatisch neu laden. -### Aktualisierung der interaktiven API-Dokumentation +### Interaktive API-Dokumentation aktualisieren { #interactive-api-docs-upgrade } Gehen Sie jetzt auf http://127.0.0.1:8000/docs. @@ -311,31 +316,31 @@ Gehen Sie jetzt auf http://127.0.0.1:8000/redoc. +Und jetzt gehen Sie auf http://127.0.0.1:8000/redoc. -* Die alternative Dokumentation wird ebenfalls den neuen Abfrageparameter und -inhalt widerspiegeln: +* Die alternative Dokumentation wird ebenfalls den neuen Query-Parameter und Body widerspiegeln: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### Zusammenfassung +### Zusammenfassung { #recap } -Zusammengefasst deklarieren Sie **einmal** die Typen von Parametern, Body, etc. als Funktionsparameter. +Zusammengefasst deklarieren Sie **einmal** die Typen von Parametern, Body, usw. als Funktionsparameter. Das machen Sie mit modernen Standard-Python-Typen. Sie müssen keine neue Syntax, Methoden oder Klassen einer bestimmten Bibliothek usw. lernen. -Nur Standard-**Python+**. +Nur Standard-**Python**. Zum Beispiel für ein `int`: @@ -356,22 +361,22 @@ item: Item * Typprüfungen. * Validierung von Daten: * Automatische und eindeutige Fehler, wenn die Daten ungültig sind. - * Validierung auch für tief verschachtelte JSON-Objekte. + * Validierung sogar für tief verschachtelte JSON-Objekte. * Konvertierung von Eingabedaten: Aus dem Netzwerk kommend, zu Python-Daten und -Typen. Lesen von: * JSON. * Pfad-Parametern. - * Abfrage-Parametern. + * Query-Parametern. * Cookies. - * Header-Feldern. + * Headern. * Formularen. * Dateien. * Konvertierung von Ausgabedaten: Konvertierung von Python-Daten und -Typen zu Netzwerkdaten (als JSON): * Konvertieren von Python-Typen (`str`, `int`, `float`, `bool`, `list`, usw.). - * `Datetime`-Objekte. + * `datetime`-Objekte. * `UUID`-Objekte. * Datenbankmodelle. * ... und viele mehr. -* Automatische interaktive API-Dokumentation, einschließlich 2 alternativer Benutzeroberflächen: +* Automatische interaktive API-Dokumentation, einschließlich zwei alternativer Benutzeroberflächen: * Swagger UI. * ReDoc. @@ -379,13 +384,13 @@ item: Item Um auf das vorherige Codebeispiel zurückzukommen, **FastAPI** wird: -* Überprüfen, dass es eine `item_id` im Pfad für `GET`- und `PUT`-Anfragen gibt. -* Überprüfen, ob die `item_id` vom Typ `int` für `GET`- und `PUT`-Anfragen ist. - * Falls nicht, wird dem Client ein nützlicher, eindeutiger Fehler angezeigt. -* Prüfen, ob es einen optionalen Abfrageparameter namens `q` (wie in `http://127.0.0.1:8000/items/foo?q=somequery`) für `GET`-Anfragen gibt. +* Validieren, dass es eine `item_id` im Pfad für `GET`- und `PUT`-Requests gibt. +* Validieren, ob die `item_id` vom Typ `int` für `GET`- und `PUT`-Requests ist. + * Falls nicht, sieht der Client einen hilfreichen, klaren Fehler. +* Prüfen, ob es einen optionalen Query-Parameter namens `q` (wie in `http://127.0.0.1:8000/items/foo?q=somequery`) für `GET`-Requests gibt. * Da der `q`-Parameter mit `= None` deklariert ist, ist er optional. * Ohne das `None` wäre er erforderlich (wie der Body im Fall von `PUT`). -* Bei `PUT`-Anfragen an `/items/{item_id}` den Body als JSON lesen: +* Bei `PUT`-Requests an `/items/{item_id}` den Body als JSON lesen: * Prüfen, ob er ein erforderliches Attribut `name` hat, das ein `str` sein muss. * Prüfen, ob er ein erforderliches Attribut `price` hat, das ein `float` sein muss. * Prüfen, ob er ein optionales Attribut `is_offer` hat, das ein `bool` sein muss, falls vorhanden. @@ -394,7 +399,7 @@ Um auf das vorherige Codebeispiel zurückzukommen, **FastAPI** wird: * Alles mit OpenAPI dokumentieren, welches verwendet werden kann von: * Interaktiven Dokumentationssystemen. * Automatisch Client-Code generierenden Systemen für viele Sprachen. -* Zwei interaktive Dokumentation-Webschnittstellen direkt zur Verfügung stellen. +* Zwei interaktive Dokumentations-Weboberflächen direkt bereitstellen. --- @@ -418,57 +423,79 @@ Versuchen Sie, diese Zeile zu ändern: ... "item_price": item.price ... ``` -... und sehen Sie, wie Ihr Editor die Attribute automatisch ausfüllt und ihre Typen kennt: +... und sehen Sie, wie Ihr Editor die Attribute automatisch vervollständigt und ihre Typen kennt: ![Editor Unterstützung](https://fastapi.tiangolo.com/img/vscode-completion.png) -Für ein vollständigeres Beispiel, mit weiteren Funktionen, siehe das Tutorial - Benutzerhandbuch. +Für ein vollständigeres Beispiel, mit weiteren Funktionen, siehe das Tutorial – Benutzerhandbuch. -**Spoiler-Alarm**: Das Tutorial - Benutzerhandbuch enthält: +**Spoiler-Alarm**: Das Tutorial – Benutzerhandbuch enthält: -* Deklaration von **Parametern** von anderen verschiedenen Stellen wie: **Header-Felder**, **Cookies**, **Formularfelder** und **Dateien**. -* Wie man **Validierungseinschränkungen** wie `maximum_length` oder `regex` setzt. +* Deklaration von **Parametern** von anderen verschiedenen Stellen wie: **Header**, **Cookies**, **Formularfelder** und **Dateien**. +* Wie man **Validierungs-Constraints** wie `maximum_length` oder `regex` setzt. * Ein sehr leistungsfähiges und einfach zu bedienendes System für **Dependency Injection**. -* Sicherheit und Authentifizierung, einschließlich Unterstützung für **OAuth2** mit **JWT-Tokens** und **HTTP-Basic**-Authentifizierung. +* Sicherheit und Authentifizierung, einschließlich Unterstützung für **OAuth2** mit **JWT-Tokens** und **HTTP Basic** Authentifizierung. * Fortgeschrittenere (aber ebenso einfache) Techniken zur Deklaration **tief verschachtelter JSON-Modelle** (dank Pydantic). -* **GraphQL** Integration mit Strawberry und anderen Bibliotheken. -* Viele zusätzliche Funktionen (dank Starlette) wie: +* **GraphQL**-Integration mit Strawberry und anderen Bibliotheken. +* Viele zusätzliche Features (dank Starlette) wie: * **WebSockets** - * extrem einfache Tests auf Basis von `httpx` und `pytest` + * extrem einfache Tests auf Basis von HTTPX und `pytest` * **CORS** - * **Cookie Sessions** + * **Cookie-Sessions** * ... und mehr. -## Performanz +## Performanz { #performance } -Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn laufen, als eines der schnellsten verfügbaren Python-Frameworks, nur noch hinter Starlette und Uvicorn selbst (intern von FastAPI verwendet). +Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn laufen, als eines der schnellsten verfügbaren Python-Frameworks, nur hinter Starlette und Uvicorn selbst (intern von FastAPI verwendet). (*) -Um mehr darüber zu erfahren, siehe den Abschnitt Benchmarks. +Um mehr darüber zu erfahren, siehe den Abschnitt Benchmarks. -## Optionale Abhängigkeiten +## Abhängigkeiten { #dependencies } -Wird von Pydantic verwendet: +FastAPI hängt von Pydantic und Starlette ab. -* email-validator - für E-Mail-Validierung. -* pydantic-settings - für die Verwaltung von Einstellungen. -* pydantic-extra-types - für zusätzliche Typen, mit Pydantic zu verwenden. +### `standard`-Abhängigkeiten { #standard-dependencies } -Wird von Starlette verwendet: +Wenn Sie FastAPI mit `pip install "fastapi[standard]"` installieren, kommt es mit der `standard`-Gruppe optionaler Abhängigkeiten: -* httpx - erforderlich, wenn Sie den `TestClient` verwenden möchten. -* jinja2 - erforderlich, wenn Sie die Standardkonfiguration für Templates verwenden möchten. -* python-multipart - erforderlich, wenn Sie Formulare mittels `request.form()` „parsen“ möchten. -* itsdangerous - erforderlich für `SessionMiddleware` Unterstützung. -* pyyaml - erforderlich für Starlette's `SchemaGenerator` Unterstützung (Sie brauchen das wahrscheinlich nicht mit FastAPI). -* ujson - erforderlich, wenn Sie `UJSONResponse` verwenden möchten. +Verwendet von Pydantic: -Wird von FastAPI / Starlette verwendet: +* email-validator – für E-Mail-Validierung. -* uvicorn - für den Server, der Ihre Anwendung lädt und serviert. -* orjson - erforderlich, wenn Sie `ORJSONResponse` verwenden möchten. +Verwendet von Starlette: -Sie können diese alle mit `pip install "fastapi[all]"` installieren. +* httpx – erforderlich, wenn Sie den `TestClient` verwenden möchten. +* jinja2 – erforderlich, wenn Sie die Default-Template-Konfiguration verwenden möchten. +* python-multipart – erforderlich, wenn Sie Formulare mittels `request.form()` „parsen“ möchten. -## Lizenz +Verwendet von FastAPI: + +* uvicorn – für den Server, der Ihre Anwendung lädt und bereitstellt. Dies umfasst `uvicorn[standard]`, das einige Abhängigkeiten (z. B. `uvloop`) beinhaltet, die für eine Bereitstellung mit hoher Performanz benötigt werden. +* `fastapi-cli[standard]` – um den `fastapi`-Befehl bereitzustellen. + * Dies beinhaltet `fastapi-cloud-cli`, das es Ihnen ermöglicht, Ihre FastAPI-Anwendung auf FastAPI Cloud bereitzustellen. + +### Ohne `standard`-Abhängigkeiten { #without-standard-dependencies } + +Wenn Sie die `standard` optionalen Abhängigkeiten nicht einschließen möchten, können Sie mit `pip install fastapi` statt `pip install "fastapi[standard]"` installieren. + +### Ohne `fastapi-cloud-cli` { #without-fastapi-cloud-cli } + +Wenn Sie FastAPI mit den Standardabhängigkeiten, aber ohne das `fastapi-cloud-cli` installieren möchten, können Sie mit `pip install "fastapi[standard-no-fastapi-cloud-cli]"` installieren. + +### Zusätzliche optionale Abhängigkeiten { #additional-optional-dependencies } + +Es gibt einige zusätzliche Abhängigkeiten, die Sie installieren möchten. + +Zusätzliche optionale Pydantic-Abhängigkeiten: + +* pydantic-settings – für die Verwaltung von Einstellungen. +* pydantic-extra-types – für zusätzliche Typen zur Verwendung mit Pydantic. + +Zusätzliche optionale FastAPI-Abhängigkeiten: + +* orjson – erforderlich, wenn Sie `ORJSONResponse` verwenden möchten. +* ujson – erforderlich, wenn Sie `UJSONResponse` verwenden möchten. + +## Lizenz { #license } Dieses Projekt ist unter den Bedingungen der MIT-Lizenz lizenziert. diff --git a/docs/de/docs/learn/index.md b/docs/de/docs/learn/index.md index b5582f55b..e1f583fb3 100644 --- a/docs/de/docs/learn/index.md +++ b/docs/de/docs/learn/index.md @@ -1,5 +1,5 @@ -# Lernen +# Lernen { #learn } -Hier finden Sie die einführenden Kapitel und Tutorials zum Erlernen von **FastAPI**. +Hier sind die einführenden Abschnitte und Tutorials, um **FastAPI** zu lernen. Sie könnten dies als **Buch**, als **Kurs**, als **offizielle** und empfohlene Methode zum Erlernen von FastAPI betrachten. 😎 diff --git a/docs/de/docs/project-generation.md b/docs/de/docs/project-generation.md index c47bcb6d3..e6da4949c 100644 --- a/docs/de/docs/project-generation.md +++ b/docs/de/docs/project-generation.md @@ -1,84 +1,28 @@ -# Projektgenerierung – Vorlage +# Full Stack FastAPI Template { #full-stack-fastapi-template } -Sie können einen Projektgenerator für den Einstieg verwenden, welcher einen Großteil der Ersteinrichtung, Sicherheit, Datenbank und einige API-Endpunkte bereits für Sie erstellt. +Vorlagen, die normalerweise mit einem bestimmten Setup geliefert werden, sind so konzipiert, dass sie flexibel und anpassbar sind. Dies ermöglicht es Ihnen, sie zu ändern und an die Anforderungen Ihres Projekts anzupassen und sie somit zu einem hervorragenden Ausgangspunkt zu machen. 🏁 -Ein Projektgenerator verfügt immer über ein sehr spezifisches Setup, das Sie aktualisieren und an Ihre eigenen Bedürfnisse anpassen sollten, aber es könnte ein guter Ausgangspunkt für Ihr Projekt sein. +Sie können diese Vorlage verwenden, um loszulegen, da sie bereits vieles der anfänglichen Einrichtung, Sicherheit, Datenbank und einige API-Endpunkte für Sie eingerichtet hat. -## Full Stack FastAPI PostgreSQL +GitHub-Repository: Full Stack FastAPI Template -GitHub: https://github.com/tiangolo/full-stack-fastapi-postgresql +## Full Stack FastAPI Template – Technologiestack und Funktionen { #full-stack-fastapi-template-technology-stack-and-features } -### Full Stack FastAPI PostgreSQL – Funktionen - -* Vollständige **Docker**-Integration (Docker-basiert). -* Docker-Schwarmmodus-Deployment. -* **Docker Compose**-Integration und Optimierung für die lokale Entwicklung. -* **Produktionsbereit** Python-Webserver, verwendet Uvicorn und Gunicorn. -* Python **FastAPI**-Backend: - * **Schnell**: Sehr hohe Leistung, auf Augenhöhe mit **NodeJS** und **Go** (dank Starlette und Pydantic). - * **Intuitiv**: Hervorragende Editor-Unterstützung. Codevervollständigung überall. Weniger Zeitaufwand für das Debuggen. - * **Einfach**: Einfach zu bedienen und zu erlernen. Weniger Zeit für das Lesen von Dokumentationen. - * **Kurz**: Codeverdoppelung minimieren. Mehrere Funktionalitäten aus jeder Parameterdeklaration. - * **Robust**: Erhalten Sie produktionsbereiten Code. Mit automatischer, interaktiver Dokumentation. - * **Standards-basiert**: Basierend auf (und vollständig kompatibel mit) den offenen Standards für APIs: OpenAPI und JSON Schema. - * **Viele weitere Funktionen**, einschließlich automatischer Validierung, Serialisierung, interaktiver Dokumentation, Authentifizierung mit OAuth2-JWT-Tokens, usw. -* **Sicheres Passwort**-Hashing standardmäßig. -* **JWT-Token**-Authentifizierung. -* **SQLAlchemy**-Modelle (unabhängig von Flask-Erweiterungen, sodass sie direkt mit Celery-Workern verwendet werden können). -* Grundlegende Startmodelle für Benutzer (ändern und entfernen Sie nach Bedarf). -* **Alembic**-Migrationen. -* **CORS** (Cross Origin Resource Sharing). -* **Celery**-Worker, welche Modelle und Code aus dem Rest des Backends selektiv importieren und verwenden können. -* REST-Backend-Tests basierend auf **Pytest**, integriert in Docker, sodass Sie die vollständige API-Interaktion unabhängig von der Datenbank testen können. Da es in Docker ausgeführt wird, kann jedes Mal ein neuer Datenspeicher von Grund auf erstellt werden (Sie können also ElasticSearch, MongoDB, CouchDB oder was auch immer Sie möchten verwenden und einfach testen, ob die API funktioniert). -* Einfache Python-Integration mit **Jupyter-Kerneln** für Remote- oder In-Docker-Entwicklung mit Erweiterungen wie Atom Hydrogen oder Visual Studio Code Jupyter. -* **Vue**-Frontend: - * Mit Vue CLI generiert. - * Handhabung der **JWT-Authentifizierung**. - * Login-View. - * Nach der Anmeldung Hauptansicht des Dashboards. - * Haupt-Dashboard mit Benutzererstellung und -bearbeitung. - * Bearbeitung des eigenen Benutzers. - * **Vuex**. - * **Vue-Router**. - * **Vuetify** für schöne Material-Designkomponenten. - * **TypeScript**. - * Docker-Server basierend auf **Nginx** (konfiguriert, um gut mit Vue-Router zu funktionieren). - * Mehrstufigen Docker-Erstellung, sodass Sie kompilierten Code nicht speichern oder committen müssen. - * Frontend-Tests, welche zur Erstellungszeit ausgeführt werden (können auch deaktiviert werden). - * So modular wie möglich gestaltet, sodass es sofort einsatzbereit ist. Sie können es aber mit Vue CLI neu generieren oder es so wie Sie möchten erstellen und wiederverwenden, was Sie möchten. -* **PGAdmin** für die PostgreSQL-Datenbank, können Sie problemlos ändern, sodass PHPMyAdmin und MySQL verwendet wird. -* **Flower** für die Überwachung von Celery-Jobs. -* Load Balancing zwischen Frontend und Backend mit **Traefik**, sodass Sie beide unter derselben Domain haben können, getrennt durch den Pfad, aber von unterschiedlichen Containern ausgeliefert. -* Traefik-Integration, einschließlich automatischer Generierung von Let's Encrypt-**HTTPS**-Zertifikaten. -* GitLab **CI** (kontinuierliche Integration), einschließlich Frontend- und Backend-Testen. - -## Full Stack FastAPI Couchbase - -GitHub: https://github.com/tiangolo/full-stack-fastapi-couchbase - -⚠️ **WARNUNG** ⚠️ - -Wenn Sie ein neues Projekt von Grund auf starten, prüfen Sie die Alternativen hier. - -Zum Beispiel könnte der Projektgenerator Full Stack FastAPI PostgreSQL eine bessere Alternative sein, da er aktiv gepflegt und genutzt wird. Und er enthält alle neuen Funktionen und Verbesserungen. - -Es steht Ihnen weiterhin frei, den Couchbase-basierten Generator zu verwenden, wenn Sie möchten. Er sollte wahrscheinlich immer noch gut funktionieren, und wenn Sie bereits ein Projekt damit erstellt haben, ist das auch in Ordnung (und Sie haben es wahrscheinlich bereits an Ihre Bedürfnisse angepasst). - -Weitere Informationen hierzu finden Sie in der Dokumentation des Repos. - -## Full Stack FastAPI MongoDB - -... könnte später kommen, abhängig von meiner verfügbaren Zeit und anderen Faktoren. 😅 🎉 - -## Modelle für maschinelles Lernen mit spaCy und FastAPI - -GitHub: https://github.com/microsoft/cookiecutter-spacy-fastapi - -### Modelle für maschinelles Lernen mit spaCy und FastAPI – Funktionen - -* **spaCy** NER-Modellintegration. -* **Azure Cognitive Search**-Anforderungsformat integriert. -* **Produktionsbereit** Python-Webserver, verwendet Uvicorn und Gunicorn. -* **Azure DevOps** Kubernetes (AKS) CI/CD-Deployment integriert. -* **Mehrsprachig** Wählen Sie bei der Projekteinrichtung ganz einfach eine der integrierten Sprachen von spaCy aus. -* **Einfach erweiterbar** auf andere Modellframeworks (Pytorch, Tensorflow), nicht nur auf SpaCy. +- ⚡ [**FastAPI**](https://fastapi.tiangolo.com/de) für die Python-Backend-API. + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) für die Interaktion mit der Python-SQL-Datenbank (ORM). + - 🔍 [Pydantic](https://docs.pydantic.dev), verwendet von FastAPI, für die Datenvalidierung und das Einstellungsmanagement. + - 💾 [PostgreSQL](https://www.postgresql.org) als SQL-Datenbank. +- 🚀 [React](https://react.dev) für das Frontend. + - 💃 Verwendung von TypeScript, Hooks, [Vite](https://vitejs.dev) und anderen Teilen eines modernen Frontend-Stacks. + - 🎨 [Chakra UI](https://chakra-ui.com) für die Frontend-Komponenten. + - 🤖 Ein automatisch generierter Frontend-Client. + - 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests. + - 🦇 Unterstützung des Dunkelmodus. +- 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion. +- 🔒 Sicheres Passwort-Hashing standardmäßig. +- 🔑 JWT-Token-Authentifizierung. +- 📫 E-Mail-basierte Passwortwiederherstellung. +- ✅ Tests mit [Pytest](https://pytest.org). +- 📞 [Traefik](https://traefik.io) als Reverse-Proxy / Load Balancer. +- 🚢 Deployment-Anleitungen unter Verwendung von Docker Compose, einschließlich der Einrichtung eines Frontend-Traefik-Proxys zur Handhabung automatischer HTTPS-Zertifikate. +- 🏭 CI (kontinuierliche Integration) und CD (kontinuierliche Bereitstellung) basierend auf GitHub Actions. diff --git a/docs/de/docs/python-types.md b/docs/de/docs/python-types.md index 81d43bc5b..317ee4e62 100644 --- a/docs/de/docs/python-types.md +++ b/docs/de/docs/python-types.md @@ -1,8 +1,8 @@ -# Einführung in Python-Typen +# Einführung in Python-Typen { #python-types-intro } -Python hat Unterstützung für optionale „Typhinweise“ (Englisch: „Type Hints“). Auch „Typ Annotationen“ genannt. +Python hat Unterstützung für optionale „Typhinweise“ (auch „Typannotationen“ genannt). -Diese **„Typhinweise“** oder -Annotationen sind eine spezielle Syntax, die es erlaubt, den Typ einer Variablen zu deklarieren. +Diese **„Typhinweise“** oder -Annotationen sind eine spezielle Syntax, die es erlaubt, den Typ einer Variablen zu deklarieren. Durch das Deklarieren von Typen für Ihre Variablen können Editoren und Tools bessere Unterstützung bieten. @@ -18,7 +18,7 @@ Wenn Sie ein Python-Experte sind und bereits alles über Typhinweise wissen, üb /// -## Motivation +## Motivation { #motivation } Fangen wir mit einem einfachen Beispiel an: @@ -38,7 +38,7 @@ Die Funktion macht Folgendes: {* ../../docs_src/python_types/tutorial001.py hl[2] *} -### Bearbeiten Sie es +### Es bearbeiten { #edit-it } Es ist ein sehr einfaches Programm. @@ -58,7 +58,7 @@ Aber leider erhalten Sie nichts Nützliches: -### Typen hinzufügen +### Typen hinzufügen { #add-types } Lassen Sie uns eine einzelne Zeile aus der vorherigen Version ändern. @@ -102,7 +102,7 @@ Hier können Sie durch die Optionen blättern, bis Sie diejenige finden, bei der -## Mehr Motivation +## Mehr Motivation { #more-motivation } Sehen Sie sich diese Funktion an, sie hat bereits Typhinweise: @@ -116,13 +116,13 @@ Jetzt, da Sie wissen, dass Sie das reparieren müssen, konvertieren Sie `age` mi {* ../../docs_src/python_types/tutorial004.py hl[2] *} -## Deklarieren von Typen +## Deklarieren von Typen { #declaring-types } Sie haben gerade den Haupt-Einsatzort für die Deklaration von Typhinweisen gesehen. Als Funktionsparameter. Das ist auch meistens, wie sie in **FastAPI** verwendet werden. -### Einfache Typen +### Einfache Typen { #simple-types } Sie können alle Standard-Python-Typen deklarieren, nicht nur `str`. @@ -135,7 +135,7 @@ Zum Beispiel diese: {* ../../docs_src/python_types/tutorial005.py hl[1] *} -### Generische Typen mit Typ-Parametern +### Generische Typen mit Typ-Parametern { #generic-types-with-type-parameters } Es gibt Datenstrukturen, die andere Werte enthalten können, wie etwa `dict`, `list`, `set` und `tuple`. Die inneren Werte können auch ihren eigenen Typ haben. @@ -143,7 +143,7 @@ Diese Typen mit inneren Typen werden „**generische**“ Typen genannt. Es ist Um diese Typen und die inneren Typen zu deklarieren, können Sie Pythons Standardmodul `typing` verwenden. Es existiert speziell für die Unterstützung dieser Typhinweise. -#### Neuere Python-Versionen +#### Neuere Python-Versionen { #newer-versions-of-python } Die Syntax, welche `typing` verwendet, ist **kompatibel** mit allen Versionen, von Python 3.6 aufwärts zu den neuesten, inklusive Python 3.9, Python 3.10, usw. @@ -157,7 +157,7 @@ Zum Beispiel bedeutet „**Python 3.6+**“, dass das Beispiel kompatibel mit Py Wenn Sie über die **neueste Version von Python** verfügen, verwenden Sie die Beispiele für die neueste Version, diese werden die **beste und einfachste Syntax** haben, zum Beispiel, „**Python 3.10+**“. -#### Liste +#### Liste { #list } Definieren wir zum Beispiel eine Variable, die eine `list` von `str` – eine Liste von Strings – sein soll. @@ -195,7 +195,7 @@ Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckige //// -/// tip | Tipp +/// info | Info Die inneren Typen in den eckigen Klammern werden als „Typ-Parameter“ bezeichnet. @@ -221,7 +221,7 @@ Beachten Sie, dass die Variable `item` eines der Elemente in der Liste `items` i Und trotzdem weiß der Editor, dass es sich um ein `str` handelt, und bietet entsprechende Unterstützung. -#### Tupel und Menge +#### Tupel und Menge { #tuple-and-set } Das Gleiche gilt für die Deklaration eines Tupels – `tuple` – und einer Menge – `set`: @@ -246,7 +246,7 @@ Das bedeutet: * Die Variable `items_t` ist ein `tuple` mit 3 Elementen, einem `int`, einem weiteren `int` und einem `str`. * Die Variable `items_s` ist ein `set`, und jedes seiner Elemente ist vom Typ `bytes`. -#### Dict +#### Dict { #dict } Um ein `dict` zu definieren, übergeben Sie zwei Typ-Parameter, getrennt durch Kommas. @@ -276,7 +276,7 @@ Das bedeutet: * Die Schlüssel dieses `dict` sind vom Typ `str` (z. B. die Namen der einzelnen Artikel). * Die Werte dieses `dict` sind vom Typ `float` (z. B. der Preis jedes Artikels). -#### Union +#### Union { #union } Sie können deklarieren, dass eine Variable einer von **verschiedenen Typen** sein kann, zum Beispiel ein `int` oder ein `str`. @@ -302,13 +302,15 @@ In Python 3.10 gibt es zusätzlich eine **neue Syntax**, die es erlaubt, die mö In beiden Fällen bedeutet das, dass `item` ein `int` oder ein `str` sein kann. -#### Vielleicht `None` +#### Vielleicht `None` { #possibly-none } Sie können deklarieren, dass ein Wert ein `str`, aber vielleicht auch `None` sein kann. In Python 3.6 und darüber (inklusive Python 3.10) können Sie das deklarieren, indem Sie `Optional` vom `typing` Modul importieren und verwenden. -{* ../../docs_src/python_types/tutorial009.py hl[1,4] *} +```Python hl_lines="1 4" +{!../../docs_src/python_types/tutorial009.py!} +``` Wenn Sie `Optional[str]` anstelle von nur `str` verwenden, wird Ihr Editor Ihnen dabei helfen, Fehler zu erkennen, bei denen Sie annehmen könnten, dass ein Wert immer eine String (`str`) ist, obwohl er auch `None` sein könnte. @@ -340,7 +342,7 @@ Das bedeutet auch, dass Sie in Python 3.10 `Something | None` verwenden können: //// -#### `Union` oder `Optional` verwenden? +#### `Union` oder `Optional` verwenden? { #using-union-or-optional } Wenn Sie eine Python-Version unterhalb 3.10 verwenden, hier ist mein sehr **subjektiver** Standpunkt dazu: @@ -366,7 +368,7 @@ say_hi() # Oh, nein, das löst einen Fehler aus! 😱 Der `name` Parameter wird **immer noch benötigt** (nicht *optional*), weil er keinen Default-Wert hat. `name` akzeptiert aber dennoch `None` als Wert: ```Python -say_hi(name=None) # Das funktioniert, None is gültig 🎉 +say_hi(name=None) # Das funktioniert, None ist gültig 🎉 ``` Die gute Nachricht ist, dass Sie sich darüber keine Sorgen mehr machen müssen, wenn Sie Python 3.10 verwenden, da Sie einfach `|` verwenden können, um Vereinigungen von Typen zu definieren: @@ -375,7 +377,7 @@ Die gute Nachricht ist, dass Sie sich darüber keine Sorgen mehr machen müssen, Und dann müssen Sie sich nicht mehr um Namen wie `Optional` und `Union` kümmern. 😎 -#### Generische Typen +#### Generische Typen { #generic-types } Diese Typen, die Typ-Parameter in eckigen Klammern akzeptieren, werden **generische Typen** oder **Generics** genannt. @@ -427,7 +429,7 @@ Verwenden Sie für den Rest, wie unter Python 3.8, das `typing`-Modul: //// -### Klassen als Typen +### Klassen als Typen { #classes-as-types } Sie können auch eine Klasse als Typ einer Variablen deklarieren. @@ -447,9 +449,9 @@ Beachten Sie, das bedeutet: „`one_person` ist eine **Instanz** der Klasse `Per Es bedeutet nicht: „`one_person` ist die **Klasse** genannt `Person`“. -## Pydantic Modelle +## Pydantic-Modelle { #pydantic-models } -Pydantic ist eine Python-Bibliothek für die Validierung von Daten. +Pydantic ist eine Python-Bibliothek für die Validierung von Daten. Sie deklarieren die „Form“ der Daten als Klassen mit Attributen. @@ -485,25 +487,25 @@ Ein Beispiel aus der offiziellen Pydantic Dokumentation: //// -/// info +/// info | Info -Um mehr über Pydantic zu erfahren, schauen Sie sich dessen Dokumentation an. +Um mehr über Pydantic zu erfahren, schauen Sie sich dessen Dokumentation an. /// **FastAPI** basiert vollständig auf Pydantic. -Viel mehr von all dem werden Sie in praktischer Anwendung im [Tutorial - Benutzerhandbuch](tutorial/index.md){.internal-link target=_blank} sehen. +Viel mehr von all dem werden Sie in praktischer Anwendung im [Tutorial – Benutzerhandbuch](tutorial/index.md){.internal-link target=_blank} sehen. /// tip | Tipp -Pydantic verhält sich speziell, wenn Sie `Optional` oder `Union[Etwas, None]` ohne einen Default-Wert verwenden. Sie können darüber in der Pydantic Dokumentation unter Required fields mehr erfahren. +Pydantic verhält sich speziell, wenn Sie `Optional` oder `Union[Something, None]` ohne einen Defaultwert verwenden. Sie können darüber in der Pydantic Dokumentation unter Erforderliche optionale Felder mehr erfahren. /// -## Typhinweise mit Metadaten-Annotationen +## Typhinweise mit Metadaten-Annotationen { #type-hints-with-metadata-annotations } -Python bietet auch die Möglichkeit, **zusätzliche Metadaten** in Typhinweisen unterzubringen, mittels `Annotated`. +Python bietet auch die Möglichkeit, **zusätzliche Metadaten** in Typhinweisen unterzubringen, mittels `Annotated`. //// tab | Python 3.9+ @@ -529,7 +531,7 @@ Es wird bereits mit **FastAPI** installiert sein. Python selbst macht nichts mit `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`. -Aber Sie können `Annotated` nutzen, um **FastAPI** mit Metadaten zu versorgen, die ihm sagen, wie sich ihre Anwendung verhalten soll. +Aber Sie können `Annotated` nutzen, um **FastAPI** mit Metadaten zu versorgen, die ihm sagen, wie sich Ihre Anwendung verhalten soll. Wichtig ist, dass **der erste *Typ-Parameter***, den Sie `Annotated` übergeben, der **tatsächliche Typ** ist. Der Rest sind Metadaten für andere Tools. @@ -539,13 +541,13 @@ Später werden Sie sehen, wie **mächtig** es sein kann. /// tip | Tipp -Der Umstand, dass es **Standard-Python** ist, bedeutet, dass Sie immer noch die **bestmögliche Entwickler-Erfahrung** in ihrem Editor haben, sowie mit den Tools, die Sie nutzen, um ihren Code zu analysieren, zu refaktorisieren, usw. ✨ +Der Umstand, dass es **Standard-Python** ist, bedeutet, dass Sie immer noch die **bestmögliche Entwickler-Erfahrung** in Ihrem Editor haben, sowie mit den Tools, die Sie nutzen, um Ihren Code zu analysieren, zu refaktorisieren, usw. ✨ Und ebenfalls, dass Ihr Code sehr kompatibel mit vielen anderen Python-Tools und -Bibliotheken sein wird. 🚀 /// -## Typhinweise in **FastAPI** +## Typhinweise in **FastAPI** { #type-hints-in-fastapi } **FastAPI** macht sich diese Typhinweise zunutze, um mehrere Dinge zu tun. @@ -556,18 +558,18 @@ Mit **FastAPI** deklarieren Sie Parameter mit Typhinweisen, und Sie erhalten: ... und **FastAPI** verwendet dieselben Deklarationen, um: -* **Anforderungen** zu definieren: aus Anfrage-Pfadparametern, Abfrageparametern, Header-Feldern, Bodys, Abhängigkeiten, usw. -* **Daten umzuwandeln**: aus der Anfrage in den erforderlichen Typ. -* **Daten zu validieren**: aus jeder Anfrage: +* **Anforderungen** zu definieren: aus Request-Pfadparametern, Query-Parametern, Header-Feldern, Bodys, Abhängigkeiten, usw. +* **Daten umzuwandeln**: aus dem Request in den erforderlichen Typ. +* **Daten zu validieren**: aus jedem Request: * **Automatische Fehler** generieren, die an den Client zurückgegeben werden, wenn die Daten ungültig sind. * Die API mit OpenAPI zu **dokumentieren**: * Die dann von den Benutzeroberflächen der automatisch generierten interaktiven Dokumentation verwendet wird. -Das mag alles abstrakt klingen. Machen Sie sich keine Sorgen. Sie werden all das in Aktion sehen im [Tutorial - Benutzerhandbuch](tutorial/index.md){.internal-link target=_blank}. +Das mag alles abstrakt klingen. Machen Sie sich keine Sorgen. Sie werden all das in Aktion sehen im [Tutorial – Benutzerhandbuch](tutorial/index.md){.internal-link target=_blank}. Das Wichtigste ist, dass **FastAPI** durch die Verwendung von Standard-Python-Typen an einer einzigen Stelle (anstatt weitere Klassen, Dekoratoren usw. hinzuzufügen) einen Großteil der Arbeit für Sie erledigt. -/// info +/// info | Info Wenn Sie bereits das ganze Tutorial durchgearbeitet haben und mehr über Typen erfahren wollen, dann ist eine gute Ressource der „Cheat Sheet“ von `mypy`. diff --git a/docs/de/docs/resources/index.md b/docs/de/docs/resources/index.md index abf270d9f..2c5046c73 100644 --- a/docs/de/docs/resources/index.md +++ b/docs/de/docs/resources/index.md @@ -1,3 +1,3 @@ -# Ressourcen +# Ressourcen { #resources } Zusätzliche Ressourcen, externe Links, Artikel und mehr. ✈️ diff --git a/docs/de/docs/tutorial/background-tasks.md b/docs/de/docs/tutorial/background-tasks.md index 05779e12c..ea85207ce 100644 --- a/docs/de/docs/tutorial/background-tasks.md +++ b/docs/de/docs/tutorial/background-tasks.md @@ -1,8 +1,8 @@ -# Hintergrundtasks +# Hintergrundtasks { #background-tasks } -Sie können Hintergrundtasks (Hintergrund-Aufgaben) definieren, die *nach* der Rückgabe einer Response ausgeführt werden sollen. +Sie können Hintergrundtasks definieren, die *nach* der Rückgabe einer Response ausgeführt werden sollen. -Das ist nützlich für Vorgänge, die nach einem Request ausgeführt werden müssen, bei denen der Client jedoch nicht unbedingt auf den Abschluss des Vorgangs warten muss, bevor er die Response erhält. +Das ist nützlich für Vorgänge, die nach einem Request ausgeführt werden müssen, bei denen der Client jedoch nicht unbedingt auf den Abschluss des Vorgangs warten muss, bevor er die Response erhält. Hierzu zählen beispielsweise: @@ -11,7 +11,7 @@ Hierzu zählen beispielsweise: * Daten verarbeiten: * Angenommen, Sie erhalten eine Datei, die einen langsamen Prozess durchlaufen muss. Sie können als Response „Accepted“ (HTTP 202) zurückgeben und die Datei im Hintergrund verarbeiten. -## `BackgroundTasks` verwenden +## `BackgroundTasks` verwenden { #using-backgroundtasks } Importieren Sie zunächst `BackgroundTasks` und definieren Sie einen Parameter in Ihrer *Pfadoperation-Funktion* mit der Typdeklaration `BackgroundTasks`: @@ -19,7 +19,7 @@ Importieren Sie zunächst `BackgroundTasks` und definieren Sie einen Parameter i **FastAPI** erstellt für Sie das Objekt vom Typ `BackgroundTasks` und übergibt es als diesen Parameter. -## Eine Taskfunktion erstellen +## Eine Taskfunktion erstellen { #create-a-task-function } Erstellen Sie eine Funktion, die als Hintergrundtask ausgeführt werden soll. @@ -33,7 +33,7 @@ Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir di {* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *} -## Den Hintergrundtask hinzufügen +## Den Hintergrundtask hinzufügen { #add-the-background-task } Übergeben Sie innerhalb Ihrer *Pfadoperation-Funktion* Ihre Taskfunktion mit der Methode `.add_task()` an das *Hintergrundtasks*-Objekt: @@ -45,21 +45,23 @@ Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir di * Eine beliebige Folge von Argumenten, die der Reihe nach an die Taskfunktion übergeben werden sollen (`email`). * Alle Schlüsselwort-Argumente, die an die Taskfunktion übergeben werden sollen (`message="some notification"`). -## Dependency Injection +## Dependency Injection { #dependency-injection } Die Verwendung von `BackgroundTasks` funktioniert auch mit dem Dependency Injection System. Sie können einen Parameter vom Typ `BackgroundTasks` auf mehreren Ebenen deklarieren: in einer *Pfadoperation-Funktion*, in einer Abhängigkeit (Dependable), in einer Unterabhängigkeit usw. **FastAPI** weiß, was jeweils zu tun ist und wie dasselbe Objekt wiederverwendet werden kann, sodass alle Hintergrundtasks zusammengeführt und anschließend im Hintergrund ausgeführt werden: + {* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + In obigem Beispiel werden die Nachrichten, *nachdem* die Response gesendet wurde, in die Datei `log.txt` geschrieben. Wenn im Request ein Query-Parameter enthalten war, wird dieser in einem Hintergrundtask in das Log geschrieben. Und dann schreibt ein weiterer Hintergrundtask, der in der *Pfadoperation-Funktion* erstellt wird, eine Nachricht unter Verwendung des Pfad-Parameters `email`. -## Technische Details +## Technische Details { #technical-details } Die Klasse `BackgroundTasks` stammt direkt von `starlette.background`. @@ -69,16 +71,16 @@ Indem Sie nur `BackgroundTasks` (und nicht `BackgroundTask`) verwenden, ist es d Es ist immer noch möglich, `BackgroundTask` allein in FastAPI zu verwenden, aber Sie müssen das Objekt in Ihrem Code erstellen und eine Starlette-`Response` zurückgeben, die es enthält. -Weitere Details finden Sie in der offiziellen Starlette-Dokumentation für Hintergrundtasks. +Weitere Details finden Sie in Starlettes offizieller Dokumentation für Hintergrundtasks. -## Vorbehalt +## Vorbehalt { #caveat } Wenn Sie umfangreiche Hintergrundberechnungen durchführen müssen und diese nicht unbedingt vom selben Prozess ausgeführt werden müssen (z. B. müssen Sie Speicher, Variablen, usw. nicht gemeinsam nutzen), könnte die Verwendung anderer größerer Tools wie z. B. Celery von Vorteil sein. Sie erfordern in der Regel komplexere Konfigurationen und einen Nachrichten-/Job-Queue-Manager wie RabbitMQ oder Redis, ermöglichen Ihnen jedoch die Ausführung von Hintergrundtasks in mehreren Prozessen und insbesondere auf mehreren Servern. -Wenn Sie jedoch über dieselbe **FastAPI**-Anwendung auf Variablen und Objekte zugreifen oder kleine Hintergrundtasks ausführen müssen (z. B. das Senden einer E-Mail-Benachrichtigung), können Sie einfach `BackgroundTasks` verwenden. +Wenn Sie jedoch über dieselbe **FastAPI**-App auf Variablen und Objekte zugreifen oder kleine Hintergrundtasks ausführen müssen (z. B. das Senden einer E-Mail-Benachrichtigung), können Sie einfach `BackgroundTasks` verwenden. -## Zusammenfassung +## Zusammenfassung { #recap } Importieren und verwenden Sie `BackgroundTasks` mit Parametern in *Pfadoperation-Funktionen* und Abhängigkeiten, um Hintergrundtasks hinzuzufügen. diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md index 514e3fd3a..928d50adf 100644 --- a/docs/de/docs/tutorial/bigger-applications.md +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -1,16 +1,16 @@ -# Größere Anwendungen – mehrere Dateien +# Größere Anwendungen – mehrere Dateien { #bigger-applications-multiple-files } Wenn Sie eine Anwendung oder eine Web-API erstellen, ist es selten der Fall, dass Sie alles in einer einzigen Datei unterbringen können. **FastAPI** bietet ein praktisches Werkzeug zur Strukturierung Ihrer Anwendung bei gleichzeitiger Wahrung der Flexibilität. -/// info +/// info | Info Wenn Sie von Flask kommen, wäre dies das Äquivalent zu Flasks Blueprints. /// -## Eine Beispiel-Dateistruktur +## Eine Beispiel-Dateistruktur { #an-example-file-structure } Nehmen wir an, Sie haben eine Dateistruktur wie diese: @@ -71,7 +71,7 @@ Die gleiche Dateistruktur mit Kommentaren: │   └── admin.py # „admin“-Submodul, z. B. import app.internal.admin ``` -## `APIRouter` +## `APIRouter` { #apirouter } Nehmen wir an, die Datei, die nur für die Verwaltung von Benutzern zuständig ist, ist das Submodul unter `/app/routers/users.py`. @@ -81,7 +81,7 @@ Aber es ist immer noch Teil derselben **FastAPI**-Anwendung/Web-API (es ist Teil Sie können die *Pfadoperationen* für dieses Modul mit `APIRouter` erstellen. -### `APIRouter` importieren +### `APIRouter` importieren { #import-apirouter } Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie mit der Klasse `FastAPI`: @@ -89,7 +89,7 @@ Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie m {!../../docs_src/bigger_applications/app/routers/users.py!} ``` -### *Pfadoperationen* mit `APIRouter` +### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter } Und dann verwenden Sie ihn, um Ihre *Pfadoperationen* zu deklarieren. @@ -113,7 +113,7 @@ In diesem Beispiel heißt die Variable `router`, aber Sie können ihr einen beli Wir werden diesen `APIRouter` in die Hauptanwendung `FastAPI` einbinden, aber zuerst kümmern wir uns um die Abhängigkeiten und einen anderen `APIRouter`. -## Abhängigkeiten +## Abhängigkeiten { #dependencies } Wir sehen, dass wir einige Abhängigkeiten benötigen, die an mehreren Stellen der Anwendung verwendet werden. @@ -159,7 +159,7 @@ Aber in der Praxis werden Sie mit den integrierten [Sicherheits-Werkzeugen](secu /// -## Ein weiteres Modul mit `APIRouter`. +## Ein weiteres Modul mit `APIRouter` { #another-module-with-apirouter } Nehmen wir an, Sie haben im Modul unter `app/routers/items.py` auch die Endpunkte, die für die Verarbeitung von Artikeln („Items“) aus Ihrer Anwendung vorgesehen sind. @@ -199,7 +199,7 @@ Das Präfix lautet in diesem Fall also `/items`. Wir können auch eine Liste von `tags` und zusätzliche `responses` hinzufügen, die auf alle in diesem Router enthaltenen *Pfadoperationen* angewendet werden. -Und wir können eine Liste von `dependencies` hinzufügen, die allen *Pfadoperationen* im Router hinzugefügt und für jeden an sie gerichteten Request ausgeführt/aufgelöst werden. +Und wir können eine Liste von `dependencies` hinzufügen, die allen *Pfadoperationen* im Router hinzugefügt und für jeden an sie gerichteten Request ausgeführt/aufgelöst werden. /// tip | Tipp @@ -228,13 +228,13 @@ Das Endergebnis ist, dass die Pfade für diese Artikel jetzt wie folgt lauten: /// -/// check +/// check | Testen Die Parameter `prefix`, `tags`, `responses` und `dependencies` sind (wie in vielen anderen Fällen) nur ein Feature von **FastAPI**, um Ihnen dabei zu helfen, Codeverdoppelung zu vermeiden. /// -### Die Abhängigkeiten importieren +### Die Abhängigkeiten importieren { #import-the-dependencies } Der folgende Code befindet sich im Modul `app.routers.items`, also in der Datei `app/routers/items.py`. @@ -246,7 +246,7 @@ Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten: {!../../docs_src/bigger_applications/app/routers/items.py!} ``` -#### Wie relative Importe funktionieren +#### Wie relative Importe funktionieren { #how-relative-imports-work } /// tip | Tipp @@ -309,7 +309,7 @@ Das würde sich auf ein Paket oberhalb von `app/` beziehen, mit seiner eigenen D Aber jetzt wissen Sie, wie es funktioniert, sodass Sie relative Importe in Ihren eigenen Anwendungen verwenden können, egal wie komplex diese sind. 🤓 -### Einige benutzerdefinierte `tags`, `responses`, und `dependencies` hinzufügen +### Einige benutzerdefinierte `tags`, `responses`, und `dependencies` hinzufügen { #add-some-custom-tags-responses-and-dependencies } Wir fügen weder das Präfix `/items` noch `tags=["items"]` zu jeder *Pfadoperation* hinzu, da wir sie zum `APIRouter` hinzugefügt haben. @@ -323,21 +323,21 @@ Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *P Diese letzte Pfadoperation wird eine Kombination von Tags haben: `["items", "custom"]`. -Und sie wird auch beide Responses in der Dokumentation haben, eine für `404` und eine für `403`. +Und sie wird auch beide Responses in der Dokumentation haben, eine für `404` und eine für `403`. /// -## Das Haupt-`FastAPI`. +## Das Haupt-`FastAPI` { #the-main-fastapi } Sehen wir uns nun das Modul unter `app/main.py` an. Hier importieren und verwenden Sie die Klasse `FastAPI`. -Dies ist die Hauptdatei Ihrer Anwendung, die alles zusammen bindet. +Dies ist die Hauptdatei Ihrer Anwendung, die alles zusammenfügt. Und da sich der Großteil Ihrer Logik jetzt in seinem eigenen spezifischen Modul befindet, wird die Hauptdatei recht einfach sein. -### `FastAPI` importieren +### `FastAPI` importieren { #import-fastapi } Sie importieren und erstellen wie gewohnt eine `FastAPI`-Klasse. @@ -347,7 +347,7 @@ Und wir können sogar [globale Abhängigkeiten](dependencies/global-dependencies {!../../docs_src/bigger_applications/app/main.py!} ``` -### Den `APIRouter` importieren +### Den `APIRouter` importieren { #import-the-apirouter } Jetzt importieren wir die anderen Submodule, die `APIRouter` haben: @@ -357,7 +357,7 @@ Jetzt importieren wir die anderen Submodule, die `APIRouter` haben: Da es sich bei den Dateien `app/routers/users.py` und `app/routers/items.py` um Submodule handelt, die Teil desselben Python-Packages `app` sind, können wir einen einzelnen Punkt `.` verwenden, um sie mit „relativen Imports“ zu importieren. -### Wie das Importieren funktioniert +### Wie das Importieren funktioniert { #how-the-importing-works } Die Sektion: @@ -381,7 +381,7 @@ Wir könnten sie auch wie folgt importieren: from app.routers import items, users ``` -/// info +/// info | Info Die erste Version ist ein „relativer Import“: @@ -399,7 +399,7 @@ Um mehr über Python-Packages und -Module zu erfahren, lesen Sie ```console -$ uvicorn app.main:app --reload +$ fastapi dev app/main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` @@ -538,7 +537,7 @@ Sie sehen die automatische API-Dokumentation, einschließlich der Pfade aller Su -## Den gleichen Router mehrmals mit unterschiedlichem `prefix` inkludieren +## Den gleichen Router mehrmals mit unterschiedlichem `prefix` inkludieren { #include-the-same-router-multiple-times-with-different-prefix } Sie können `.include_router()` auch mehrmals mit *demselben* Router und unterschiedlichen Präfixen verwenden. @@ -546,7 +545,7 @@ Dies könnte beispielsweise nützlich sein, um dieselbe API unter verschiedenen Dies ist eine fortgeschrittene Verwendung, die Sie möglicherweise nicht wirklich benötigen, aber für den Fall, dass Sie sie benötigen, ist sie vorhanden. -## Einen `APIRouter` in einen anderen einfügen +## Einen `APIRouter` in einen anderen einfügen { #include-an-apirouter-in-another } Auf die gleiche Weise, wie Sie einen `APIRouter` in eine `FastAPI`-Anwendung einbinden können, können Sie einen `APIRouter` in einen anderen `APIRouter` einbinden, indem Sie Folgendes verwenden: diff --git a/docs/de/docs/tutorial/body-fields.md b/docs/de/docs/tutorial/body-fields.md index 9fddfb1f0..b73d57d2d 100644 --- a/docs/de/docs/tutorial/body-fields.md +++ b/docs/de/docs/tutorial/body-fields.md @@ -1,8 +1,8 @@ -# Body – Felder +# Body – Felder { #body-fields } -So wie Sie zusätzliche Validation und Metadaten in Parametern der **Pfadoperation-Funktion** mittels `Query`, `Path` und `Body` deklarieren, können Sie auch innerhalb von Pydantic-Modellen zusätzliche Validation und Metadaten deklarieren, mittels Pydantics `Field`. +So wie Sie zusätzliche Validierung und Metadaten in Parametern der *Pfadoperation-Funktion* mittels `Query`, `Path` und `Body` deklarieren, können Sie auch innerhalb von Pydantic-Modellen zusätzliche Validierung und Metadaten deklarieren, mittels Pydantics `Field`. -## `Field` importieren +## `Field` importieren { #import-field } Importieren Sie es zuerst: @@ -14,7 +14,7 @@ Beachten Sie, dass `Field` direkt von `pydantic` importiert wird, nicht von `fas /// -## Modellattribute deklarieren +## Modellattribute deklarieren { #declare-model-attributes } Dann können Sie `Field` mit Modellattributen deklarieren: @@ -24,23 +24,23 @@ Dann können Sie `Field` mit Modellattributen deklarieren: /// note | Technische Details -Tatsächlich erstellen `Query`, `Path` und andere, die sie kennenlernen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, die ihrerseits eine Unterklasse von Pydantics `FieldInfo`-Klasse ist. +Tatsächlich erstellen `Query`, `Path` und andere, die Sie als nächstes sehen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, welche selbst eine Unterklasse von Pydantics `FieldInfo`-Klasse ist. Und Pydantics `Field` gibt ebenfalls eine Instanz von `FieldInfo` zurück. -`Body` gibt auch Instanzen einer Unterklasse von `FieldInfo` zurück. Und später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind. +`Body` gibt auch direkt Instanzen einer Unterklasse von `FieldInfo` zurück. Später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind. -Denken Sie daran, dass `Query`, `Path` und andere von `fastapi` tatsächlich Funktionen sind, die spezielle Klassen zurückgeben. +Denken Sie daran, dass `Query`, `Path` und andere, wenn Sie sie von `fastapi` importieren, tatsächlich Funktionen sind, die spezielle Klassen zurückgeben. /// /// tip | Tipp -Beachten Sie, dass jedes Modellattribut mit einem Typ, Defaultwert und `Field` die gleiche Struktur hat wie ein Parameter einer Pfadoperation-Funktion, nur mit `Field` statt `Path`, `Query`, `Body`. +Beachten Sie, wie jedes Attribut eines Modells mit einem Typ, Defaultwert und `Field` die gleiche Struktur hat wie ein Parameter einer *Pfadoperation-Funktion*, nur mit `Field` statt `Path`, `Query`, `Body`. /// -## Zusätzliche Information hinzufügen +## Zusätzliche Information hinzufügen { #add-extra-information } Sie können zusätzliche Information in `Field`, `Query`, `Body`, usw. deklarieren. Und es wird im generierten JSON-Schema untergebracht. @@ -48,12 +48,12 @@ Sie werden später mehr darüber lernen, wie man zusätzliche Information unterb /// warning | Achtung -Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel nicht notwendigerweise Teil der OpenAPI-Spezifikation sind, könnten einige OpenAPI-Tools, wie etwa [der OpenAPI-Validator](https://validator.swagger.io/), nicht mit Ihrem generierten Schema funktionieren. +Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel möglicherweise nicht Teil der OpenAPI-Spezifikation sind, könnten einige OpenAPI-Tools, wie etwa [der OpenAPI-Validator](https://validator.swagger.io/), nicht mit Ihrem generierten Schema funktionieren. /// -## Zusammenfassung +## Zusammenfassung { #recap } Sie können Pydantics `Field` verwenden, um zusätzliche Validierungen und Metadaten für Modellattribute zu deklarieren. -Sie können auch Extra-Schlüssel verwenden, um zusätzliche JSON-Schema-Metadaten zu überreichen. +Sie können auch die zusätzlichen Schlüsselwortargumente verwenden, um zusätzliche JSON-Schema-Metadaten zu übergeben. diff --git a/docs/de/docs/tutorial/body-multiple-params.md b/docs/de/docs/tutorial/body-multiple-params.md index 8a9978d34..3b5fa52dd 100644 --- a/docs/de/docs/tutorial/body-multiple-params.md +++ b/docs/de/docs/tutorial/body-multiple-params.md @@ -1,8 +1,8 @@ -# Body – Mehrere Parameter +# Body – Mehrere Parameter { #body-multiple-parameters } -Jetzt, da wir gesehen haben, wie `Path` und `Query` verwendet werden, schauen wir uns fortgeschrittenere Verwendungsmöglichkeiten von Requestbody-Deklarationen an. +Nun, da wir gesehen haben, wie `Path` und `Query` verwendet werden, schauen wir uns fortgeschrittenere Verwendungsmöglichkeiten von Requestbody-Deklarationen an. -## `Path`-, `Query`- und Body-Parameter vermischen +## `Path`-, `Query`- und Body-Parameter vermischen { #mix-path-query-and-body-parameters } Zuerst einmal, Sie können `Path`-, `Query`- und Requestbody-Parameter-Deklarationen frei mischen und **FastAPI** wird wissen, was zu tun ist. @@ -16,9 +16,9 @@ Beachten Sie, dass in diesem Fall das `item`, welches vom Body genommen wird, op /// -## Mehrere Body-Parameter +## Mehrere Body-Parameter { #multiple-body-parameters } -Im vorherigen Beispiel erwartete die *Pfadoperation* einen JSON-Body mit den Attributen eines `Item`s, etwa: +Im vorherigen Beispiel erwarteten die *Pfadoperationen* einen JSON-Body mit den Attributen eines `Item`s, etwa: ```JSON { @@ -35,7 +35,7 @@ Aber Sie können auch mehrere Body-Parameter deklarieren, z. B. `item` und `user In diesem Fall wird **FastAPI** bemerken, dass es mehr als einen Body-Parameter in der Funktion gibt (zwei Parameter, die Pydantic-Modelle sind). -Es wird deshalb die Parameternamen als Schlüssel (Feldnamen) im Body verwenden, und erwartet einen Body wie folgt: +Es wird deshalb die Parameternamen als Schlüssel (Feldnamen) im Body verwenden und erwartet einen Body wie folgt: ```JSON { @@ -58,17 +58,17 @@ Beachten Sie, dass, obwohl `item` wie zuvor deklariert wurde, es nun unter einem /// -**FastAPI** wird die automatische Konvertierung des Requests übernehmen, sodass der Parameter `item` seinen spezifischen Inhalt bekommt, genau so wie der Parameter `user`. +**FastAPI** wird die automatische Konvertierung des Requests übernehmen, sodass der Parameter `item` seinen spezifischen Inhalt bekommt, und das Gleiche gilt für den Parameter `user`. -Es wird die Validierung dieser zusammengesetzten Daten übernehmen, und sie im OpenAPI-Schema und der automatischen Dokumentation dokumentieren. +Es wird die Validierung dieser zusammengesetzten Daten übernehmen, und diese im OpenAPI-Schema und der automatischen Dokumentation dokumentieren. -## Einzelne Werte im Body +## Einzelne Werte im Body { #singular-values-in-body } -So wie `Query` und `Path` für Query- und Pfad-Parameter, hat **FastAPI** auch das Äquivalent `Body`, um Extra-Daten für Body-Parameter zu definieren. +So wie `Query` und `Path` für Query- und Pfad-Parameter, stellt **FastAPI** das Äquivalent `Body` zur Verfügung, um Extra-Daten für Body-Parameter zu definieren. -Zum Beispiel, das vorherige Modell erweiternd, könnten Sie entscheiden, dass Sie einen weiteren Schlüssel `importance` haben möchten, im selben Body, Seite an Seite mit `item` und `user`. +Zum Beispiel, das vorherige Modell erweiternd, könnten Sie entscheiden, dass Sie einen weiteren Schlüssel `importance` im selben Body haben möchten, neben `item` und `user`. -Wenn Sie diesen Parameter einfach so hinzufügen, wird **FastAPI** annehmen, dass es ein Query-Parameter ist. +Wenn Sie diesen Parameter einfach so hinzufügen, wird **FastAPI** annehmen, dass es ein Query-Parameter ist, da er ein einzelner Wert ist. Aber Sie können **FastAPI** instruieren, ihn als weiteren Body-Schlüssel zu erkennen, indem Sie `Body` verwenden: @@ -92,9 +92,9 @@ In diesem Fall erwartet **FastAPI** einen Body wie: } ``` -Wiederum wird es die Daten konvertieren, validieren, dokumentieren, usw. +Wiederum wird es die Datentypen konvertieren, validieren, dokumentieren, usw. -## Mehrere Body-Parameter und Query-Parameter +## Mehrere Body-Parameter und Query-Parameter { #multiple-body-params-and-query } Natürlich können Sie auch, wann immer Sie das brauchen, weitere Query-Parameter hinzufügen, zusätzlich zu den Body-Parametern. @@ -112,21 +112,21 @@ q: str | None = None Zum Beispiel: -{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[27] *} +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info +/// info | Info -`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query` und `Path` und andere, die Sie später kennenlernen. +`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query`, `Path` und andere, die Sie später kennenlernen werden. /// -## Einen einzelnen Body-Parameter einbetten +## Einen einzelnen Body-Parameter einbetten { #embed-a-single-body-parameter } -Nehmen wir an, Sie haben nur einen einzelnen `item`-Body-Parameter, ein Pydantic-Modell `Item`. +Nehmen wir an, Sie haben nur einen einzelnen `item`-Body-Parameter von einem Pydantic-Modell `Item`. -Normalerweise wird **FastAPI** dann seinen JSON-Body direkt erwarten. +Standardmäßig wird **FastAPI** dann seinen Body direkt erwarten. -Aber wenn Sie möchten, dass es einen JSON-Body erwartet, mit einem Schlüssel `item` und darin den Inhalt des Modells, so wie es das tut, wenn Sie mehrere Body-Parameter deklarieren, dann können Sie den speziellen `Body`-Parameter `embed` setzen: +Aber wenn Sie möchten, dass es einen JSON-Body mit einem Schlüssel `item` erwartet, und darin den Inhalt des Modells, so wie es das tut, wenn Sie mehrere Body-Parameter deklarieren, dann können Sie den speziellen `Body`-Parameter `embed` setzen: ```Python item: Item = Body(embed=True) @@ -160,11 +160,11 @@ statt: } ``` -## Zusammenfassung +## Zusammenfassung { #recap } -Sie können mehrere Body-Parameter zu ihrer *Pfadoperation-Funktion* hinzufügen, obwohl ein Request nur einen einzigen Body enthalten kann. +Sie können mehrere Body-Parameter zu Ihrer *Pfadoperation-Funktion* hinzufügen, obwohl ein Request nur einen einzigen Body enthalten kann. -**FastAPI** wird sich darum kümmern, Ihnen korrekte Daten in Ihrer Funktion zu überreichen, und das korrekte Schema in der *Pfadoperation* zu validieren und zu dokumentieren. +Aber **FastAPI** wird sich darum kümmern, Ihnen korrekte Daten in Ihrer Funktion zu überreichen, und das korrekte Schema in der *Pfadoperation* zu validieren und zu dokumentieren. Sie können auch einzelne Werte deklarieren, die als Teil des Bodys empfangen werden. diff --git a/docs/de/docs/tutorial/body-nested-models.md b/docs/de/docs/tutorial/body-nested-models.md index 6287490c6..324d31928 100644 --- a/docs/de/docs/tutorial/body-nested-models.md +++ b/docs/de/docs/tutorial/body-nested-models.md @@ -1,20 +1,20 @@ -# Body – Verschachtelte Modelle +# Body – Verschachtelte Modelle { #body-nested-models } -Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle definieren, validieren und dokumentieren. +Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle definieren, validieren, dokumentieren und verwenden. -## Listen als Felder +## Listen als Felder { #list-fields } -Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`e. +Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`. {* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der Elemente der Liste aussagt. -## Listen mit Typ-Parametern als Felder +## Listen mit Typ-Parametern als Felder { #list-fields-with-type-parameter } Aber Python erlaubt es, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren. -### `List` von `typing` importieren +### `List` von `typing` importieren { #import-typings-list } In Python 3.9 oder darüber können Sie einfach `list` verwenden, um diese Typannotationen zu deklarieren, wie wir unten sehen werden. 💡 @@ -22,7 +22,7 @@ In Python-Versionen vor 3.9 (3.6 und darüber), müssen Sie zuerst `List` von Py {* ../../docs_src/body_nested_models/tutorial002.py hl[1] *} -### Eine `list`e mit einem Typ-Parameter deklarieren +### Eine `list` mit einem Typ-Parameter deklarieren { #declare-a-list-with-a-type-parameter } Um Typen wie `list`, `dict`, `tuple` mit inneren Typ-Parametern (inneren Typen) zu deklarieren: @@ -51,7 +51,7 @@ In unserem Beispiel können wir also bewirken, dass `tags` spezifisch eine „Li {* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} -## Set-Typen +## Set-Typen { #set-types } Aber dann denken wir darüber nach und stellen fest, dass sich die Tags nicht wiederholen sollen, es sollen eindeutige Strings sein. @@ -61,13 +61,13 @@ Deklarieren wir also `tags` als Set von Strings. {* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} -Jetzt, selbst wenn Sie einen Request mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert. +Jetzt, selbst wenn Sie einen Request mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert. Und wann immer Sie diese Daten ausgeben, selbst wenn die Quelle Duplikate hatte, wird es als Set von eindeutigen Dingen ausgegeben. Und es wird entsprechend annotiert/dokumentiert. -## Verschachtelte Modelle +## Verschachtelte Modelle { #nested-models } Jedes Attribut eines Pydantic-Modells hat einen Typ. @@ -77,19 +77,19 @@ Sie können also tief verschachtelte JSON-„Objekte“ deklarieren, mit spezifi Alles das beliebig tief verschachtelt. -### Ein Kindmodell definieren +### Ein Kindmodell definieren { #define-a-submodel } -Wir können zum Beispiel ein `Image`-Modell definieren. +Für ein Beispiel können wir ein `Image`-Modell definieren. {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} -### Das Kindmodell als Typ verwenden +### Das Kindmodell als Typ verwenden { #use-the-submodel-as-a-type } -Und dann können wir es als Typ eines Attributes verwenden. +Und dann können wir es als Typ eines Attributes verwenden: {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} -Das würde bedeuten, dass **FastAPI** einen Body erwartet wie: +Das würde bedeuten, dass **FastAPI** einen Body wie folgt erwartet: ```JSON { @@ -112,25 +112,25 @@ Wiederum, nur mit dieser Deklaration erhalten Sie von **FastAPI**: * Datenvalidierung * Automatische Dokumentation -## Spezielle Typen und Validierungen +## Spezielle Typen und Validierungen { #special-types-and-validation } -Abgesehen von normalen einfachen Typen, wie `str`, `int`, `float`, usw. können Sie komplexere einfache Typen verwenden, die von `str` erben. +Abgesehen von normalen einfachen Typen wie `str`, `int`, `float`, usw. können Sie komplexere einfache Typen verwenden, die von `str` erben. -Um alle Optionen kennenzulernen, die Sie haben, schauen Sie sich Pydantics Typübersicht an. Sie werden im nächsten Kapitel ein paar Beispiele kennenlernen. +Um alle Optionen kennenzulernen, die Sie haben, schauen Sie sich Pydantics Typübersicht an. Sie werden einige Beispiele im nächsten Kapitel kennenlernen. -Da wir zum Beispiel im `Image`-Modell ein Feld `url` haben, können wir deklarieren, dass das eine Instanz von Pydantics `HttpUrl` sein soll, anstelle eines `str`: +Zum Beispiel, da wir im `Image`-Modell ein Feld `url` haben, können wir deklarieren, dass das eine Instanz von Pydantics `HttpUrl` sein soll, anstelle eines `str`: {* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in JSON Schema / OpenAPI dokumentiert. -## Attribute mit Listen von Kindmodellen +## Attribute mit Listen von Kindmodellen { #attributes-with-lists-of-submodels } Sie können Pydantic-Modelle auch als Typen innerhalb von `list`, `set`, usw. verwenden: {* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} -Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie: +Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren, usw.) wie: ```JSON hl_lines="11" { @@ -156,27 +156,27 @@ Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie } ``` -/// info +/// info | Info Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat. /// -## Tief verschachtelte Modelle +## Tief verschachtelte Modelle { #deeply-nested-models } Sie können beliebig tief verschachtelte Modelle definieren: {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info +/// info | Info -Beachten Sie, wie `Offer` eine Liste von `Item`s hat, von denen jedes seinerseits eine optionale Liste von `Image`s hat. +Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine optionale Liste von `Image`s haben. /// -## Bodys aus reinen Listen +## Bodys aus reinen Listen { #bodies-of-pure-lists } -Wenn Sie möchten, dass das äußerste Element des JSON-Bodys ein JSON-`array` (eine Python-`list`e) ist, können Sie den Typ im Funktionsparameter deklarieren, mit der gleichen Syntax wie in Pydantic-Modellen: +Wenn das äußerste Element des JSON-Bodys, das Sie erwarten, ein JSON-`array` (eine Python-`list`) ist, können Sie den Typ im Funktionsparameter deklarieren, mit der gleichen Syntax wie in Pydantic-Modellen: ```Python images: List[Image] @@ -192,7 +192,7 @@ so wie in: {* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} -## Editor-Unterstützung überall +## Editor-Unterstützung überall { #editor-support-everywhere } Und Sie erhalten Editor-Unterstützung überall. @@ -204,11 +204,11 @@ Sie würden diese Editor-Unterstützung nicht erhalten, wenn Sie direkt mit `dic Aber Sie müssen sich auch nicht weiter um die Modelle kümmern, hereinkommende Dicts werden automatisch in sie konvertiert. Und was Sie zurückgeben, wird automatisch nach JSON konvertiert. -## Bodys mit beliebigen `dict`s +## Bodys mit beliebigen `dict`s { #bodies-of-arbitrary-dicts } Sie können einen Body auch als `dict` deklarieren, mit Schlüsseln eines Typs und Werten eines anderen Typs. -So brauchen Sie vorher nicht zu wissen, wie die Feld-/Attribut-Namen lauten (wie es bei Pydantic-Modellen der Fall wäre). +So brauchen Sie vorher nicht zu wissen, wie die Feld-/Attributnamen lauten (wie es bei Pydantic-Modellen der Fall wäre). Das ist nützlich, wenn Sie Schlüssel empfangen, deren Namen Sie nicht bereits kennen. @@ -218,7 +218,7 @@ Ein anderer nützlicher Anwendungsfall ist, wenn Sie Schlüssel eines anderen Ty Das schauen wir uns mal an. -Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat. +Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat: {* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} @@ -230,11 +230,11 @@ Aber Pydantic hat automatische Datenkonvertierung. Das bedeutet, dass Ihre API-Clients nur Strings senden können, aber solange diese Strings nur Zahlen enthalten, wird Pydantic sie konvertieren und validieren. -Und das `dict` welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben. +Und das `dict`, welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben. /// -## Zusammenfassung +## Zusammenfassung { #recap } Mit **FastAPI** haben Sie die maximale Flexibilität von Pydantic-Modellen, während Ihr Code einfach, kurz und elegant bleibt. diff --git a/docs/de/docs/tutorial/body-updates.md b/docs/de/docs/tutorial/body-updates.md index 574016c58..aa62199fe 100644 --- a/docs/de/docs/tutorial/body-updates.md +++ b/docs/de/docs/tutorial/body-updates.md @@ -1,16 +1,16 @@ -# Body – Aktualisierungen +# Body – Aktualisierungen { #body-updates } -## Ersetzendes Aktualisieren mit `PUT` +## Ersetzendes Aktualisieren mit `PUT` { #update-replacing-with-put } Um einen Artikel zu aktualisieren, können Sie die HTTP `PUT` Operation verwenden. -Sie können den `jsonable_encoder` verwenden, um die empfangenen Daten in etwas zu konvertieren, das als JSON gespeichert werden kann (in z. B. einer NoSQL-Datenbank). Zum Beispiel, um ein `datetime` in einen `str` zu konvertieren. +Sie können den `jsonable_encoder` verwenden, um die empfangenen Daten in etwas zu konvertieren, das als JSON gespeichert werden kann (z. B. in einer NoSQL-Datenbank). Zum Beispiel, um ein `datetime` in einen `str` zu konvertieren. {* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} `PUT` wird verwendet, um Daten zu empfangen, die die existierenden Daten ersetzen sollen. -### Warnung bezüglich des Ersetzens +### Warnung bezüglich des Ersetzens { #warning-about-replacing } Das bedeutet, dass, wenn Sie den Artikel `bar` aktualisieren wollen, mittels `PUT` und folgendem Body: @@ -22,15 +22,15 @@ Das bedeutet, dass, wenn Sie den Artikel `bar` aktualisieren wollen, mittels `PU } ``` -das Eingabemodell nun den Defaultwert `"tax": 10.5` hat, weil Sie das bereits gespeicherte Attribut `"tax": 20.2` nicht mit übergeben haben. +weil das bereits gespeicherte Attribut `"tax": 20.2` nicht enthalten ist, das Eingabemodell den Defaultwert `"tax": 10.5` erhalten würde. -Die Daten werden darum mit einem „neuen“ `tax`-Wert von `10.5` abgespeichert. +Und die Daten würden mit diesem „neuen“ `tax` von `10.5` gespeichert werden. -## Teilweises Ersetzen mit `PATCH` +## Teil-Aktualisierungen mit `PATCH` { #partial-updates-with-patch } Sie können auch die HTTP `PATCH` Operation verwenden, um Daten *teilweise* zu ersetzen. -Das bedeutet, sie senden nur die Daten, die Sie aktualisieren wollen, der Rest bleibt unverändert. +Das bedeutet, Sie senden nur die Daten, die Sie aktualisieren wollen, der Rest bleibt unverändert. /// note | Hinweis @@ -44,33 +44,33 @@ Aber dieser Leitfaden zeigt Ihnen mehr oder weniger, wie die beiden normalerweis /// -### Pydantics `exclude_unset`-Parameter verwenden +### Pydantics `exclude_unset`-Parameter verwenden { #using-pydantics-exclude-unset-parameter } Wenn Sie Teil-Aktualisierungen entgegennehmen, ist der `exclude_unset`-Parameter in der `.model_dump()`-Methode von Pydantic-Modellen sehr nützlich. Wie in `item.model_dump(exclude_unset=True)`. -/// info +/// info | Info -In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt. +In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecatet (aber immer noch unterstützt) und in `.model_dump()` umbenannt. Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können. /// -Das wird ein `dict` erstellen, mit nur den Daten, die gesetzt wurden als das `item`-Modell erstellt wurde, Defaultwerte ausgeschlossen. +Das wird ein `dict` erstellen, mit nur den Daten, die gesetzt wurden, als das `item`-Modell erstellt wurde, Defaultwerte ausgeschlossen. -Sie können das verwenden, um ein `dict` zu erstellen, das nur die (im Request) gesendeten Daten enthält, ohne Defaultwerte: +Sie können das verwenden, um ein `dict` zu erstellen, das nur die (im Request) gesendeten Daten enthält, ohne Defaultwerte: {* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} -### Pydantics `update`-Parameter verwenden +### Pydantics `update`-Parameter verwenden { #using-pydantics-update-parameter } Jetzt können Sie eine Kopie des existierenden Modells mittels `.model_copy()` erstellen, wobei Sie dem `update`-Parameter ein `dict` mit den zu ändernden Daten übergeben. -/// info +/// info | Info -In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_copy()` umbenannt. +In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie deprecatet (aber immer noch unterstützt) und in `.model_copy()` umbenannt. Die Beispiele hier verwenden `.copy()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_copy()` verwenden, wenn Sie Pydantic v2 verwenden können. @@ -80,9 +80,9 @@ Wie in `stored_item_model.model_copy(update=update_data)`: {* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} -### Rekapitulation zum teilweisen Ersetzen +### Rekapitulation zu Teil-Aktualisierungen { #partial-updates-recap } -Zusammengefasst, um Teil-Ersetzungen vorzunehmen: +Zusammengefasst, um Teil-Aktualisierungen vorzunehmen: * (Optional) verwenden Sie `PATCH` statt `PUT`. * Lesen Sie die bereits gespeicherten Daten aus. @@ -90,7 +90,7 @@ Zusammengefasst, um Teil-Ersetzungen vorzunehmen: * Erzeugen Sie aus dem empfangenen Modell ein `dict` ohne Defaultwerte (mittels `exclude_unset`). * So ersetzen Sie nur die tatsächlich vom Benutzer gesetzten Werte, statt dass bereits gespeicherte Werte mit Defaultwerten des Modells überschrieben werden. * Erzeugen Sie eine Kopie ihres gespeicherten Modells, wobei Sie die Attribute mit den empfangenen Teil-Ersetzungen aktualisieren (mittels des `update`-Parameters). -* Konvertieren Sie das kopierte Modell zu etwas, das in ihrer Datenbank gespeichert werden kann (indem Sie beispielsweise `jsonable_encoder` verwenden). +* Konvertieren Sie das kopierte Modell zu etwas, das in Ihrer Datenbank gespeichert werden kann (indem Sie beispielsweise `jsonable_encoder` verwenden). * Das ist vergleichbar dazu, die `.model_dump()`-Methode des Modells erneut aufzurufen, aber es wird sicherstellen, dass die Werte zu Daten konvertiert werden, die ihrerseits zu JSON konvertiert werden können, zum Beispiel `datetime` zu `str`. * Speichern Sie die Daten in Ihrer Datenbank. * Geben Sie das aktualisierte Modell zurück. diff --git a/docs/de/docs/tutorial/body.md b/docs/de/docs/tutorial/body.md index e25323786..1e6382b6f 100644 --- a/docs/de/docs/tutorial/body.md +++ b/docs/de/docs/tutorial/body.md @@ -1,40 +1,40 @@ -# Requestbody +# Requestbody { #request-body } -Wenn Sie Daten von einem Client (sagen wir, einem Browser) zu Ihrer API senden, dann senden Sie diese als einen **Requestbody** (Deutsch: Anfragekörper). +Wenn Sie Daten von einem Client (sagen wir, einem Browser) zu Ihrer API senden müssen, senden Sie sie als **Requestbody**. -Ein **Request**body sind Daten, die vom Client zu Ihrer API gesendet werden. Ein **Response**body (Deutsch: Antwortkörper) sind Daten, die Ihre API zum Client sendet. +Ein **Request**body sind Daten, die vom Client zu Ihrer API gesendet werden. Ein **Response**body sind Daten, die Ihre API zum Client sendet. -Ihre API sendet fast immer einen **Response**body. Aber Clients senden nicht unbedingt immer **Request**bodys (sondern nur Metadaten). +Ihre API muss fast immer einen **Response**body senden. Aber Clients müssen nicht unbedingt immer **Requestbodys** senden, manchmal fordern sie nur einen Pfad an, vielleicht mit einigen Query-Parametern, aber senden keinen Body. -Um einen **Request**body zu deklarieren, verwenden Sie Pydantic-Modelle mit allen deren Fähigkeiten und Vorzügen. +Um einen **Request**body zu deklarieren, verwenden Sie Pydantic-Modelle mit all deren Fähigkeiten und Vorzügen. -/// info +/// info | Info -Um Daten zu versenden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden. +Um Daten zu senden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden. -Senden Sie einen Body mit einem `GET`-Request, dann führt das laut Spezifikation zu undefiniertem Verhalten. Trotzdem wird es von FastAPI unterstützt, für sehr komplexe/extreme Anwendungsfälle. +Das Senden eines Bodys mit einem `GET`-Request hat ein undefiniertes Verhalten in den Spezifikationen, wird aber dennoch von FastAPI unterstützt, nur für sehr komplexe/extreme Anwendungsfälle. -Da aber davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body auch nicht an, wenn `GET` verwendet wird. Dazwischengeschaltete Proxys unterstützen es möglicherweise auch nicht. +Da davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body nicht an, wenn `GET` verwendet wird, und zwischengeschaltete Proxys unterstützen es möglicherweise nicht. /// -## Importieren Sie Pydantics `BaseModel` +## Pydantics `BaseModel` importieren { #import-pydantics-basemodel } Zuerst müssen Sie `BaseModel` von `pydantic` importieren: {* ../../docs_src/body/tutorial001_py310.py hl[2] *} -## Erstellen Sie Ihr Datenmodell +## Ihr Datenmodell erstellen { #create-your-data-model } Dann deklarieren Sie Ihr Datenmodell als eine Klasse, die von `BaseModel` erbt. -Verwenden Sie Standard-Python-Typen für die Klassenattribute: +Verwenden Sie Standard-Python-Typen für alle Attribute: {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} -Wie auch bei Query-Parametern gilt, wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Ansonsten ist es erforderlich. Verwenden Sie `None`, um es als optional zu kennzeichnen. +Wie auch bei der Deklaration von Query-Parametern gilt: Wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Andernfalls ist es erforderlich. Verwenden Sie `None`, um es einfach optional zu machen. -Zum Beispiel deklariert das obige Modell ein JSON "`object`" (oder Python-`dict`) wie dieses: +Zum Beispiel deklariert das obige Modell ein JSON „`object`“ (oder Python-`dict`) wie dieses: ```JSON { @@ -45,7 +45,7 @@ Zum Beispiel deklariert das obige Modell ein JSON "`object`" (oder Python-`dict` } ``` -Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre folgendes JSON "`object`" auch gültig: +Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre folgendes JSON „`object`“ auch gültig: ```JSON { @@ -54,109 +54,120 @@ Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre fol } ``` -## Deklarieren Sie es als Parameter +## Als Parameter deklarieren { #declare-it-as-a-parameter } Um es zu Ihrer *Pfadoperation* hinzuzufügen, deklarieren Sie es auf die gleiche Weise, wie Sie Pfad- und Query-Parameter deklariert haben: {* ../../docs_src/body/tutorial001_py310.py hl[16] *} -... und deklarieren Sie seinen Typ als das Modell, welches Sie erstellt haben, `Item`. +... und deklarieren Sie dessen Typ als das Modell, welches Sie erstellt haben, `Item`. -## Resultate +## Resultate { #results } -Mit nur dieser Python-Typdeklaration, wird **FastAPI**: +Mit nur dieser Python-Typdeklaration wird **FastAPI**: * Den Requestbody als JSON lesen. * Die entsprechenden Typen konvertieren (falls nötig). * Diese Daten validieren. - * Wenn die Daten ungültig sind, einen klar lesbaren Fehler zurückgeben, der anzeigt, wo und was die inkorrekten Daten waren. + * Wenn die Daten ungültig sind, wird ein klar lesbarer Fehler zurückgegeben, der genau anzeigt, wo und was die inkorrekten Daten sind. * Ihnen die erhaltenen Daten im Parameter `item` übergeben. - * Da Sie diesen in der Funktion als vom Typ `Item` deklariert haben, erhalten Sie die ganze Editor-Unterstützung (Autovervollständigung, usw.) für alle Attribute und deren Typen. -* Eine JSON Schema Definition für Ihr Modell generieren, welche Sie überall sonst verwenden können, wenn es für Ihr Projekt Sinn macht. -* Diese Schemas werden Teil des generierten OpenAPI-Schemas und werden von den UIs der automatischen Dokumentation verwendet. + * Da Sie ihn in der Funktion als vom Typ `Item` deklariert haben, erhalten Sie auch die volle Unterstützung des Editors (Autovervollständigung, usw.) für alle Attribute und deren Typen. +* JSON Schema-Definitionen für Ihr Modell generieren, die Sie auch überall sonst verwenden können, wenn es für Ihr Projekt Sinn macht. +* Diese Schemas werden Teil des generierten OpenAPI-Schemas und werden von den UIs der automatischen Dokumentation genutzt. -## Automatische Dokumentation +## Automatische Dokumentation { #automatic-docs } -Die JSON-Schemas Ihrer Modelle werden Teil ihrer OpenAPI-generierten Schemas und werden in der interaktiven API Dokumentation angezeigt: +Die JSON-Schemas Ihrer Modelle werden Teil Ihres OpenAPI-generierten Schemas und in der interaktiven API-Dokumentation angezeigt: -Und werden auch verwendet in der API-Dokumentation innerhalb jeder *Pfadoperation*, welche sie braucht: +Und werden auch in der API-Dokumentation innerhalb jeder *Pfadoperation*, die sie benötigt, verwendet: -## Editor Unterstützung +## Editor-Unterstützung { #editor-support } -In Ihrem Editor, innerhalb Ihrer Funktion, erhalten Sie Typhinweise und Code-Vervollständigung überall (was nicht der Fall wäre, wenn Sie ein `dict` anstelle eines Pydantic Modells erhalten hätten): +In Ihrem Editor erhalten Sie innerhalb Ihrer Funktion Typhinweise und Code-Vervollständigung überall (was nicht der Fall wäre, wenn Sie ein `dict` anstelle eines Pydantic-Modells erhalten hätten): -Sie bekommen auch Fehler-Meldungen für inkorrekte Typoperationen: +Sie bekommen auch Fehlermeldungen für inkorrekte Typoperationen: Das ist nicht zufällig so, das ganze Framework wurde um dieses Design herum aufgebaut. -Und es wurde in der Designphase gründlich getestet, vor der Implementierung, um sicherzustellen, dass es mit jedem Editor funktioniert. +Und es wurde in der Designphase gründlich getestet, bevor irgendeine Implementierung stattfand, um sicherzustellen, dass es mit allen Editoren funktioniert. -Es gab sogar ein paar Änderungen an Pydantic selbst, um das zu unterstützen. +Es gab sogar einige Änderungen an Pydantic selbst, um dies zu unterstützen. -Die vorherigen Screenshots zeigten Visual Studio Code. +Die vorherigen Screenshots wurden mit Visual Studio Code aufgenommen. -Aber Sie bekommen die gleiche Editor-Unterstützung in PyCharm und in den meisten anderen Python-Editoren: +Aber Sie würden die gleiche Editor-Unterstützung in PyCharm und den meisten anderen Python-Editoren erhalten: /// tip | Tipp -Wenn Sie PyCharm als Ihren Editor verwenden, probieren Sie das Pydantic PyCharm Plugin aus. +Wenn Sie PyCharm als Ihren Editor verwenden, können Sie das Pydantic PyCharm Plugin ausprobieren. Es verbessert die Editor-Unterstützung für Pydantic-Modelle, mit: * Code-Vervollständigung * Typüberprüfungen * Refaktorisierung -* Suchen +* Suche * Inspektionen /// -## Das Modell verwenden +## Das Modell verwenden { #use-the-model } -Innerhalb der Funktion können Sie alle Attribute des Modells direkt verwenden: +Innerhalb der Funktion können Sie alle Attribute des Modellobjekts direkt verwenden: -{* ../../docs_src/body/tutorial002_py310.py hl[19] *} +{* ../../docs_src/body/tutorial002_py310.py *} -## Requestbody- + Pfad-Parameter +/// info | Info -Sie können Pfad- und Requestbody-Parameter gleichzeitig deklarieren. +In Pydantic v1 hieß die Methode `.dict()`, sie wurde in Pydantic v2 deprecatet (aber weiterhin unterstützt) und in `.model_dump()` umbenannt. + +Die Beispiele hier verwenden `.dict()` zur Kompatibilität mit Pydantic v1, aber Sie sollten stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 nutzen können. + +/// + +## Requestbody- + Pfad-Parameter { #request-body-path-parameters } + +Sie können Pfad-Parameter und den Requestbody gleichzeitig deklarieren. **FastAPI** erkennt, dass Funktionsparameter, die mit Pfad-Parametern übereinstimmen, **vom Pfad genommen** werden sollen, und dass Funktionsparameter, welche Pydantic-Modelle sind, **vom Requestbody genommen** werden sollen. {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} -## Requestbody- + Pfad- + Query-Parameter + +## Requestbody- + Pfad- + Query-Parameter { #request-body-path-query-parameters } Sie können auch zur gleichen Zeit **Body-**, **Pfad-** und **Query-Parameter** deklarieren. -**FastAPI** wird jeden Parameter korrekt erkennen und die Daten vom richtigen Ort holen. +**FastAPI** wird jeden von ihnen korrekt erkennen und die Daten vom richtigen Ort holen. {* ../../docs_src/body/tutorial004_py310.py hl[16] *} Die Funktionsparameter werden wie folgt erkannt: -* Wenn der Parameter auch im **Pfad** deklariert wurde, wird er als Pfad-Parameter interpretiert. +* Wenn der Parameter auch im **Pfad** deklariert wurde, wird er als Pfad-Parameter verwendet. * Wenn der Parameter ein **einfacher Typ** ist (wie `int`, `float`, `str`, `bool`, usw.), wird er als **Query**-Parameter interpretiert. * Wenn der Parameter vom Typ eines **Pydantic-Modells** ist, wird er als Request**body** interpretiert. /// note | Hinweis -FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, wegen des definierten Defaultwertes `= None` +FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, aufgrund des definierten Defaultwertes `= None`. -Das `Union` in `Union[str, None]` wird von FastAPI nicht verwendet, aber es erlaubt Ihrem Editor, Sie besser zu unterstützen und Fehler zu erkennen. +Das `str | None` (Python 3.10+) oder `Union` in `Union[str, None]` (Python 3.8+) wird von FastAPI nicht verwendet, um zu bestimmen, dass der Wert nicht erforderlich ist. FastAPI weiß, dass er nicht erforderlich ist, weil er einen Defaultwert von `= None` hat. + +Das Hinzufügen der Typannotationen ermöglicht jedoch Ihrem Editor, Ihnen eine bessere Unterstützung zu bieten und Fehler zu erkennen. /// -## Ohne Pydantic +## Ohne Pydantic { #without-pydantic } -Wenn Sie keine Pydantic-Modelle verwenden wollen, können Sie auch **Body**-Parameter nehmen. Siehe die Dokumentation unter [Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#einzelne-werte-im-body){.internal-link target=\_blank}. +Wenn Sie keine Pydantic-Modelle verwenden möchten, können Sie auch **Body**-Parameter verwenden. Siehe die Dokumentation unter [Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}. diff --git a/docs/de/docs/tutorial/cookie-param-models.md b/docs/de/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..2baf3d70d --- /dev/null +++ b/docs/de/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Cookie-Parameter-Modelle { #cookie-parameter-models } + +Wenn Sie eine Gruppe von **Cookies** haben, die zusammengehören, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren. 🍪 + +Damit können Sie das Modell an **mehreren Stellen wiederverwenden** und auch Validierungen und Metadaten für alle Parameter gleichzeitig deklarieren. 😎 + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓 + +/// + +/// tip | Tipp + +Diese gleiche Technik gilt für `Query`, `Cookie` und `Header`. 😎 + +/// + +## Cookies mit einem Pydantic-Modell { #cookies-with-a-pydantic-model } + +Deklarieren Sie die **Cookie**-Parameter, die Sie benötigen, in einem **Pydantic-Modell**, und deklarieren Sie dann den Parameter als `Cookie`: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den im Request empfangenen **Cookies** **extrahieren** und Ihnen das von Ihnen definierte Pydantic-Modell bereitstellen. + +## Die Dokumentation testen { #check-the-docs } + +Sie können die definierten Cookies in der Dokumentationsoberfläche unter `/docs` sehen: + +
+ +
+ +/// info | Info + +Bitte beachten Sie, dass Browser Cookies auf spezielle Weise und im Hintergrund bearbeiten, sodass sie **nicht** leicht **JavaScript** erlauben, diese zu berühren. + +Wenn Sie zur **API-Dokumentationsoberfläche** unter `/docs` gehen, können Sie die **Dokumentation** für Cookies für Ihre *Pfadoperationen* sehen. + +Aber selbst wenn Sie die **Daten ausfüllen** und auf „Ausführen“ klicken, werden aufgrund der Tatsache, dass die Dokumentationsoberfläche mit **JavaScript** arbeitet, die Cookies nicht gesendet, und Sie werden eine **Fehlermeldung** sehen, als ob Sie keine Werte eingegeben hätten. + +/// + +## Zusätzliche Cookies verbieten { #forbid-extra-cookies } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Cookies, die Sie empfangen möchten, **einschränken**. + +Ihre API hat jetzt die Macht, ihre eigene Cookie-Einwilligung zu kontrollieren. 🤪🍪 + +Sie können die Modellkonfiguration von Pydantic verwenden, um `extra` Felder zu verbieten (`forbid`): + +{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} + +Wenn ein Client versucht, einige **zusätzliche Cookies** zu senden, erhält er eine **Error-Response**. + +Arme Cookie-Banner, wie sie sich mühen, Ihre Einwilligung zu erhalten, dass die API sie ablehnen darf. 🍪 + +Wenn der Client beispielsweise versucht, ein `santa_tracker`-Cookie mit einem Wert von `good-list-please` zu senden, erhält der Client eine **Error-Response**, die ihm mitteilt, dass das `santa_tracker` Cookie nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## Zusammenfassung { #summary } + +Sie können **Pydantic-Modelle** verwenden, um **Cookies** in **FastAPI** zu deklarieren. 😎 diff --git a/docs/de/docs/tutorial/cookie-params.md b/docs/de/docs/tutorial/cookie-params.md index 711c8c8e9..9f50c7ae5 100644 --- a/docs/de/docs/tutorial/cookie-params.md +++ b/docs/de/docs/tutorial/cookie-params.md @@ -1,35 +1,35 @@ -# Cookie-Parameter +# Cookie-Parameter { #cookie-parameters } -So wie `Query`- und `Path`-Parameter können Sie auch Cookie-Parameter definieren. +Sie können Cookie-Parameter auf die gleiche Weise definieren wie `Query`- und `Path`-Parameter. -## `Cookie` importieren +## `Cookie` importieren { #import-cookie } Importieren Sie zuerst `Cookie`: {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} -## `Cookie`-Parameter deklarieren +## `Cookie`-Parameter deklarieren { #declare-cookie-parameters } -Dann deklarieren Sie Ihre Cookie-Parameter, auf die gleiche Weise, wie Sie auch `Path`- und `Query`-Parameter deklarieren. +Deklarieren Sie dann die Cookie-Parameter mit derselben Struktur wie bei `Path` und `Query`. -Der erste Wert ist der Typ. Sie können `Cookie` die gehabten Extra Validierungs- und Beschreibungsparameter hinzufügen. Danach können Sie einen Defaultwert vergeben: +Sie können den Defaultwert sowie alle zusätzlichen Validierungen oder Annotierungsparameter definieren: {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} /// note | Technische Details -`Cookie` ist eine Schwesterklasse von `Path` und `Query`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse. +`Cookie` ist eine „Schwester“-Klasse von `Path` und `Query`. Sie erbt auch von derselben gemeinsamen `Param`-Klasse. -Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben. +Aber denken Sie daran, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, die spezielle Klassen zurückgeben. /// -/// info +/// info | Info -Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden. +Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da die Parameter sonst als Query-Parameter interpretiert würden. /// -## Zusammenfassung +## Zusammenfassung { #recap } -Deklarieren Sie Cookies mittels `Cookie`, auf die gleiche Weise wie bei `Query` und `Path`. +Deklarieren Sie Cookies mit `Cookie` und verwenden Sie dabei das gleiche allgemeine Muster wie bei `Query` und `Path`. diff --git a/docs/de/docs/tutorial/cors.md b/docs/de/docs/tutorial/cors.md new file mode 100644 index 000000000..191a7b4ef --- /dev/null +++ b/docs/de/docs/tutorial/cors.md @@ -0,0 +1,88 @@ +# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing } + +CORS oder „Cross-Origin Resource Sharing“ bezieht sich auf Situationen, in denen ein Frontend, das in einem Browser läuft, JavaScript-Code enthält, der mit einem Backend kommuniziert, und das Backend sich in einem anderen „Origin“ als das Frontend befindet. + +## Origin { #origin } + +Ein Origin ist die Kombination aus Protokoll (`http`, `https`), Domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`) und Port (`80`, `443`, `8080`). + +Alle folgenden sind also unterschiedliche Origins: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +Auch wenn sie alle in `localhost` sind, verwenden sie unterschiedliche Protokolle oder Ports, daher sind sie unterschiedliche „Origins“. + +## Schritte { #steps } + +Angenommen, Sie haben ein Frontend, das in Ihrem Browser unter `http://localhost:8080` läuft, und dessen JavaScript versucht, mit einem Backend zu kommunizieren, das unter `http://localhost` läuft (da wir keinen Port angegeben haben, geht der Browser vom Default-Port `80` aus). + +Dann wird der Browser ein HTTP-`OPTIONS`-Request an das `:80`-Backend senden, und wenn das Backend die entsprechenden Header sendet, die die Kommunikation von diesem anderen Origin (`http://localhost:8080`) autorisieren, lässt der `:8080`-Browser das JavaScript im Frontend seinen Request an das `:80`-Backend senden. + +Um dies zu erreichen, muss das `:80`-Backend eine Liste von „erlaubten Origins“ haben. + +In diesem Fall müsste die Liste `http://localhost:8080` enthalten, damit das `:8080`-Frontend korrekt funktioniert. + +## Wildcards { #wildcards } + +Es ist auch möglich, die Liste als `"*"` (ein „Wildcard“) zu deklarieren, um anzuzeigen, dass alle erlaubt sind. + +Aber das erlaubt nur bestimmte Arten der Kommunikation und schließt alles aus, was Anmeldeinformationen beinhaltet: Cookies, Autorisierungsheader wie die, die mit Bearer Tokens verwendet werden, usw. + +Um sicherzustellen, dass alles korrekt funktioniert, ist es besser, die erlaubten Origins explizit anzugeben. + +## `CORSMiddleware` verwenden { #use-corsmiddleware } + +Sie können das in Ihrer **FastAPI**-Anwendung mit der `CORSMiddleware` konfigurieren. + +* Importieren Sie `CORSMiddleware`. +* Erstellen Sie eine Liste der erlaubten Origins (als Strings). +* Fügen Sie es als „Middleware“ zu Ihrer **FastAPI**-Anwendung hinzu. + +Sie können auch angeben, ob Ihr Backend erlaubt: + +* Anmeldeinformationen (Autorisierungsheader, Cookies, usw.). +* Bestimmte HTTP-Methoden (`POST`, `PUT`) oder alle mit der Wildcard `"*"`. +* Bestimmte HTTP-Header oder alle mit der Wildcard `"*"`. + +{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *} + +Die von der `CORSMiddleware`-Implementierung verwendeten Defaultparameter sind standardmäßig restriktiv, daher müssen Sie bestimmte Origins, Methoden oder Header ausdrücklich aktivieren, damit Browser sie in einem Cross-Domain-Kontext verwenden dürfen. + +Die folgenden Argumente werden unterstützt: + +* `allow_origins` – Eine Liste von Origins, die Cross-Origin-Requests machen dürfen. z. B. `['https://example.org', 'https://www.example.org']`. Sie können `['*']` verwenden, um jedes Origin zuzulassen. +* `allow_origin_regex` – Ein Regex-String zum Abgleichen gegen Origins, die Cross-Origin-Requests machen dürfen. z. B. `'https://.*\.example\.org'`. +* `allow_methods` – Eine Liste von HTTP-Methoden, die für Cross-Origin-Requests erlaubt sein sollen. Standardmäßig `['GET']`. Sie können `['*']` verwenden, um alle Standardmethoden zu erlauben. +* `allow_headers` – Eine Liste von HTTP-Requestheadern, die für Cross-Origin-Requests unterstützt werden sollten. Standardmäßig `[]`. Sie können `['*']` verwenden, um alle Header zu erlauben. Die Header `Accept`, `Accept-Language`, `Content-Language` und `Content-Type` sind immer für einfache CORS-Requests erlaubt. +* `allow_credentials` – Anzeigen, dass Cookies für Cross-Origin-Requests unterstützt werden sollten. Standardmäßig `False`. + + Keines der `allow_origins`, `allow_methods` und `allow_headers` kann auf `['*']` gesetzt werden, wenn `allow_credentials` auf `True` gesetzt ist. Alle müssen explizit angegeben werden. + +* `expose_headers` – Angabe der Responseheader, auf die der Browser zugreifen können soll. Standardmäßig `[]`. +* `max_age` – Legt eine maximale Zeit in Sekunden fest, die Browser CORS-Responses zwischenspeichern dürfen. Standardmäßig `600`. + +Die Middleware antwortet auf zwei besondere Arten von HTTP-Requests ... + +### CORS-Preflight-Requests { #cors-preflight-requests } + +Dies sind alle `OPTIONS`-Requests mit `Origin`- und `Access-Control-Request-Method`-Headern. + +In diesem Fall wird die Middleware den eingehenden Request abfangen und mit entsprechenden CORS-Headern, und entweder einer `200`- oder `400`-Response zu Informationszwecken antworten. + +### Einfache Requests { #simple-requests } + +Jeder Request mit einem `Origin`-Header. In diesem Fall wird die Middleware den Request wie gewohnt durchlassen, aber entsprechende CORS-Header in die Response aufnehmen. + +## Weitere Informationen { #more-info } + +Weitere Informationen zu CORS finden Sie in der Mozilla CORS-Dokumentation. + +/// note | Technische Details + +Sie könnten auch `from starlette.middleware.cors import CORSMiddleware` verwenden. + +**FastAPI** bietet mehrere Middlewares in `fastapi.middleware` nur als Komfort für Sie, den Entwickler. Aber die meisten der verfügbaren Middlewares stammen direkt von Starlette. + +/// diff --git a/docs/de/docs/tutorial/debugging.md b/docs/de/docs/tutorial/debugging.md new file mode 100644 index 000000000..0a31f8653 --- /dev/null +++ b/docs/de/docs/tutorial/debugging.md @@ -0,0 +1,113 @@ +# Debugging { #debugging } + +Sie können den Debugger in Ihrem Editor verbinden, zum Beispiel mit Visual Studio Code oder PyCharm. + +## `uvicorn` aufrufen { #call-uvicorn } + +Importieren und führen Sie `uvicorn` direkt in Ihrer FastAPI-Anwendung aus: + +{* ../../docs_src/debugging/tutorial001.py hl[1,15] *} + +### Über `__name__ == "__main__"` { #about-name-main } + +Der Hauptzweck von `__name__ == "__main__"` ist, dass Code ausgeführt wird, wenn Ihre Datei mit folgendem Befehl aufgerufen wird: + +
+ +```console +$ python myapp.py +``` + +
+ +aber nicht aufgerufen wird, wenn eine andere Datei sie importiert, wie in: + +```Python +from myapp import app +``` + +#### Weitere Details { #more-details } + +Angenommen, Ihre Datei heißt `myapp.py`. + +Wenn Sie sie mit folgendem Befehl ausführen: + +
+ +```console +$ python myapp.py +``` + +
+ +dann hat in Ihrer Datei die interne Variable `__name__`, die von Python automatisch erstellt wird, als Wert den String `"__main__"`. + +Daher wird der Abschnitt: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +ausgeführt. + +--- + +Dies wird nicht passieren, wenn Sie das Modul (die Datei) importieren. + +Wenn Sie also eine weitere Datei `importer.py` mit folgendem Inhalt haben: + +```Python +from myapp import app + +# Hier mehr Code +``` + +wird in diesem Fall in `myapp.py` die automatisch erstellte Variable `__name__` nicht den Wert `"__main__"` haben. + +Daher wird die Zeile: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +nicht ausgeführt. + +/// info | Info + +Für weitere Informationen besuchen Sie bitte die offizielle Python-Dokumentation. + +/// + +## Ihren Code mit Ihrem Debugger ausführen { #run-your-code-with-your-debugger } + +Da Sie den Uvicorn-Server direkt aus Ihrem Code ausführen, können Sie Ihr Python-Programm (Ihre FastAPI-Anwendung) direkt aus dem Debugger aufrufen. + +--- + +Zum Beispiel können Sie in Visual Studio Code: + +* Zum „Debug“-Panel gehen. +* „Konfiguration hinzufügen ...“ auswählen. +* „Python“ auswählen. +* Den Debugger mit der Option „`Python: Current File (Integrated Terminal)`“ ausführen. + +Der Server wird dann mit Ihrem **FastAPI**-Code gestartet, an Ihren Haltepunkten angehalten, usw. + +So könnte es aussehen: + + + +--- + +Wenn Sie Pycharm verwenden, können Sie: + +* Das Menü „Run“ öffnen. +* Die Option „Debug ...“ auswählen. +* Ein Kontextmenü wird angezeigt. +* Die zu debuggende Datei auswählen (in diesem Fall `main.py`). + +Der Server wird dann mit Ihrem **FastAPI**-Code gestartet, an Ihren Haltepunkten angehalten, usw. + +So könnte es aussehen: + + diff --git a/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md index e9f25f786..3d4493f35 100644 --- a/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md +++ b/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md @@ -1,10 +1,10 @@ -# Klassen als Abhängigkeiten +# Klassen als Abhängigkeiten { #classes-as-dependencies } Bevor wir tiefer in das **Dependency Injection** System eintauchen, lassen Sie uns das vorherige Beispiel verbessern. -## Ein `dict` aus dem vorherigen Beispiel +## Ein `dict` aus dem vorherigen Beispiel { #a-dict-from-the-previous-example } -Im vorherigen Beispiel haben wir ein `dict` von unserer Abhängigkeit („Dependable“) zurückgegeben: +Im vorherigen Beispiel haben wir ein `dict` von unserer Abhängigkeit („Dependable“) zurückgegeben: {* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} @@ -14,7 +14,7 @@ Und wir wissen, dass Editoren nicht viel Unterstützung (wie etwa Code-Vervollst Das können wir besser machen ... -## Was macht eine Abhängigkeit aus +## Was macht eine Abhängigkeit aus { #what-makes-a-dependency } Bisher haben Sie Abhängigkeiten gesehen, die als Funktionen deklariert wurden. @@ -38,7 +38,7 @@ something(some_argument, some_keyword_argument="foo") dann ist das ein „Callable“ (ein „Aufrufbares“). -## Klassen als Abhängigkeiten +## Klassen als Abhängigkeiten { #classes-as-dependencies_1 } Möglicherweise stellen Sie fest, dass Sie zum Erstellen einer Instanz einer Python-Klasse die gleiche Syntax verwenden. @@ -89,7 +89,7 @@ In beiden Fällen wird sie haben: In beiden Fällen werden die Daten konvertiert, validiert, im OpenAPI-Schema dokumentiert, usw. -## Verwendung +## Verwenden { #use-it } Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren. @@ -97,7 +97,7 @@ Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren. **FastAPI** ruft die Klasse `CommonQueryParams` auf. Dadurch wird eine „Instanz“ dieser Klasse erstellt und die Instanz wird als Parameter `commons` an Ihre Funktion überreicht. -## Typannotation vs. `Depends` +## Typannotation vs. `Depends` { #type-annotation-vs-depends } Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben: @@ -193,7 +193,7 @@ Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was al -## Abkürzung +## Abkürzung { #shortcut } Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben: diff --git a/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index bbba1a536..59c9fcf48 100644 --- a/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -1,14 +1,14 @@ -# Abhängigkeiten in Pfadoperation-Dekoratoren +# Abhängigkeiten in Pfadoperation-Dekoratoren { #dependencies-in-path-operation-decorators } Manchmal benötigen Sie den Rückgabewert einer Abhängigkeit innerhalb Ihrer *Pfadoperation-Funktion* nicht wirklich. Oder die Abhängigkeit gibt keinen Wert zurück. -Aber Sie müssen Sie trotzdem ausführen/auflösen. +Aber Sie müssen sie trotzdem ausführen/auflösen. In diesen Fällen können Sie, anstatt einen Parameter der *Pfadoperation-Funktion* mit `Depends` zu deklarieren, eine `list`e von `dependencies` zum *Pfadoperation-Dekorator* hinzufügen. -## `dependencies` zum *Pfadoperation-Dekorator* hinzufügen +## `dependencies` zum *Pfadoperation-Dekorator* hinzufügen { #add-dependencies-to-the-path-operation-decorator } Der *Pfadoperation-Dekorator* erhält ein optionales Argument `dependencies`. @@ -28,7 +28,7 @@ Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die ein /// -/// info +/// info | Info In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`. @@ -36,23 +36,23 @@ Aber in realen Fällen würden Sie bei der Implementierung von Sicherheit mehr V /// -## Abhängigkeitsfehler und -Rückgabewerte +## Abhängigkeitsfehler und -Rückgabewerte { #dependencies-errors-and-return-values } Sie können dieselben Abhängigkeits-*Funktionen* verwenden, die Sie normalerweise verwenden. -### Abhängigkeitsanforderungen +### Abhängigkeitsanforderungen { #dependency-requirements } -Sie können Anforderungen für einen Request (wie Header) oder andere Unterabhängigkeiten deklarieren: +Sie können Anforderungen für einen Request (wie Header) oder andere Unterabhängigkeiten deklarieren: {* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *} -### Exceptions auslösen +### Exceptions auslösen { #raise-exceptions } Die Abhängigkeiten können Exceptions `raise`n, genau wie normale Abhängigkeiten: {* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *} -### Rückgabewerte +### Rückgabewerte { #return-values } Und sie können Werte zurückgeben oder nicht, die Werte werden nicht verwendet. @@ -60,10 +60,10 @@ Sie können also eine normale Abhängigkeit (die einen Wert zurückgibt), die Si {* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *} -## Abhängigkeiten für eine Gruppe von *Pfadoperationen* +## Abhängigkeiten für eine Gruppe von *Pfadoperationen* { #dependencies-for-a-group-of-path-operations } Wenn Sie später lesen, wie Sie größere Anwendungen strukturieren ([Größere Anwendungen – Mehrere Dateien](../../tutorial/bigger-applications.md){.internal-link target=_blank}), möglicherweise mit mehreren Dateien, lernen Sie, wie Sie einen einzelnen `dependencies`-Parameter für eine Gruppe von *Pfadoperationen* deklarieren. -## Globale Abhängigkeiten +## Globale Abhängigkeiten { #global-dependencies } Als Nächstes werden wir sehen, wie man Abhängigkeiten zur gesamten `FastAPI`-Anwendung hinzufügt, sodass sie für jede *Pfadoperation* gelten. diff --git a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md index 4b12f8447..178c2673e 100644 --- a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,4 +1,4 @@ -# Abhängigkeiten mit yield +# Abhängigkeiten mit `yield` { #dependencies-with-yield } FastAPI unterstützt Abhängigkeiten, die nach Abschluss einige zusätzliche Schritte ausführen. @@ -23,11 +23,11 @@ Tatsächlich verwendet FastAPI diese beiden Dekoratoren intern. /// -## Eine Datenbank-Abhängigkeit mit `yield`. +## Eine Datenbank-Abhängigkeit mit `yield` { #a-database-dependency-with-yield } Sie könnten damit beispielsweise eine Datenbanksession erstellen und diese nach Abschluss schließen. -Nur der Code vor und einschließlich der `yield`-Anweisung wird ausgeführt, bevor eine Response erzeugt wird: +Nur der Code vor und einschließlich der `yield`-Anweisung wird ausgeführt, bevor eine Response erzeugt wird: {* ../../docs_src/dependencies/tutorial007.py hl[2:4] *} @@ -35,19 +35,19 @@ Der ge`yield`ete Wert ist das, was in *Pfadoperationen* und andere Abhängigkeit {* ../../docs_src/dependencies/tutorial007.py hl[4] *} -Der auf die `yield`-Anweisung folgende Code wird ausgeführt, nachdem die Response gesendet wurde: +Der auf die `yield`-Anweisung folgende Code wird ausgeführt, nachdem die Response erstellt wurde, aber bevor sie gesendet wird: {* ../../docs_src/dependencies/tutorial007.py hl[5:6] *} /// tip | Tipp -Sie können `async`hrone oder reguläre Funktionen verwenden. +Sie können `async`- oder reguläre Funktionen verwenden. **FastAPI** wird bei jeder das Richtige tun, so wie auch bei normalen Abhängigkeiten. /// -## Eine Abhängigkeit mit `yield` und `try`. +## Eine Abhängigkeit mit `yield` und `try` { #a-dependency-with-yield-and-try } Wenn Sie einen `try`-Block in einer Abhängigkeit mit `yield` verwenden, empfangen Sie alle Exceptions, die bei Verwendung der Abhängigkeit geworfen wurden. @@ -59,7 +59,7 @@ Auf die gleiche Weise können Sie `finally` verwenden, um sicherzustellen, dass {* ../../docs_src/dependencies/tutorial007.py hl[3,5] *} -## Unterabhängigkeiten mit `yield`. +## Unterabhängigkeiten mit `yield` { #sub-dependencies-with-yield } Sie können Unterabhängigkeiten und „Bäume“ von Unterabhängigkeiten beliebiger Größe und Form haben, und einige oder alle davon können `yield` verwenden. @@ -93,7 +93,7 @@ Dieses funktioniert dank Pythons Dependency Injection
** System. +**FastAPI** hat ein sehr mächtiges, aber intuitives **Dependency Injection** System. Es ist so konzipiert, sehr einfach zu verwenden zu sein und es jedem Entwickler sehr leicht zu machen, andere Komponenten mit **FastAPI** zu integrieren. -## Was ist „Dependency Injection“ +## Was ist „Dependency Injection“ { #what-is-dependency-injection } **„Dependency Injection“** bedeutet in der Programmierung, dass es für Ihren Code (in diesem Fall Ihre *Pfadoperation-Funktionen*) eine Möglichkeit gibt, Dinge zu deklarieren, die er verwenden möchte und die er zum Funktionieren benötigt: „Abhängigkeiten“ – „Dependencies“. @@ -19,15 +19,15 @@ Das ist sehr nützlich, wenn Sie: All dies, während Sie Codeverdoppelung minimieren. -## Erste Schritte +## Erste Schritte { #first-steps } Sehen wir uns ein sehr einfaches Beispiel an. Es ist so einfach, dass es vorerst nicht sehr nützlich ist. Aber so können wir uns besser auf die Funktionsweise des **Dependency Injection** Systems konzentrieren. -### Erstellen Sie eine Abhängigkeit („Dependable“) +### Eine Abhängigkeit erstellen, oder „Dependable“ { #create-a-dependency-or-dependable } -Konzentrieren wir uns zunächst auf die Abhängigkeit - die Dependency. +Konzentrieren wir uns zunächst auf die Abhängigkeit – die Dependency. Es handelt sich einfach um eine Funktion, die die gleichen Parameter entgegennimmt wie eine *Pfadoperation-Funktion*: {* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} @@ -48,23 +48,23 @@ In diesem Fall erwartet diese Abhängigkeit: * Einen optionalen Query-Parameter `skip`, der ein `int` ist und standardmäßig `0` ist. * Einen optionalen Query-Parameter `limit`, der ein `int` ist und standardmäßig `100` ist. -Und dann wird einfach ein `dict` zurückgegeben, welches diese Werte enthält. +Und dann wird einfach ein `dict` zurückgegeben, welches diese Werte enthält. -/// info +/// info | Info FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0. Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden. -Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden. +Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden. /// -### `Depends` importieren +### `Depends` importieren { #import-depends } {* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} -### Deklarieren der Abhängigkeit im „Dependant“ +### Die Abhängigkeit im „Dependant“ deklarieren { #declare-the-dependency-in-the-dependant } So wie auch `Body`, `Query`, usw., verwenden Sie `Depends` mit den Parametern Ihrer *Pfadoperation-Funktion*: @@ -86,7 +86,7 @@ Im nächsten Kapitel erfahren Sie, welche anderen „Dinge“, außer Funktionen /// -Immer wenn ein neuer Request eintrifft, kümmert sich **FastAPI** darum: +Immer wenn ein neuer Request eintrifft, kümmert sich **FastAPI** darum: * Ihre Abhängigkeitsfunktion („Dependable“) mit den richtigen Parametern aufzurufen. * Sich das Ergebnis von dieser Funktion zu holen. @@ -105,7 +105,7 @@ common_parameters --> read_users Auf diese Weise schreiben Sie gemeinsam genutzten Code nur einmal, und **FastAPI** kümmert sich darum, ihn für Ihre *Pfadoperationen* aufzurufen. -/// check +/// check | Testen Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich. @@ -113,7 +113,7 @@ Sie übergeben es einfach an `Depends` und **FastAPI** weiß, wie der Rest erled /// -## `Annotated`-Abhängigkeiten wiederverwenden +## `Annotated`-Abhängigkeiten wiederverwenden { #share-annotated-dependencies } In den Beispielen oben sehen Sie, dass es ein kleines bisschen **Codeverdoppelung** gibt. @@ -139,7 +139,7 @@ Die Abhängigkeiten funktionieren weiterhin wie erwartet, und das **Beste daran* Das ist besonders nützlich, wenn Sie es in einer **großen Codebasis** verwenden, in der Sie in **vielen *Pfadoperationen*** immer wieder **dieselben Abhängigkeiten** verwenden. -## `async` oder nicht `async` +## `async` oder nicht `async` { #to-async-or-not-to-async } Da Abhängigkeiten auch von **FastAPI** aufgerufen werden (so wie Ihre *Pfadoperation-Funktionen*), gelten beim Definieren Ihrer Funktionen die gleichen Regeln. @@ -151,11 +151,11 @@ Es spielt keine Rolle. **FastAPI** weiß, was zu tun ist. /// note | Hinweis -Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-eile){.internal-link target=_blank}-Abschnitt über `async` und `await` in der Dokumentation. +Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-a-hurry){.internal-link target=_blank}-Abschnitt über `async` und `await` in der Dokumentation. /// -## Integriert in OpenAPI +## Integriert in OpenAPI { #integrated-with-openapi } Alle Requestdeklarationen, -validierungen und -anforderungen Ihrer Abhängigkeiten (und Unterabhängigkeiten) werden in dasselbe OpenAPI-Schema integriert. @@ -163,9 +163,9 @@ Die interaktive Dokumentation enthält also auch alle Informationen aus diesen A -## Einfache Verwendung +## Einfache Verwendung { #simple-usage } -Näher betrachtet, werden *Pfadoperation-Funktionen* deklariert, um verwendet zu werden, wann immer ein *Pfad* und eine *Operation* übereinstimmen, und dann kümmert sich **FastAPI** darum, die Funktion mit den richtigen Parametern aufzurufen, die Daten aus der Anfrage extrahierend. +Näher betrachtet, werden *Pfadoperation-Funktionen* deklariert, um verwendet zu werden, wann immer ein *Pfad* und eine *Operation* übereinstimmen, und dann kümmert sich **FastAPI** darum, die Funktion mit den richtigen Parametern aufzurufen, die Daten aus dem Request extrahierend. Tatsächlich funktionieren alle (oder die meisten) Webframeworks auf die gleiche Weise. @@ -181,7 +181,7 @@ Andere gebräuchliche Begriffe für dieselbe Idee der „Abhängigkeitsinjektion * Injectables * Komponenten -## **FastAPI**-Plugins +## **FastAPI**-Plugins { #fastapi-plug-ins } Integrationen und „Plugins“ können mit dem **Dependency Injection** System erstellt werden. Aber tatsächlich besteht **keine Notwendigkeit, „Plugins“ zu erstellen**, da es durch die Verwendung von Abhängigkeiten möglich ist, eine unendliche Anzahl von Integrationen und Interaktionen zu deklarieren, die dann für Ihre *Pfadoperation-Funktionen* verfügbar sind. @@ -189,7 +189,7 @@ Und Abhängigkeiten können auf sehr einfache und intuitive Weise erstellt werde Beispiele hierfür finden Sie in den nächsten Kapiteln zu relationalen und NoSQL-Datenbanken, Sicherheit usw. -## **FastAPI**-Kompatibilität +## **FastAPI**-Kompatibilität { #fastapi-compatibility } Die Einfachheit des Dependency Injection Systems macht **FastAPI** kompatibel mit: @@ -199,10 +199,10 @@ Die Einfachheit des Dependency Injection Systems macht **FastAPI** kompatibel mi * externen APIs * Authentifizierungs- und Autorisierungssystemen * API-Nutzungs-Überwachungssystemen -* Responsedaten-Injektionssystemen +* Responsedaten-Injektionssystemen * usw. -## Einfach und leistungsstark +## Einfach und leistungsstark { #simple-and-powerful } Obwohl das hierarchische Dependency Injection System sehr einfach zu definieren und zu verwenden ist, ist es dennoch sehr mächtig. @@ -242,7 +242,7 @@ admin_user --> activate_user paying_user --> pro_items ``` -## Integriert mit **OpenAPI** +## Integriert mit **OpenAPI** { #integrated-with-openapi_1 } Alle diese Abhängigkeiten, während sie ihre Anforderungen deklarieren, fügen auch Parameter, Validierungen, usw. zu Ihren *Pfadoperationen* hinzu. diff --git a/docs/de/docs/tutorial/dependencies/sub-dependencies.md b/docs/de/docs/tutorial/dependencies/sub-dependencies.md index 66bdc7043..061952f92 100644 --- a/docs/de/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/de/docs/tutorial/dependencies/sub-dependencies.md @@ -1,4 +1,4 @@ -# Unterabhängigkeiten +# Unterabhängigkeiten { #sub-dependencies } Sie können Abhängigkeiten erstellen, die **Unterabhängigkeiten** haben. @@ -6,17 +6,17 @@ Diese können so **tief** verschachtelt sein, wie nötig. **FastAPI** kümmert sich darum, sie aufzulösen. -## Erste Abhängigkeit, „Dependable“ +## Erste Abhängigkeit, „Dependable“ { #first-dependency-dependable } Sie könnten eine erste Abhängigkeit („Dependable“) wie folgt erstellen: {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} -Diese deklariert einen optionalen Abfrageparameter `q` vom Typ `str` und gibt ihn dann einfach zurück. +Diese deklariert einen optionalen Query-Parameter `q` vom Typ `str` und gibt ihn dann einfach zurück. Das ist recht einfach (nicht sehr nützlich), hilft uns aber dabei, uns auf die Funktionsweise der Unterabhängigkeiten zu konzentrieren. -## Zweite Abhängigkeit, „Dependable“ und „Dependant“ +## Zweite Abhängigkeit, „Dependable“ und „Dependant“ { #second-dependency-dependable-and-dependant } Dann können Sie eine weitere Abhängigkeitsfunktion (ein „Dependable“) erstellen, die gleichzeitig eine eigene Abhängigkeit deklariert (also auch ein „Dependant“ ist): @@ -29,17 +29,17 @@ Betrachten wir die deklarierten Parameter: * Sie deklariert außerdem ein optionales `last_query`-Cookie, ein `str`. * Wenn der Benutzer keine Query `q` übermittelt hat, verwenden wir die zuletzt übermittelte Query, die wir zuvor in einem Cookie gespeichert haben. -## Die Abhängigkeit verwenden +## Die Abhängigkeit verwenden { #use-the-dependency } Diese Abhängigkeit verwenden wir nun wie folgt: {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info +/// info | Info Beachten Sie, dass wir in der *Pfadoperation-Funktion* nur eine einzige Abhängigkeit deklarieren, den `query_or_cookie_extractor`. -Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird. +Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat an `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird. /// @@ -54,13 +54,13 @@ read_query["/items/"] query_extractor --> query_or_cookie_extractor --> read_query ``` -## Dieselbe Abhängigkeit mehrmals verwenden +## Dieselbe Abhängigkeit mehrmals verwenden { #using-the-same-dependency-multiple-times } -Wenn eine Ihrer Abhängigkeiten mehrmals für dieselbe *Pfadoperation* deklariert wird, beispielsweise wenn mehrere Abhängigkeiten eine gemeinsame Unterabhängigkeit haben, wird **FastAPI** diese Unterabhängigkeit nur einmal pro Request aufrufen. +Wenn eine Ihrer Abhängigkeiten mehrmals für dieselbe *Pfadoperation* deklariert wird, beispielsweise wenn mehrere Abhängigkeiten eine gemeinsame Unterabhängigkeit haben, wird **FastAPI** diese Unterabhängigkeit nur einmal pro Request aufrufen. Und es speichert den zurückgegebenen Wert in einem „Cache“ und übergibt diesen gecachten Wert an alle „Dependanten“, die ihn in diesem spezifischen Request benötigen, anstatt die Abhängigkeit mehrmals für denselben Request aufzurufen. -In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhängigkeit bei jedem Schritt (möglicherweise mehrmals) in derselben Anfrage aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, können Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden: +In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhängigkeit bei jedem Schritt (möglicherweise mehrmals) in demselben Request aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, können Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden: //// tab | Python 3.8+ @@ -86,7 +86,7 @@ async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False //// -## Zusammenfassung +## Zusammenfassung { #recap } Abgesehen von all den ausgefallenen Wörtern, die hier verwendet werden, ist das **Dependency Injection**-System recht simpel. diff --git a/docs/de/docs/tutorial/encoder.md b/docs/de/docs/tutorial/encoder.md index 5678d7b8f..25dc6fa18 100644 --- a/docs/de/docs/tutorial/encoder.md +++ b/docs/de/docs/tutorial/encoder.md @@ -1,12 +1,12 @@ -# JSON-kompatibler Encoder +# JSON-kompatibler Encoder { #json-compatible-encoder } -Es gibt Fälle, da möchten Sie einen Datentyp (etwa ein Pydantic-Modell) in etwas konvertieren, das kompatibel mit JSON ist (etwa ein `dict`, eine `list`e, usw.). +Es gibt Fälle, da möchten Sie einen Datentyp (etwa ein Pydantic-Modell) in etwas konvertieren, das kompatibel mit JSON ist (etwa ein `dict`, eine `list`, usw.). Zum Beispiel, wenn Sie es in einer Datenbank speichern möchten. Dafür bietet **FastAPI** eine Funktion `jsonable_encoder()`. -## `jsonable_encoder` verwenden +## `jsonable_encoder` verwenden { #using-the-jsonable-encoder } Stellen wir uns vor, Sie haben eine Datenbank `fake_db`, die nur JSON-kompatible Daten entgegennimmt. diff --git a/docs/de/docs/tutorial/extra-data-types.md b/docs/de/docs/tutorial/extra-data-types.md index 334f32f7b..5002f0534 100644 --- a/docs/de/docs/tutorial/extra-data-types.md +++ b/docs/de/docs/tutorial/extra-data-types.md @@ -1,4 +1,4 @@ -# Zusätzliche Datentypen +# Zusätzliche Datentypen { #extra-data-types } Bisher haben Sie gängige Datentypen verwendet, wie zum Beispiel: @@ -12,12 +12,12 @@ Sie können aber auch komplexere Datentypen verwenden. Und Sie haben immer noch dieselbe Funktionalität wie bisher gesehen: * Großartige Editor-Unterstützung. -* Datenkonvertierung bei eingehenden Requests. -* Datenkonvertierung für Response-Daten. +* Datenkonvertierung bei eingehenden Requests. +* Datenkonvertierung für Response-Daten. * Datenvalidierung. * Automatische Annotation und Dokumentation. -## Andere Datentypen +## Andere Datentypen { #other-data-types } Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können: @@ -36,11 +36,11 @@ Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können: * `datetime.timedelta`: * Ein Python-`datetime.timedelta`. * Wird in Requests und Responses als `float` der Gesamtsekunden dargestellt. - * Pydantic ermöglicht auch die Darstellung als „ISO 8601 Zeitdifferenz-Kodierung“, Weitere Informationen finden Sie in der Dokumentation. + * Pydantic ermöglicht auch die Darstellung als „ISO 8601 Zeitdifferenz-Kodierung“, siehe die Dokumentation für weitere Informationen. * `frozenset`: * Wird in Requests und Responses wie ein `set` behandelt: * Bei Requests wird eine Liste gelesen, Duplikate entfernt und in ein `set` umgewandelt. - * Bei Responses wird das `set` in eine `list`e umgewandelt. + * Bei Responses wird das `set` in eine `list` umgewandelt. * Das generierte Schema zeigt an, dass die `set`-Werte eindeutig sind (unter Verwendung von JSON Schemas `uniqueItems`). * `bytes`: * Standard-Python-`bytes`. @@ -49,9 +49,9 @@ Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können: * `Decimal`: * Standard-Python-`Decimal`. * In Requests und Responses wird es wie ein `float` behandelt. -* Sie können alle gültigen Pydantic-Datentypen hier überprüfen: Pydantic data types. +* Sie können alle gültigen Pydantic-Datentypen hier überprüfen: Pydantic-Datentypen. -## Beispiel +## Beispiel { #example } Hier ist ein Beispiel für eine *Pfadoperation* mit Parametern, die einige der oben genannten Typen verwenden. diff --git a/docs/de/docs/tutorial/extra-models.md b/docs/de/docs/tutorial/extra-models.md index 6aad1c0f4..967e8535b 100644 --- a/docs/de/docs/tutorial/extra-models.md +++ b/docs/de/docs/tutorial/extra-models.md @@ -1,42 +1,42 @@ -# Extramodelle +# Extramodelle { #extra-models } -Fahren wir beim letzten Beispiel fort. Es gibt normalerweise mehrere zusammengehörende Modelle. +Im Anschluss an das vorherige Beispiel ist es üblich, mehr als ein zusammenhängendes Modell zu haben. -Insbesondere Benutzermodelle, denn: +Dies gilt insbesondere für Benutzermodelle, denn: -* Das **hereinkommende Modell** sollte ein Passwort haben können. -* Das **herausgehende Modell** sollte kein Passwort haben. -* Das **Datenbankmodell** sollte wahrscheinlich ein gehashtes Passwort haben. +* Das **Eingabemodell** muss ein Passwort enthalten können. +* Das **Ausgabemodell** sollte kein Passwort haben. +* Das **Datenbankmodell** müsste wahrscheinlich ein gehashtes Passwort haben. /// danger | Gefahr -Speichern Sie niemals das Klartext-Passwort eines Benutzers. Speichern Sie immer den „sicheren Hash“, den Sie verifizieren können. +Speichern Sie niemals das Klartextpasswort eines Benutzers. Speichern Sie immer einen „sicheren Hash“, den Sie dann verifizieren können. -Falls Ihnen das nichts sagt, in den [Sicherheits-Kapiteln](security/simple-oauth2.md#passwort-hashing){.internal-link target=_blank} werden Sie lernen, was ein „Passwort-Hash“ ist. +Wenn Sie nicht wissen, was das ist, werden Sie in den [Sicherheitskapiteln](security/simple-oauth2.md#password-hashing){.internal-link target=_blank} lernen, was ein „Passworthash“ ist. /// -## Mehrere Modelle +## Mehrere Modelle { #multiple-models } -Hier der generelle Weg, wie die Modelle mit ihren Passwort-Feldern aussehen könnten, und an welchen Orten sie verwendet werden würden. +Hier ist eine allgemeine Idee, wie die Modelle mit ihren Passwortfeldern aussehen könnten und an welchen Stellen sie verwendet werden: {* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} -/// info +/// info | Info -In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt. +In Pydantic v1 hieß die Methode `.dict()`, in Pydantic v2 wurde sie deprecatet (aber weiterhin unterstützt) und in `.model_dump()` umbenannt. -Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können. +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()` +### Über `**user_in.dict()` { #about-user-in-dict } -#### Pydantic's `.dict()` +#### Die `.dict()`-Methode von Pydantic { #pydantics-dict } `user_in` ist ein Pydantic-Modell der Klasse `UserIn`. -Pydantic-Modelle haben eine `.dict()`-Methode, die ein `dict` mit den Daten des Modells zurückgibt. +Pydantic-Modelle haben eine `.dict()`-Methode, die ein `dict` mit den Daten des Modells zurückgibt. Wenn wir also ein Pydantic-Objekt `user_in` erstellen, etwa so: @@ -44,21 +44,21 @@ Wenn wir also ein Pydantic-Objekt `user_in` erstellen, etwa so: user_in = UserIn(username="john", password="secret", email="john.doe@example.com") ``` -und wir rufen seine `.dict()`-Methode auf: +und dann aufrufen: ```Python user_dict = user_in.dict() ``` -dann haben wir jetzt in der Variable `user_dict` ein `dict` mit den gleichen Daten (es ist ein `dict` statt eines Pydantic-Modellobjekts). +haben wir jetzt ein `dict` mit den Daten in der Variablen `user_dict` (es ist ein `dict` statt eines Pydantic-Modellobjekts). -Wenn wir es ausgeben: +Und wenn wir aufrufen: ```Python print(user_dict) ``` -bekommen wir ein Python-`dict`: +würden wir ein Python-`dict` erhalten mit: ```Python { @@ -69,17 +69,17 @@ bekommen wir ein Python-`dict`: } ``` -#### Ein `dict` entpacken +#### Ein `dict` entpacken { #unpacking-a-dict } -Wenn wir ein `dict` wie `user_dict` nehmen, und es einer Funktion (oder Klassenmethode) mittels `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüsselwort-Argumente übergeben. +Wenn wir ein `dict` wie `user_dict` nehmen und es einer Funktion (oder Klasse) mit `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüsselwort-Argumente übergeben. -Wenn wir also das `user_dict` von oben nehmen und schreiben: +Setzen wir also das `user_dict` von oben ein: ```Python UserInDB(**user_dict) ``` -dann ist das ungefähr äquivalent zu: +so ist das äquivalent zu: ```Python UserInDB( @@ -90,7 +90,7 @@ UserInDB( ) ``` -Oder, präziser, `user_dict` wird direkt verwendet, welche Werte es auch immer haben mag: +Oder genauer gesagt, dazu, `user_dict` direkt zu verwenden, mit welchen Inhalten es auch immer in der Zukunft haben mag: ```Python UserInDB( @@ -101,34 +101,34 @@ UserInDB( ) ``` -#### Ein Pydantic-Modell aus den Inhalten eines anderen erstellen. +#### Ein Pydantic-Modell aus dem Inhalt eines anderen { #a-pydantic-model-from-the-contents-of-another } -Da wir in obigem Beispiel `user_dict` mittels `user_in.dict()` erzeugt haben, ist dieser Code: +Da wir im obigen Beispiel `user_dict` von `user_in.dict()` bekommen haben, wäre dieser Code: ```Python user_dict = user_in.dict() UserInDB(**user_dict) ``` -äquivalent zu: +gleichwertig zu: ```Python UserInDB(**user_in.dict()) ``` -... weil `user_in.dict()` ein `dict` ist, und dann lassen wir Python es „entpacken“, indem wir es `UserInDB` übergeben, mit vorangestelltem `**`. +... weil `user_in.dict()` ein `dict` ist, und dann lassen wir Python es „entpacken“, indem wir es an `UserInDB` mit vorangestelltem `**` übergeben. -Wir erhalten also ein Pydantic-Modell aus den Daten eines anderen Pydantic-Modells. +Auf diese Weise erhalten wir ein Pydantic-Modell aus den Daten eines anderen Pydantic-Modells. -#### Ein `dict` entpacken und zusätzliche Schlüsselwort-Argumente +#### Ein `dict` entpacken und zusätzliche Schlüsselwort-Argumente { #unpacking-a-dict-and-extra-keywords } -Und dann fügen wir ein noch weiteres Schlüsselwort-Argument hinzu, `hashed_password=hashed_password`: +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) ``` -... was am Ende ergibt: +... was so ist wie: ```Python UserInDB( @@ -142,78 +142,81 @@ UserInDB( /// warning | Achtung -Die Hilfsfunktionen `fake_password_hasher` und `fake_save_user` demonstrieren nur den möglichen Fluss der Daten und bieten natürlich keine echte Sicherheit. +Die unterstützenden zusätzlichen Funktionen `fake_password_hasher` und `fake_save_user` dienen nur zur Demo eines möglichen Datenflusses, bieten jedoch natürlich keine echte Sicherheit. /// -## Verdopplung vermeiden +## Verdopplung vermeiden { #reduce-duplication } -Reduzierung von Code-Verdoppelung ist eine der Kern-Ideen von **FastAPI**. +Die Reduzierung von Code-Verdoppelung ist eine der Kernideen von **FastAPI**. -Weil Verdoppelung von Code die Wahrscheinlichkeit von Fehlern, Sicherheitsproblemen, Desynchronisation (Code wird nur an einer Stelle verändert, aber nicht an einer anderen), usw. erhöht. +Da die Verdopplung von Code die Wahrscheinlichkeit von Fehlern, Sicherheitsproblemen, Problemen mit der Desynchronisation des Codes (wenn Sie an einer Stelle, aber nicht an der anderen aktualisieren) usw. erhöht. -Unsere Modelle teilen alle eine Menge der Daten und verdoppeln Attribut-Namen und -Typen. +Und diese Modelle teilen alle eine Menge der Daten und verdoppeln Attributnamen und -typen. -Das können wir besser machen. +Wir könnten es besser machen. -Wir deklarieren ein `UserBase`-Modell, das als Basis für unsere anderen Modelle dient. Dann können wir Unterklassen erstellen, die seine Attribute (Typdeklarationen, Validierungen, usw.) erben. +Wir können ein `UserBase`-Modell deklarieren, das als Basis für unsere anderen Modelle dient. Und dann können wir Unterklassen dieses Modells erstellen, die seine Attribute (Typdeklarationen, Validierung usw.) erben. -Die ganze Datenkonvertierung, -validierung, -dokumentation, usw. wird immer noch wie gehabt funktionieren. +Die ganze Datenkonvertierung, -validierung, -dokumentation usw. wird immer noch wie gewohnt funktionieren. -Auf diese Weise beschreiben wir nur noch die Unterschiede zwischen den Modellen (mit Klartext-`password`, mit `hashed_password`, und ohne Passwort): +Auf diese Weise können wir nur die Unterschiede zwischen den Modellen (mit Klartext-`password`, mit `hashed_password` und ohne Passwort) deklarieren: {* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} -## `Union`, oder `anyOf` +## `Union` oder `anyOf` { #union-or-anyof } -Sie können deklarieren, dass eine Response eine `Union` mehrerer Typen ist, sprich, einer dieser Typen. +Sie können deklarieren, dass eine Response eine `Union` mehrerer Typen ist, das bedeutet, dass die Response einer von ihnen ist. -Das wird in OpenAPI mit `anyOf` angezeigt. +Dies wird in OpenAPI mit `anyOf` definiert. -Um das zu tun, verwenden Sie Pythons Standard-Typhinweis `typing.Union`: +Um das zu tun, verwenden Sie den Standard-Python-Typhinweis `typing.Union`: /// note | Hinweis -Listen Sie, wenn Sie eine `Union` definieren, denjenigen Typ zuerst, der am spezifischsten ist, gefolgt von den weniger spezifischen Typen. Im Beispiel oben, in `Union[PlaneItem, CarItem]` also den spezifischeren `PlaneItem` vor dem weniger spezifischen `CarItem`. +Wenn Sie eine `Union` definieren, listen Sie den spezifischeren Typ zuerst auf, gefolgt vom weniger spezifischen Typ. Im Beispiel unten steht `PlaneItem` vor `CarItem` in `Union[PlaneItem, CarItem]`. /// {* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} -### `Union` in Python 3.10 -In diesem Beispiel übergeben wir dem Argument `response_model` den Wert `Union[PlaneItem, CarItem]`. +### `Union` in Python 3.10 { #union-in-python-3-10 } -Da wir es als **Wert einem Argument überreichen**, statt es als **Typannotation** zu verwenden, müssen wir `Union` verwenden, selbst in Python 3.10. +In diesem Beispiel übergeben wir `Union[PlaneItem, CarItem]` als Wert des Arguments `response_model`. -Wenn es eine Typannotation gewesen wäre, hätten wir auch den vertikalen Trennstrich verwenden können, wie in: +Da wir es als **Wert an ein Argument übergeben**, anstatt es in einer **Typannotation** zu verwenden, müssen wir `Union` verwenden, sogar in Python 3.10. + +Wäre es eine Typannotation gewesen, hätten wir den vertikalen Strich verwenden können, wie in: ```Python some_variable: PlaneItem | CarItem ``` -Aber wenn wir das in der Zuweisung `response_model=PlaneItem | CarItem` machen, erhalten wir eine Fehlermeldung, da Python versucht, eine **ungültige Operation** zwischen `PlaneItem` und `CarItem` durchzuführen, statt es als Typannotation zu interpretieren. +Aber wenn wir das in der Zuweisung `response_model=PlaneItem | CarItem` machen, würden wir einen Fehler erhalten, weil Python versuchen würde, eine **ungültige Operation** zwischen `PlaneItem` und `CarItem` auszuführen, anstatt es als Typannotation zu interpretieren. -## Listen von Modellen +## Liste von Modellen { #list-of-models } -Genauso können Sie eine Response deklarieren, die eine Liste von Objekten ist. +Auf die gleiche Weise können Sie Responses von Listen von Objekten deklarieren. -Verwenden Sie dafür Pythons Standard `typing.List` (oder nur `list` in Python 3.9 und darüber): +Dafür verwenden Sie Pythons Standard-`typing.List` (oder nur `list` in Python 3.9 und höher): {* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} -## Response mit beliebigem `dict` -Sie könne auch eine Response deklarieren, die ein beliebiges `dict` zurückgibt, bei dem nur die Typen der Schlüssel und der Werte bekannt sind, ohne ein Pydantic-Modell zu verwenden. +## Response mit beliebigem `dict` { #response-with-arbitrary-dict } -Das ist nützlich, wenn Sie die gültigen Feld-/Attribut-Namen von vorneherein nicht wissen (was für ein Pydantic-Modell notwendig ist). +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. -In diesem Fall können Sie `typing.Dict` verwenden (oder nur `dict` in Python 3.9 und darüber): +Dies ist nützlich, wenn Sie die gültigen Feld-/Attributnamen nicht im Voraus kennen (die für ein Pydantic-Modell benötigt werden würden). + +In diesem Fall können Sie `typing.Dict` verwenden (oder nur `dict` in Python 3.9 und höher): {* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} -## Zusammenfassung + +## Zusammenfassung { #recap } Verwenden Sie gerne mehrere Pydantic-Modelle und vererben Sie je nach Bedarf. -Sie brauchen kein einzelnes Datenmodell pro Einheit, wenn diese Einheit verschiedene Zustände annehmen kann. So wie unsere Benutzer-„Einheit“, welche einen Zustand mit `password`, einen mit `password_hash` und einen ohne Passwort hatte. +Sie brauchen kein einzelnes Datenmodell pro Einheit, wenn diese Einheit in der Lage sein muss, verschiedene „Zustände“ zu haben. Wie im Fall der Benutzer-„Einheit“ mit einem Zustand einschließlich `password`, `password_hash` und ohne Passwort. diff --git a/docs/de/docs/tutorial/first-steps.md b/docs/de/docs/tutorial/first-steps.md index 3104c8d61..374127c17 100644 --- a/docs/de/docs/tutorial/first-steps.md +++ b/docs/de/docs/tutorial/first-steps.md @@ -1,64 +1,80 @@ -# Erste Schritte +# Erste Schritte { #first-steps } Die einfachste FastAPI-Datei könnte wie folgt aussehen: {* ../../docs_src/first_steps/tutorial001.py *} -Kopieren Sie dies in eine Datei `main.py`. +Kopieren Sie das in eine Datei `main.py`. Starten Sie den Live-Server:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-/// note | Hinweis - -Der Befehl `uvicorn main:app` bezieht sich auf: - -* `main`: die Datei `main.py` (das sogenannte Python-„Modul“). -* `app`: das Objekt, welches in der Datei `main.py` mit der Zeile `app = FastAPI()` erzeugt wurde. -* `--reload`: lässt den Server nach Codeänderungen neu starten. Verwenden Sie das nur während der Entwicklung. - -/// - In der Konsolenausgabe sollte es eine Zeile geben, die ungefähr so aussieht: ```hl_lines="4" INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` -Diese Zeile zeigt die URL, unter der Ihre Anwendung auf Ihrem lokalen Computer bereitgestellt wird. +Diese Zeile zeigt die URL, unter der Ihre App auf Ihrem lokalen Computer bereitgestellt wird. -### Testen Sie es +### Es testen { #check-it } -Öffnen Sie Ihren Browser unter http://127.0.0.1:8000. +Öffnen Sie Ihren Browser unter http://127.0.0.1:8000. -Sie werden folgende JSON-Response sehen: +Sie werden die JSON-Response sehen: ```JSON {"message": "Hello World"} ``` -### Interaktive API-Dokumentation +### Interaktive API-Dokumentation { #interactive-api-docs } -Gehen Sie als Nächstes auf http://127.0.0.1:8000/docs . +Gehen Sie als Nächstes auf http://127.0.0.1:8000/docs. Sie werden die automatisch erzeugte, interaktive API-Dokumentation sehen (bereitgestellt durch Swagger UI): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) -### Alternative API-Dokumentation +### Alternative API-Dokumentation { #alternative-api-docs } Gehen Sie nun auf http://127.0.0.1:8000/redoc. @@ -66,31 +82,31 @@ Dort sehen Sie die alternative, automatische Dokumentation (bereitgestellt durch ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -### OpenAPI +### OpenAPI { #openapi } **FastAPI** generiert ein „Schema“ mit all Ihren APIs unter Verwendung des **OpenAPI**-Standards zur Definition von APIs. -#### „Schema“ +#### „Schema“ { #schema } Ein „Schema“ ist eine Definition oder Beschreibung von etwas. Nicht der eigentliche Code, der es implementiert, sondern lediglich eine abstrakte Beschreibung. -#### API-„Schema“ +#### API-„Schema“ { #api-schema } -In diesem Fall ist OpenAPI eine Spezifikation, die vorschreibt, wie ein Schema für Ihre API zu definieren ist. +In diesem Fall ist OpenAPI eine Spezifikation, die vorschreibt, wie ein Schema für Ihre API zu definieren ist. Diese Schemadefinition enthält Ihre API-Pfade, die möglichen Parameter, welche diese entgegennehmen, usw. -#### Daten-„Schema“ +#### Daten-„Schema“ { #data-schema } Der Begriff „Schema“ kann sich auch auf die Form von Daten beziehen, wie z. B. einen JSON-Inhalt. In diesem Fall sind die JSON-Attribute und deren Datentypen, usw. gemeint. -#### OpenAPI und JSON Schema +#### OpenAPI und JSON Schema { #openapi-and-json-schema } OpenAPI definiert ein API-Schema für Ihre API. Dieses Schema enthält Definitionen (oder „Schemas“) der Daten, die von Ihrer API unter Verwendung von **JSON Schema**, dem Standard für JSON-Datenschemata, gesendet und empfangen werden. -#### Überprüfen Sie die `openapi.json` +#### Die `openapi.json` testen { #check-the-openapi-json } Falls Sie wissen möchten, wie das rohe OpenAPI-Schema aussieht: FastAPI generiert automatisch ein JSON (Schema) mit den Beschreibungen Ihrer gesamten API. @@ -119,7 +135,7 @@ Es wird ein JSON angezeigt, welches ungefähr so aussieht: ... ``` -#### Wofür OpenAPI gedacht ist +#### Wofür OpenAPI gedacht ist { #what-is-openapi-for } Das OpenAPI-Schema ist die Grundlage für die beiden enthaltenen interaktiven Dokumentationssysteme. @@ -127,9 +143,9 @@ Es gibt dutzende Alternativen, die alle auf OpenAPI basieren. Sie können jede d Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generieren, die mit Ihrer API kommunizieren. Zum Beispiel für Frontend-, Mobile- oder IoT-Anwendungen. -## Rückblick, Schritt für Schritt +## Zusammenfassung, Schritt für Schritt { #recap-step-by-step } -### Schritt 1: Importieren von `FastAPI` +### Schritt 1: `FastAPI` importieren { #step-1-import-fastapi } {* ../../docs_src/first_steps/tutorial001.py hl[1] *} @@ -137,13 +153,13 @@ Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generier /// note | Technische Details -`FastAPI` ist eine Klasse, die direkt von `Starlette` erbt. +`FastAPI` ist eine Klasse, die direkt von `Starlette` erbt. Sie können alle Starlette-Funktionalitäten auch mit `FastAPI` nutzen. /// -### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“ +### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“ { #step-2-create-a-fastapi-instance } {* ../../docs_src/first_steps/tutorial001.py hl[3] *} @@ -151,37 +167,9 @@ In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI Dies wird der Hauptinteraktionspunkt für die Erstellung all Ihrer APIs sein. -Die Variable `app` ist dieselbe, auf die sich der Befehl `uvicorn` bezieht: +### Schritt 3: Erstellen einer *Pfadoperation* { #step-3-create-a-path-operation } -
- -```console -$ uvicorn main:app --reload - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` - -
- -Wenn Sie Ihre Anwendung wie folgt erstellen: - -{* ../../docs_src/first_steps/tutorial002.py hl[3] *} - -Und in eine Datei `main.py` einfügen, dann würden Sie `uvicorn` wie folgt aufrufen: - -
- -```console -$ uvicorn main:my_awesome_api --reload - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` - -
- -### Schritt 3: Erstellen einer *Pfadoperation* - -#### Pfad +#### Pfad { #path } „Pfad“ bezieht sich hier auf den letzten Teil der URL, beginnend mit dem ersten `/`. @@ -197,7 +185,7 @@ https://example.com/items/foo /items/foo ``` -/// info +/// info | Info Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet. @@ -205,7 +193,7 @@ Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet. Bei der Erstellung einer API ist der „Pfad“ die wichtigste Möglichkeit zur Trennung von „Anliegen“ und „Ressourcen“. -#### Operation +#### Operation { #operation } „Operation“ bezieht sich hier auf eine der HTTP-„Methoden“. @@ -240,16 +228,16 @@ In OpenAPI wird folglich jede dieser HTTP-Methoden als „Operation“ bezeichne Wir werden sie auch „**Operationen**“ nennen. -#### Definieren eines *Pfadoperation-Dekorators* +#### Definieren eines *Pfadoperation-Dekorators* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001.py hl[6] *} -Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von Anfragen zuständig ist, die an: +Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von Requests zuständig ist, die an: - * den Pfad `/` - * unter der Verwendung der get-Operation gehen +* den Pfad `/` +* unter der Verwendung der get-Operation gehen -/// info | `@decorator` Information +/// info | `@decorator` Info Diese `@something`-Syntax wird in Python „Dekorator“ genannt. @@ -269,7 +257,7 @@ Sie können auch die anderen Operationen verwenden: * `@app.put()` * `@app.delete()` -Oder die exotischeren: +Und die exotischeren: * `@app.options()` * `@app.head()` @@ -288,7 +276,7 @@ Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktion /// -### Schritt 4: Definieren der **Pfadoperation-Funktion** +### Schritt 4: Definieren der **Pfadoperation-Funktion** { #step-4-define-the-path-operation-function } Das ist unsere „**Pfadoperation-Funktion**“: @@ -300,7 +288,7 @@ Das ist unsere „**Pfadoperation-Funktion**“: Dies ist eine Python-Funktion. -Sie wird von **FastAPI** immer dann aufgerufen, wenn sie eine Anfrage an die URL "`/`" mittels einer `GET`-Operation erhält. +Sie wird von **FastAPI** immer dann aufgerufen, wenn sie einen Request an die URL „`/`“ mittels einer `GET`-Operation erhält. In diesem Fall handelt es sich um eine `async`-Funktion. @@ -312,11 +300,11 @@ Sie könnten sie auch als normale Funktion anstelle von `async def` definieren: /// note | Hinweis -Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-eile){.internal-link target=_blank}. +Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-a-hurry){.internal-link target=_blank}. /// -### Schritt 5: den Inhalt zurückgeben +### Schritt 5: den Inhalt zurückgeben { #step-5-return-the-content } {* ../../docs_src/first_steps/tutorial001.py hl[8] *} @@ -324,12 +312,12 @@ Sie können ein `dict`, eine `list`, einzelne Werte wie `str`, `int`, usw. zurü Sie können auch Pydantic-Modelle zurückgeben (dazu später mehr). -Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert werden (einschließlich ORMs usw.). Versuchen Sie, Ihre Lieblingsobjekte zu verwenden. Es ist sehr wahrscheinlich, dass sie bereits unterstützt werden. +Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert werden (einschließlich ORMs, usw.). Versuchen Sie, Ihre Lieblingsobjekte zu verwenden. Es ist sehr wahrscheinlich, dass sie bereits unterstützt werden. -## Zusammenfassung +## Zusammenfassung { #recap } * Importieren Sie `FastAPI`. * Erstellen Sie eine `app` Instanz. -* Schreiben Sie einen **Pfadoperation-Dekorator** (wie z. B. `@app.get("/")`). -* Schreiben Sie eine **Pfadoperation-Funktion** (wie z. B. oben `def root(): ...`). -* Starten Sie den Entwicklungsserver (z. B. `uvicorn main:app --reload`). +* Schreiben Sie einen **Pfadoperation-Dekorator** unter Verwendung von Dekoratoren wie `@app.get("/")`. +* Definieren Sie eine **Pfadoperation-Funktion**, zum Beispiel `def root(): ...`. +* Starten Sie den Entwicklungsserver mit dem Befehl `fastapi dev`. diff --git a/docs/de/docs/tutorial/handling-errors.md b/docs/de/docs/tutorial/handling-errors.md index 31bc6d328..51294f44f 100644 --- a/docs/de/docs/tutorial/handling-errors.md +++ b/docs/de/docs/tutorial/handling-errors.md @@ -1,49 +1,49 @@ -# Fehlerbehandlung +# Fehler behandeln { #handling-errors } -Es gibt viele Situationen, in denen Sie einem Client, der Ihre API benutzt, einen Fehler zurückgeben müssen. +Es gibt viele Situationen, in denen Sie einem Client, der Ihre API nutzt, einen Fehler mitteilen müssen. -Dieser Client könnte ein Browser mit einem Frontend, Code von jemand anderem, ein IoT-Gerät, usw., sein. +Dieser Client könnte ein Browser mit einem Frontend sein, ein Code von jemand anderem, ein IoT-Gerät usw. -Sie müssten beispielsweise einem Client sagen: +Sie könnten dem Client mitteilen müssen, dass: -* Dass er nicht die notwendigen Berechtigungen hat, eine Aktion auszuführen. -* Dass er zu einer Ressource keinen Zugriff hat. -* Dass die Ressource, auf die er zugreifen möchte, nicht existiert. +* Der Client nicht genügend Berechtigungen für diese Operation hat. +* Der Client keinen Zugriff auf diese Ressource hat. +* Die Ressource, auf die der Client versucht hat, zuzugreifen, nicht existiert. * usw. -In diesen Fällen geben Sie normalerweise einen **HTTP-Statuscode** im Bereich **400** (400 bis 499) zurück. +In diesen Fällen würden Sie normalerweise einen **HTTP-Statuscode** im Bereich **400** (von 400 bis 499) zurückgeben. -Das ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“er Statuscodes bedeuten, dass der Request in einem bestimmten Aspekt ein „Success“ („Erfolg“) war. +Dies ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“-Statuscodes bedeuten, dass der Request in irgendeiner Weise erfolgreich war. -Die Statuscodes im 400er-Bereich bedeuten hingegen, dass es einen Fehler gab. +Die Statuscodes im Bereich 400 bedeuten hingegen, dass es einen Fehler seitens des Clients gab. -Erinnern Sie sich an all diese **404 Not Found** Fehler (und Witze)? +Erinnern Sie sich an all diese **„404 Not Found“** Fehler (und Witze)? -## `HTTPException` verwenden +## `HTTPException` verwenden { #use-httpexception } -Um HTTP-Responses mit Fehlern zum Client zurückzugeben, verwenden Sie `HTTPException`. +Um HTTP-Responses mit Fehlern an den Client zurückzugeben, verwenden Sie `HTTPException`. -### `HTTPException` importieren +### `HTTPException` importieren { #import-httpexception } {* ../../docs_src/handling_errors/tutorial001.py hl[1] *} -### Eine `HTTPException` in Ihrem Code auslösen +### Eine `HTTPException` in Ihrem Code auslösen { #raise-an-httpexception-in-your-code } -`HTTPException` ist eine normale Python-Exception mit einigen zusätzlichen Daten, die für APIs relevant sind. +`HTTPException` ist eine normale Python-Exception mit zusätzlichen Daten, die für APIs relevant sind. -Weil es eine Python-Exception ist, geben Sie sie nicht zurück, (`return`), sondern Sie lösen sie aus (`raise`). +Weil es eine Python-Exception ist, geben Sie sie nicht zurück (`return`), sondern lösen sie aus (`raise`). -Das bedeutet auch, wenn Sie in einer Hilfsfunktion sind, die Sie von ihrer *Pfadoperation-Funktion* aus aufrufen, und Sie lösen eine `HTTPException` von innerhalb dieser Hilfsfunktion aus, dann wird der Rest der *Pfadoperation-Funktion* nicht ausgeführt, sondern der Request wird sofort abgebrochen und der HTTP-Error der `HTTP-Exception` wird zum Client gesendet. +Das bedeutet auch, wenn Sie sich innerhalb einer Hilfsfunktion befinden, die Sie innerhalb Ihrer *Pfadoperation-Funktion* aufrufen, und Sie die `HTTPException` aus dieser Hilfsfunktion heraus auslösen, wird der restliche Code in der *Pfadoperation-Funktion* nicht ausgeführt. Der Request wird sofort abgebrochen und der HTTP-Error der `HTTPException` wird an den Client gesendet. -Der Vorteil, eine Exception auszulösen (`raise`), statt sie zurückzugeben (`return`) wird im Abschnitt über Abhängigkeiten und Sicherheit klarer werden. +Der Vorteil des Auslösens einer Exception gegenüber dem Zurückgeben eines Wertes wird im Abschnitt über Abhängigkeiten und Sicherheit deutlicher werden. -Im folgenden Beispiel lösen wir, wenn der Client eine ID anfragt, die nicht existiert, eine Exception mit dem Statuscode `404` aus. +In diesem Beispiel lösen wir eine Exception mit einem Statuscode von `404` aus, wenn der Client einen Artikel mit einer nicht existierenden ID anfordert: {* ../../docs_src/handling_errors/tutorial001.py hl[11] *} -### Die resultierende Response +### Die resultierende Response { #the-resulting-response } -Wenn der Client `http://example.com/items/foo` anfragt (ein `item_id` `"foo"`), erhält dieser Client einen HTTP-Statuscode 200 und folgende JSON-Response: +Wenn der Client `http://example.com/items/foo` anfordert (ein `item_id` `"foo"`), erhält dieser Client einen HTTP-Statuscode 200 und diese JSON-Response: ```JSON { @@ -51,7 +51,7 @@ Wenn der Client `http://example.com/items/foo` anfragt (ein `item_id` `"foo"`), } ``` -Aber wenn der Client `http://example.com/items/bar` anfragt (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „Not Found“-Fehler), und eine JSON-Response wie folgt: +Aber wenn der Client `http://example.com/items/bar` anfordert (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „Not Found“-Error) und eine JSON-Response wie: ```JSON { @@ -61,41 +61,41 @@ Aber wenn der Client `http://example.com/items/bar` anfragt (ein nicht-existiere /// tip | Tipp -Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der nach JSON konvertiert werden kann, nicht nur `str`. +Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der in JSON konvertiert werden kann, nicht nur `str`. -Zum Beispiel ein `dict`, eine `list`, usw. +Sie könnten ein `dict`, eine `list`, usw. übergeben. -Das wird automatisch von **FastAPI** gehandhabt und der Wert nach JSON konvertiert. +Diese werden von **FastAPI** automatisch gehandhabt und in JSON konvertiert. /// -## Benutzerdefinierte Header hinzufügen +## Benutzerdefinierte Header hinzufügen { #add-custom-headers } -Es gibt Situationen, da ist es nützlich, dem HTTP-Error benutzerdefinierte Header hinzufügen zu können, etwa in einigen Sicherheitsszenarien. +Es gibt Situationen, in denen es nützlich ist, dem HTTP-Error benutzerdefinierte Header hinzuzufügen. Zum Beispiel in einigen Sicherheitsszenarien. -Sie müssen das wahrscheinlich nicht direkt in ihrem Code verwenden. +Sie werden es wahrscheinlich nicht direkt in Ihrem Code verwenden müssen. -Aber falls es in einem fortgeschrittenen Szenario notwendig ist, können Sie benutzerdefinierte Header wie folgt hinzufügen: +Aber falls Sie es für ein fortgeschrittenes Szenario benötigen, können Sie benutzerdefinierte Header hinzufügen: {* ../../docs_src/handling_errors/tutorial002.py hl[14] *} -## Benutzerdefinierte Exceptionhandler definieren +## Benutzerdefinierte Exceptionhandler installieren { #install-custom-exception-handlers } -Sie können benutzerdefinierte Exceptionhandler hinzufügen, mithilfe derselben Werkzeuge für Exceptions von Starlette. +Sie können benutzerdefinierte Exceptionhandler mit den gleichen Exception-Werkzeugen von Starlette hinzufügen. -Nehmen wir an, Sie haben eine benutzerdefinierte Exception `UnicornException`, die Sie (oder eine Bibliothek, die Sie verwenden) `raise`n könnten. +Angenommen, Sie haben eine benutzerdefinierte Exception `UnicornException`, die Sie (oder eine Bibliothek, die Sie verwenden) `raise`n könnten. Und Sie möchten diese Exception global mit FastAPI handhaben. -Sie könnten einen benutzerdefinierten Exceptionhandler mittels `@app.exception_handler()` hinzufügen: +Sie könnten einen benutzerdefinierten Exceptionhandler mit `@app.exception_handler()` hinzufügen: {* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *} -Wenn Sie nun `/unicorns/yolo` anfragen, `raise`d die *Pfadoperation* eine `UnicornException`. +Hier, wenn Sie `/unicorns/yolo` anfordern, wird die *Pfadoperation* eine `UnicornException` `raise`n. Aber diese wird von `unicorn_exception_handler` gehandhabt. -Sie erhalten also einen sauberen Error mit einem Statuscode `418` und dem JSON-Inhalt: +Sie erhalten also einen sauberen Fehler mit einem HTTP-Statuscode von `418` und dem JSON-Inhalt: ```JSON {"message": "Oops! yolo did something. There goes a rainbow..."} @@ -103,33 +103,33 @@ Sie erhalten also einen sauberen Error mit einem Statuscode `418` und dem JSON-I /// note | Technische Details -Sie können auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden. +Sie könnten auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden. -**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `Request`. +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, nur als Annehmlichkeit für Sie, den Entwickler. Aber die meisten verfügbaren Responses kommen direkt von Starlette. Dasselbe gilt für `Request`. /// -## Die Default-Exceptionhandler überschreiben +## Die Default-Exceptionhandler überschreiben { #override-the-default-exception-handlers } **FastAPI** hat einige Default-Exceptionhandler. -Diese Handler kümmern sich darum, Default-JSON-Responses zurückzugeben, wenn Sie eine `HTTPException` `raise`n, und wenn der Request ungültige Daten enthält. +Diese Handler sind dafür verantwortlich, die Default-JSON-Responses zurückzugeben, wenn Sie eine `HTTPException` `raise`n und wenn der Request ungültige Daten enthält. -Sie können diese Exceptionhandler mit ihren eigenen überschreiben. +Sie können diese Exceptionhandler mit Ihren eigenen überschreiben. -### Requestvalidierung-Exceptions überschreiben +### Überschreiben von Request-Validierungs-Exceptions { #override-request-validation-exceptions } Wenn ein Request ungültige Daten enthält, löst **FastAPI** intern einen `RequestValidationError` aus. -Und bietet auch einen Default-Exceptionhandler dafür. +Und es enthält auch einen Default-Exceptionhandler für diesen. -Um diesen zu überschreiben, importieren Sie den `RequestValidationError` und verwenden Sie ihn in `@app.exception_handler(RequestValidationError)`, um Ihren Exceptionhandler zu dekorieren. +Um diesen zu überschreiben, importieren Sie den `RequestValidationError` und verwenden Sie ihn mit `@app.exception_handler(RequestValidationError)`, um den Exceptionhandler zu dekorieren. -Der Exceptionhandler wird einen `Request` und die Exception entgegennehmen. +Der Exceptionhandler erhält einen `Request` und die Exception. {* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *} -Wenn Sie nun `/items/foo` besuchen, erhalten Sie statt des Default-JSON-Errors: +Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen JSON-Fehlers mit: ```JSON { @@ -146,7 +146,7 @@ Wenn Sie nun `/items/foo` besuchen, erhalten Sie statt des Default-JSON-Errors: } ``` -eine Textversion: +eine Textversion mit: ``` 1 validation error @@ -154,27 +154,27 @@ path -> item_id value is not a valid integer (type=type_error.integer) ``` -#### `RequestValidationError` vs. `ValidationError` +#### `RequestValidationError` vs. `ValidationError` { #requestvalidationerror-vs-validationerror } /// warning | Achtung -Das folgende sind technische Details, die Sie überspringen können, wenn sie für Sie nicht wichtig sind. +Dies sind technische Details, die Sie überspringen können, wenn sie für Sie jetzt nicht wichtig sind. /// -`RequestValidationError` ist eine Unterklasse von Pydantics `ValidationError`. +`RequestValidationError` ist eine Unterklasse von Pydantics `ValidationError`. -**FastAPI** verwendet diesen, sodass Sie, wenn Sie ein Pydantic-Modell für `response_model` verwenden, und ihre Daten fehlerhaft sind, einen Fehler in ihrem Log sehen. +**FastAPI** verwendet diesen so, dass, wenn Sie ein Pydantic-Modell in `response_model` verwenden und Ihre Daten einen Fehler haben, Sie den Fehler in Ihrem Log sehen. -Aber der Client/Benutzer sieht ihn nicht. Stattdessen erhält der Client einen „Internal Server Error“ mit einem HTTP-Statuscode `500`. +Aber der Client/Benutzer wird ihn nicht sehen. Stattdessen erhält der Client einen „Internal Server Error“ mit einem HTTP-Statuscode `500`. -Das ist, wie es sein sollte, denn wenn Sie einen Pydantic-`ValidationError` in Ihrer *Response* oder irgendwo sonst in ihrem Code haben (es sei denn, im *Request* des Clients), ist das tatsächlich ein Bug in ihrem Code. +Es sollte so sein, denn wenn Sie einen Pydantic `ValidationError` in Ihrer *Response* oder irgendwo anders in Ihrem Code haben (nicht im *Request* des Clients), ist es tatsächlich ein Fehler in Ihrem Code. -Und während Sie den Fehler beheben, sollten ihre Clients/Benutzer keinen Zugriff auf interne Informationen über den Fehler haben, da das eine Sicherheitslücke aufdecken könnte. +Und während Sie den Fehler beheben, sollten Ihre Clients/Benutzer keinen Zugriff auf interne Informationen über den Fehler haben, da das eine Sicherheitslücke aufdecken könnte. -### den `HTTPException`-Handler überschreiben +### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler } -Genauso können Sie den `HTTPException`-Handler überschreiben. +Auf die gleiche Weise können Sie den `HTTPException`-Handler überschreiben. Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zurückgeben wollen: @@ -182,21 +182,21 @@ Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zu /// note | Technische Details -Sie können auch `from starlette.responses import PlainTextResponse` verwenden. +Sie könnten auch `from starlette.responses import PlainTextResponse` verwenden. -**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, nur als Annehmlichkeit für Sie, den Entwickler. Aber die meisten verfügbaren Responses kommen direkt von Starlette. /// -### Den `RequestValidationError`-Body verwenden +### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body } Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten. -Sie könnten diesen verwenden, während Sie Ihre Anwendung entwickeln, um den Body zu loggen und zu debuggen, ihn zum Benutzer zurückzugeben, usw. +Sie könnten diesen während der Entwicklung Ihrer Anwendung verwenden, um den Body zu loggen und zu debuggen, ihn an den Benutzer zurückzugeben usw. {* ../../docs_src/handling_errors/tutorial005.py hl[14] *} -Jetzt versuchen Sie, einen ungültigen Artikel zu senden: +Versuchen Sie nun, einen ungültigen Artikel zu senden: ```JSON { @@ -205,7 +205,7 @@ Jetzt versuchen Sie, einen ungültigen Artikel zu senden: } ``` -Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind, und welche den empfangenen Body enthält. +Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind und die den empfangenen Body enthält: ```JSON hl_lines="12-15" { @@ -226,30 +226,30 @@ Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind, und w } ``` -#### FastAPIs `HTTPException` vs. Starlettes `HTTPException` +#### FastAPIs `HTTPException` vs. Starlettes `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception } **FastAPI** hat seine eigene `HTTPException`. -Und **FastAPI**s `HTTPException`-Fehlerklasse erbt von Starlettes `HTTPException`-Fehlerklasse. +Und die `HTTPException`-Fehlerklasse von **FastAPI** erbt von der `HTTPException`-Fehlerklasse von Starlette. -Der einzige Unterschied besteht darin, dass **FastAPIs** `HTTPException` alles für das Feld `detail` akzeptiert, was nach JSON konvertiert werden kann, während Starlettes `HTTPException` nur Strings zulässt. +Der einzige Unterschied besteht darin, dass die `HTTPException` von **FastAPI** beliebige JSON-konvertierbare Daten für das `detail`-Feld akzeptiert, während die `HTTPException` von Starlette nur Strings dafür akzeptiert. -Sie können also weiterhin **FastAPI**s `HTTPException` wie üblich in Ihrem Code auslösen. +Sie können also weiterhin die `HTTPException` von **FastAPI** wie üblich in Ihrem Code auslösen. -Aber wenn Sie einen Exceptionhandler registrieren, registrieren Sie ihn für Starlettes `HTTPException`. +Aber wenn Sie einen Exceptionhandler registrieren, sollten Sie ihn für die `HTTPException` von Starlette registrieren. -Auf diese Weise wird Ihr Handler, wenn irgendein Teil von Starlettes internem Code, oder eine Starlette-Erweiterung, oder -Plugin eine Starlette-`HTTPException` auslöst, in der Lage sein, diese zu fangen und zu handhaben. +Auf diese Weise, wenn irgendein Teil des internen Codes von Starlette, oder eine Starlette-Erweiterung oder ein Plug-in, eine Starlette `HTTPException` auslöst, wird Ihr Handler in der Lage sein, diese abzufangen und zu handhaben. -Damit wir in diesem Beispiel beide `HTTPException`s im selben Code haben können, benennen wir Starlettes Exception um zu `StarletteHTTPException`: +Um in diesem Beispiel beide `HTTPException`s im selben Code zu haben, wird die Exception von Starlette zu `StarletteHTTPException` umbenannt: ```Python from starlette.exceptions import HTTPException as StarletteHTTPException ``` -### **FastAPI**s Exceptionhandler wiederverwenden +### Die Exceptionhandler von **FastAPI** wiederverwenden { #reuse-fastapis-exception-handlers } -Wenn Sie die Exception zusammen mit denselben Default-Exceptionhandlern von **FastAPI** verwenden möchten, können Sie die Default-Exceptionhandler von `fastapi.Exception_handlers` importieren und wiederverwenden: +Wenn Sie die Exception zusammen mit den gleichen Default-Exceptionhandlern von **FastAPI** verwenden möchten, können Sie die Default-Exceptionhandler aus `fastapi.exception_handlers` importieren und wiederverwenden: {* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *} -In diesem Beispiel `print`en Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht, aber Sie sehen, worauf wir hinauswollen. Sie können mit der Exception etwas machen und dann einfach die Default-Exceptionhandler wiederverwenden. +In diesem Beispiel geben Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht aus, aber Sie verstehen das Prinzip. Sie können die Exception verwenden und dann einfach die Default-Exceptionhandler wiederverwenden. diff --git a/docs/de/docs/tutorial/header-param-models.md b/docs/de/docs/tutorial/header-param-models.md new file mode 100644 index 000000000..8c1bf61ae --- /dev/null +++ b/docs/de/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# Header-Parameter-Modelle { #header-parameter-models } + +Wenn Sie eine Gruppe verwandter **Header-Parameter** haben, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren. + +Dadurch können Sie das **Modell an mehreren Stellen wiederverwenden** und auch Validierungen und Metadaten für alle Parameter gleichzeitig deklarieren. 😎 + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓 + +/// + +## Header-Parameter mit einem Pydantic-Modell { #header-parameters-with-a-pydantic-model } + +Deklarieren Sie die erforderlichen **Header-Parameter** in einem **Pydantic-Modell** und dann den Parameter als `Header`: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den **Headern** des Request extrahieren und Ihnen das von Ihnen definierte Pydantic-Modell geben. + +## Die Dokumentation testen { #check-the-docs } + +Sie können die erforderlichen Header in der Dokumentationsoberfläche unter `/docs` sehen: + +
+ +
+ +## Zusätzliche Header verbieten { #forbid-extra-headers } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die **Header einschränken**, die Sie erhalten möchten. + +Sie können Pydantics Modellkonfiguration verwenden, um `extra` Felder zu verbieten (`forbid`): + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Wenn ein Client versucht, einige **zusätzliche Header** zu senden, erhält er eine **Error-Response**. + +Zum Beispiel, wenn der Client versucht, einen `tool`-Header mit einem Wert von `plumbus` zu senden, erhält er eine **Error-Response**, die ihm mitteilt, dass der Header-Parameter `tool` nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## Automatische Umwandlung von Unterstrichen deaktivieren { #disable-convert-underscores } + +Ähnlich wie bei regulären Header-Parametern werden bei der Verwendung von Unterstrichen in den Parameternamen diese **automatisch in Bindestriche umgewandelt**. + +Wenn Sie beispielsweise einen Header-Parameter `save_data` im Code haben, wird der erwartete HTTP-Header `save-data` sein, und er wird auch so in der Dokumentation angezeigt. + +Falls Sie aus irgendeinem Grund diese automatische Umwandlung deaktivieren müssen, können Sie dies auch für Pydantic-Modelle für Header-Parameter tun. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | Achtung + +Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass einige HTTP-Proxies und -Server die Verwendung von Headern mit Unterstrichen nicht zulassen. + +/// + +## Zusammenfassung { #summary } + +Sie können **Pydantic-Modelle** verwenden, um **Header** in **FastAPI** zu deklarieren. 😎 diff --git a/docs/de/docs/tutorial/header-params.md b/docs/de/docs/tutorial/header-params.md index 8283cc929..5c0bb3f87 100644 --- a/docs/de/docs/tutorial/header-params.md +++ b/docs/de/docs/tutorial/header-params.md @@ -1,50 +1,50 @@ -# Header-Parameter +# Header-Parameter { #header-parameters } -So wie `Query`-, `Path`-, und `Cookie`-Parameter können Sie auch Header-Parameter definieren. +Sie können Header-Parameter genauso definieren, wie Sie `Query`-, `Path`- und `Cookie`-Parameter definieren. -## `Header` importieren +## `Header` importieren { #import-header } Importieren Sie zuerst `Header`: {* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} -## `Header`-Parameter deklarieren +## `Header`-Parameter deklarieren { #declare-header-parameters } -Dann deklarieren Sie Ihre Header-Parameter, auf die gleiche Weise, wie Sie auch `Path`-, `Query`-, und `Cookie`-Parameter deklarieren. +Deklarieren Sie dann die Header-Parameter mit derselben Struktur wie bei `Path`, `Query` und `Cookie`. -Der erste Wert ist der Typ. Sie können `Header` die gehabten Extra Validierungs- und Beschreibungsparameter hinzufügen. Danach können Sie einen Defaultwert vergeben: +Sie können den Defaultwert sowie alle zusätzlichen Validierungs- oder Annotationsparameter definieren: {* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} /// note | Technische Details -`Header` ist eine Schwesterklasse von `Path`, `Query` und `Cookie`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse. +`Header` ist eine „Schwester“-Klasse von `Path`, `Query` und `Cookie`. Sie erbt ebenfalls von der gemeinsamen `Param`-Klasse. -Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Header` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben. +Aber denken Sie daran, dass bei der Nutzung von `Query`, `Path`, `Header` und anderen Importen aus `fastapi`, diese tatsächlich Funktionen sind, die spezielle Klassen zurückgeben. /// -/// info +/// info | Info -Um Header zu deklarieren, müssen Sie `Header` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden. +Um Header zu deklarieren, müssen Sie `Header` verwenden, da die Parameter sonst als Query-Parameter interpretiert werden würden. /// -## Automatische Konvertierung +## Automatische Konvertierung { #automatic-conversion } -`Header` hat weitere Funktionalität, zusätzlich zu der, die `Path`, `Query` und `Cookie` bereitstellen. +`Header` bietet etwas zusätzliche Funktionalität im Vergleich zu `Path`, `Query` und `Cookie`. -Die meisten Standard-Header benutzen als Trennzeichen einen Bindestrich, auch bekannt als das „Minus-Symbol“ (`-`). +Die meisten Standard-Header sind durch ein „Bindestrich“-Zeichen getrennt, auch bekannt als „Minus-Symbol“ (`-`). -Aber eine Variable wie `user-agent` ist in Python nicht gültig. +Aber eine Variable wie `user-agent` ist in Python ungültig. -Darum wird `Header` standardmäßig in Parameternamen den Unterstrich (`_`) zu einem Bindestrich (`-`) konvertieren. +Daher wird `Header` standardmäßig die Zeichen des Parameter-Namens von Unterstrich (`_`) zu Bindestrich (`-`) konvertieren, um die Header zu extrahieren und zu dokumentieren. -HTTP-Header sind außerdem unabhängig von Groß-/Kleinschreibung, darum können Sie sie mittels der Standard-Python-Schreibweise deklarieren (auch bekannt als "snake_case"). +Außerdem ist Groß-/Klein­schrei­bung in HTTP-Headern nicht relevant, daher können Sie sie im Standard-Python-Stil (auch bekannt als „snake_case“) deklarieren. -Sie können also `user_agent` schreiben, wie Sie es normalerweise in Python-Code machen würden, statt etwa die ersten Buchstaben groß zu schreiben, wie in `User_Agent`. +Sie können also `user_agent` verwenden, wie Sie es normalerweise im Python-Code tun würden, anstatt die Anfangsbuchstaben wie bei `User_Agent` großzuschreiben oder Ähnliches. -Wenn Sie aus irgendeinem Grund das automatische Konvertieren von Unterstrichen zu Bindestrichen abschalten möchten, setzen Sie den Parameter `convert_underscores` auf `False`. +Wenn Sie aus irgendeinem Grund die automatische Konvertierung von Unterstrichen zu Bindestrichen deaktivieren müssen, setzen Sie den Parameter `convert_underscores` von `Header` auf `False`: {* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} @@ -54,26 +54,26 @@ Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass manche HT /// -## Doppelte Header +## Doppelte Header { #duplicate-headers } -Es ist möglich, doppelte Header zu empfangen. Also den gleichen Header mit unterschiedlichen Werten. +Es ist möglich, doppelte Header zu empfangen. Damit ist gemeint, denselben Header mit mehreren Werten. -Sie können solche Fälle deklarieren, indem Sie in der Typdeklaration eine Liste verwenden. +Sie können solche Fälle definieren, indem Sie in der Typdeklaration eine Liste verwenden. -Sie erhalten dann alle Werte von diesem doppelten Header als Python-`list`e. +Sie erhalten dann alle Werte von diesem doppelten Header als Python-`list`. -Um zum Beispiel einen Header `X-Token` zu deklarieren, der mehrmals vorkommen kann, schreiben Sie: +Um beispielsweise einen `X-Token`-Header zu deklarieren, der mehrmals vorkommen kann, können Sie schreiben: {* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} -Wenn Sie mit einer *Pfadoperation* kommunizieren, die zwei HTTP-Header sendet, wie: +Wenn Sie mit dieser *Pfadoperation* kommunizieren und zwei HTTP-Header senden, wie: ``` X-Token: foo X-Token: bar ``` -Dann wäre die Response: +Dann wäre die Response: ```JSON { @@ -84,8 +84,8 @@ Dann wäre die Response: } ``` -## Zusammenfassung +## Zusammenfassung { #recap } -Deklarieren Sie Header mittels `Header`, auf die gleiche Weise wie bei `Query`, `Path` und `Cookie`. +Deklarieren Sie Header mit `Header`, wobei Sie dasselbe gängige Muster wie bei `Query`, `Path` und `Cookie` verwenden. -Machen Sie sich keine Sorgen um Unterstriche in ihren Variablen, **FastAPI** wird sich darum kümmern, diese zu konvertieren. +Und machen Sie sich keine Sorgen um Unterstriche in Ihren Variablen, **FastAPI** wird sich darum kümmern, sie zu konvertieren. diff --git a/docs/de/docs/tutorial/index.md b/docs/de/docs/tutorial/index.md index 3cbfe37f4..70a6b6a08 100644 --- a/docs/de/docs/tutorial/index.md +++ b/docs/de/docs/tutorial/index.md @@ -1,83 +1,95 @@ -# Tutorial – Benutzerhandbuch +# Tutorial – Benutzerhandbuch { #tutorial-user-guide } -Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie **FastAPI** und die meisten seiner Funktionen verwenden können. +Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie **FastAPI** mit den meisten seiner Funktionen verwenden können. -Jeder Abschnitt baut schrittweise auf den vorhergehenden auf. Diese Abschnitte sind aber nach einzelnen Themen gegliedert, sodass Sie direkt zu einem bestimmten Thema übergehen können, um Ihre speziellen API-Anforderungen zu lösen. +Jeder Abschnitt baut schrittweise auf den vorhergehenden auf, ist jedoch in einzelne Themen gegliedert, sodass Sie direkt zu einem bestimmten Thema übergehen können, um Ihre spezifischen API-Anforderungen zu lösen. -Außerdem dienen diese als zukünftige Referenz. +Es ist auch so gestaltet, dass es als zukünftige Referenz dient, sodass Sie jederzeit zurückkommen und genau das sehen, was Sie benötigen. -Dadurch können Sie jederzeit zurückkommen und sehen genau das, was Sie benötigen. +## Den Code ausführen { #run-the-code } -## Den Code ausführen +Alle Codeblöcke können kopiert und direkt verwendet werden (es sind tatsächlich getestete Python-Dateien). -Alle Codeblöcke können kopiert und direkt verwendet werden (da es sich um getestete Python-Dateien handelt). - -Um eines der Beispiele auszuführen, kopieren Sie den Code in eine Datei `main.py`, und starten Sie `uvicorn` mit: +Um eines der Beispiele auszuführen, kopieren Sie den Code in eine Datei `main.py` und starten Sie `fastapi dev` mit:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-Es wird **ausdrücklich empfohlen**, dass Sie den Code schreiben oder kopieren, ihn bearbeiten und lokal ausführen. +Es wird **dringend empfohlen**, den Code zu schreiben oder zu kopieren, ihn zu bearbeiten und lokal auszuführen. Die Verwendung in Ihrem eigenen Editor zeigt Ihnen die Vorteile von FastAPI am besten, wenn Sie sehen, wie wenig Code Sie schreiben müssen, all die Typprüfungen, die automatische Vervollständigung usw. --- -## FastAPI installieren +## FastAPI installieren { #install-fastapi } -Der erste Schritt besteht aus der Installation von FastAPI. +Der erste Schritt besteht darin, FastAPI zu installieren. -Für dieses Tutorial empfiehlt es sich, FastAPI mit allen optionalen Abhängigkeiten und Funktionen zu installieren: +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann **FastAPI installieren**:
```console -$ pip install "fastapi[all]" +$ pip install "fastapi[standard]" ---> 100% ```
-... das beinhaltet auch `uvicorn`, welchen Sie als Server verwenden können, der ihren Code ausführt. - /// note | Hinweis -Sie können die einzelnen Teile auch separat installieren. +Wenn Sie mit `pip install "fastapi[standard]"` installieren, werden einige optionale Standard-Abhängigkeiten mit installiert, einschließlich `fastapi-cloud-cli`, welches Ihnen das Deployment in der FastAPI Cloud ermöglicht. -Das folgende würden Sie wahrscheinlich tun, wenn Sie Ihre Anwendung in der Produktion einsetzen: +Wenn Sie diese optionalen Abhängigkeiten nicht haben möchten, können Sie stattdessen `pip install fastapi` installieren. -``` -pip install fastapi -``` - -Installieren Sie auch `uvicorn` als Server: - -``` -pip install "uvicorn[standard]" -``` - -Das gleiche gilt für jede der optionalen Abhängigkeiten, die Sie verwenden möchten. +Wenn Sie die Standard-Abhängigkeiten, aber ohne das `fastapi-cloud-cli` installieren möchten, können Sie mit `pip install "fastapi[standard-no-fastapi-cloud-cli]"` installieren. /// -## Handbuch für fortgeschrittene Benutzer +## Handbuch für fortgeschrittene Benutzer { #advanced-user-guide } -Es gibt auch ein **Handbuch für fortgeschrittene Benutzer**, welches Sie später nach diesem **Tutorial – Benutzerhandbuch** lesen können. +Es gibt auch ein **Handbuch für fortgeschrittene Benutzer**, das Sie nach diesem **Tutorial – Benutzerhandbuch** lesen können. -Das **Handbuch für fortgeschrittene Benutzer** baut auf diesem Tutorial auf, verwendet dieselben Konzepte und bringt Ihnen einige zusätzliche Funktionen bei. +Das **Handbuch für fortgeschrittene Benutzer** baut hierauf auf, verwendet dieselben Konzepte und bringt Ihnen einige zusätzliche Funktionen bei. -Allerdings sollten Sie zuerst das **Tutorial – Benutzerhandbuch** lesen (was Sie hier gerade tun). +Sie sollten jedoch zuerst das **Tutorial – Benutzerhandbuch** lesen (was Sie gerade tun). -Die Dokumentation ist so konzipiert, dass Sie mit dem **Tutorial – Benutzerhandbuch** eine vollständige Anwendung erstellen können und diese dann je nach Bedarf mit einigen der zusätzlichen Ideen aus dem **Handbuch für fortgeschrittene Benutzer** vervollständigen können. +Es ist so konzipiert, dass Sie mit dem **Tutorial – Benutzerhandbuch** eine vollständige Anwendung erstellen können und diese dann je nach Bedarf mit einigen der zusätzlichen Ideen aus dem **Handbuch für fortgeschrittene Benutzer** erweitern können. diff --git a/docs/de/docs/tutorial/metadata.md b/docs/de/docs/tutorial/metadata.md index 4809530be..44d02e6d8 100644 --- a/docs/de/docs/tutorial/metadata.md +++ b/docs/de/docs/tutorial/metadata.md @@ -1,10 +1,10 @@ -# Metadaten und URLs der Dokumentationen +# Metadaten und Dokumentations-URLs { #metadata-and-docs-urls } -Sie können mehrere Metadaten-Einstellungen für Ihre **FastAPI**-Anwendung konfigurieren. +Sie können mehrere Metadaten-Konfigurationen in Ihrer **FastAPI**-Anwendung anpassen. -## Metadaten für die API +## Metadaten für die API { #metadata-for-api } -Sie können die folgenden Felder festlegen, welche in der OpenAPI-Spezifikation und den Benutzeroberflächen der automatischen API-Dokumentation verwendet werden: +Sie können die folgenden Felder festlegen, die in der OpenAPI-Spezifikation und in den Benutzeroberflächen der automatischen API-Dokumentation verwendet werden: | Parameter | Typ | Beschreibung | |------------|------|-------------| @@ -13,16 +13,16 @@ Sie können die folgenden Felder festlegen, welche in der OpenAPI-Spezifikation | `description` | `str` | Eine kurze Beschreibung der API. Kann Markdown verwenden. | | `version` | `string` | Die Version der API. Das ist die Version Ihrer eigenen Anwendung, nicht die von OpenAPI. Zum Beispiel `2.5.0`. | | `terms_of_service` | `str` | Eine URL zu den Nutzungsbedingungen für die API. Falls angegeben, muss es sich um eine URL handeln. | -| `contact` | `dict` | Die Kontaktinformationen für die verfügbar gemachte API. Kann mehrere Felder enthalten.
contact-Felder
ParameterTypBeschreibung
namestrDer identifizierende Name der Kontaktperson/Organisation.
urlstrDie URL, die auf die Kontaktinformationen verweist. MUSS im Format einer URL vorliegen.
emailstrDie E-Mail-Adresse der Kontaktperson/Organisation. MUSS im Format einer E-Mail-Adresse vorliegen.
| -| `license_info` | `dict` | Die Lizenzinformationen für die verfügbar gemachte API. Kann mehrere Felder enthalten.
license_info-Felder
ParameterTypBeschreibung
namestrERFORDERLICH (wenn eine license_info festgelegt ist). Der für die API verwendete Lizenzname.
identifierstrEin SPDX-Lizenzausdruck für die API. Das Feld identifier und das Feld url schließen sich gegenseitig aus. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrEine URL zur Lizenz, die für die API verwendet wird. MUSS im Format einer URL vorliegen.
| +| `contact` | `dict` | Die Kontaktinformationen für die freigegebene API. Kann mehrere Felder enthalten.
contact-Felder
ParameterTypBeschreibung
namestrDer identifizierende Name der Kontaktperson/Organisation.
urlstrDie URL, die auf die Kontaktinformationen verweist. MUSS im Format einer URL vorliegen.
emailstrDie E-Mail-Adresse der Kontaktperson/Organisation. MUSS im Format einer E-Mail-Adresse vorliegen.
| +| `license_info` | `dict` | Die Lizenzinformationen für die freigegebene API. Kann mehrere Felder enthalten.
license_info-Felder
ParameterTypBeschreibung
namestrERFORDERLICH (wenn eine license_info festgelegt ist). Der für die API verwendete Lizenzname.
identifierstrEin SPDX-Lizenzausdruck für die API. Das Feld identifier und das Feld url schließen sich gegenseitig aus. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrEine URL zur Lizenz, die für die API verwendet wird. MUSS im Format einer URL vorliegen.
| Sie können diese wie folgt setzen: -{* ../../docs_src/metadata/tutorial001.py hl[3:16,19:32] *} +{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *} /// tip | Tipp -Sie können Markdown in das Feld `description` schreiben und es wird in der Ausgabe gerendert. +Sie können Markdown im Feld `description` verwenden, und es wird in der Ausgabe gerendert. /// @@ -30,7 +30,7 @@ Mit dieser Konfiguration würde die automatische API-Dokumentation wie folgt aus -## Lizenz-ID +## Lizenzkennung { #license-identifier } Seit OpenAPI 3.1.0 und FastAPI 0.99.0 können Sie die `license_info` auch mit einem `identifier` anstelle einer `url` festlegen. @@ -38,29 +38,29 @@ Zum Beispiel: {* ../../docs_src/metadata/tutorial001_1.py hl[31] *} -## Metadaten für Tags +## Metadaten für Tags { #metadata-for-tags } -Sie können mit dem Parameter `openapi_tags` auch zusätzliche Metadaten für die verschiedenen Tags hinzufügen, die zum Gruppieren Ihrer Pfadoperationen verwendet werden. +Sie können auch zusätzliche Metadaten für die verschiedenen Tags hinzufügen, die zum Gruppieren Ihrer Pfadoperationen verwendet werden, mit dem Parameter `openapi_tags`. -Es wird eine Liste benötigt, die für jedes Tag ein Dict enthält. +Er nimmt eine Liste entgegen, die für jeden Tag ein Dictionary enthält. -Jedes Dict kann Folgendes enthalten: +Jedes Dictionary kann Folgendes enthalten: * `name` (**erforderlich**): ein `str` mit demselben Tag-Namen, den Sie im Parameter `tags` in Ihren *Pfadoperationen* und `APIRouter`n verwenden. * `description`: ein `str` mit einer kurzen Beschreibung für das Tag. Sie kann Markdown enthalten und wird in der Benutzeroberfläche der Dokumentation angezeigt. * `externalDocs`: ein `dict`, das externe Dokumentation beschreibt mit: - * `description`: ein `str` mit einer kurzen Beschreibung für die externe Dokumentation. - * `url` (**erforderlich**): ein `str` mit der URL für die externe Dokumentation. + * `description`: ein `str` mit einer kurzen Beschreibung für die externe Dokumentation. + * `url` (**erforderlich**): ein `str` mit der URL für die externe Dokumentation. -### Metadaten für Tags erstellen +### Metadaten für Tags erstellen { #create-metadata-for-tags } -Versuchen wir das an einem Beispiel mit Tags für `users` und `items`. +Versuchen wir es mit einem Beispiel mit Tags für `users` und `items`. -Erstellen Sie Metadaten für Ihre Tags und übergeben Sie sie an den Parameter `openapi_tags`: +Erstellen Sie Metadaten für Ihre Tags und übergeben Sie diese an den Parameter `openapi_tags`: {* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *} -Beachten Sie, dass Sie Markdown in den Beschreibungen verwenden können. Beispielsweise wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt. +Beachten Sie, dass Sie Markdown innerhalb der Beschreibungen verwenden können. Zum Beispiel wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt. /// tip | Tipp @@ -68,31 +68,31 @@ Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen. /// -### Ihre Tags verwenden +### Ihre Tags verwenden { #use-your-tags } Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n), um diese verschiedenen Tags zuzuweisen: {* ../../docs_src/metadata/tutorial004.py hl[21,26] *} -/// info +/// info | Info Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags){.internal-link target=_blank}. /// -### Die Dokumentation anschauen +### Die Dokumentation testen { #check-the-docs } Wenn Sie nun die Dokumentation ansehen, werden dort alle zusätzlichen Metadaten angezeigt: -### Reihenfolge der Tags +### Reihenfolge der Tags { #order-of-tags } -Die Reihenfolge der Tag-Metadaten-Dicts definiert auch die Reihenfolge, in der diese in der Benutzeroberfläche der Dokumentation angezeigt werden. +Die Reihenfolge der Tag-Metadaten-Dictionarys definiert auch die Reihenfolge, in der diese in der Benutzeroberfläche der Dokumentation angezeigt werden. -Auch wenn beispielsweise `users` im Alphabet nach `items` kommt, wird es vor diesen angezeigt, da wir seine Metadaten als erstes Dict der Liste hinzugefügt haben. +Auch wenn beispielsweise `users` im Alphabet nach `items` kommt, wird es vor diesen angezeigt, da wir deren Metadaten als erstes Dictionary der Liste hinzugefügt haben. -## OpenAPI-URL +## OpenAPI-URL { #openapi-url } Standardmäßig wird das OpenAPI-Schema unter `/openapi.json` bereitgestellt. @@ -104,16 +104,16 @@ Um beispielsweise festzulegen, dass es unter `/api/v1/openapi.json` bereitgestel Wenn Sie das OpenAPI-Schema vollständig deaktivieren möchten, können Sie `openapi_url=None` festlegen, wodurch auch die Dokumentationsbenutzeroberflächen deaktiviert werden, die es verwenden. -## URLs der Dokumentationen +## Dokumentations-URLs { #docs-urls } Sie können die beiden enthaltenen Dokumentationsbenutzeroberflächen konfigurieren: * **Swagger UI**: bereitgestellt unter `/docs`. - * Sie können deren URL mit dem Parameter `docs_url` festlegen. - * Sie können sie deaktivieren, indem Sie `docs_url=None` festlegen. + * Sie können deren URL mit dem Parameter `docs_url` festlegen. + * Sie können sie deaktivieren, indem Sie `docs_url=None` festlegen. * **ReDoc**: bereitgestellt unter `/redoc`. - * Sie können deren URL mit dem Parameter `redoc_url` festlegen. - * Sie können sie deaktivieren, indem Sie `redoc_url=None` festlegen. + * Sie können deren URL mit dem Parameter `redoc_url` festlegen. + * Sie können sie deaktivieren, indem Sie `redoc_url=None` festlegen. Um beispielsweise Swagger UI so einzustellen, dass sie unter `/documentation` bereitgestellt wird, und ReDoc zu deaktivieren: diff --git a/docs/de/docs/tutorial/middleware.md b/docs/de/docs/tutorial/middleware.md index d3699be1b..a1e2ba9df 100644 --- a/docs/de/docs/tutorial/middleware.md +++ b/docs/de/docs/tutorial/middleware.md @@ -1,8 +1,8 @@ -# Middleware +# Middleware { #middleware } Sie können Middleware zu **FastAPI**-Anwendungen hinzufügen. -Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bevor er von einer bestimmten *Pfadoperation* verarbeitet wird. Und auch mit jeder **Response**, bevor sie zurückgegeben wird. +Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bevor er von einer bestimmten *Pfadoperation* verarbeitet wird. Und auch mit jeder **Response**, bevor sie zurückgegeben wird. * Sie nimmt jeden **Request** entgegen, der an Ihre Anwendung gesendet wird. * Sie kann dann etwas mit diesem **Request** tun oder beliebigen Code ausführen. @@ -15,11 +15,11 @@ Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bev Wenn Sie Abhängigkeiten mit `yield` haben, wird der Exit-Code *nach* der Middleware ausgeführt. -Wenn es Hintergrundaufgaben gab (später dokumentiert), werden sie *nach* allen Middlewares ausgeführt. +Wenn es Hintergrundtasks gab (dies wird später im [Hintergrundtasks](background-tasks.md){.internal-link target=_blank}-Abschnitt behandelt), werden sie *nach* allen Middlewares ausgeführt. /// -## Erstellung einer Middleware +## Eine Middleware erstellen { #create-a-middleware } Um eine Middleware zu erstellen, verwenden Sie den Dekorator `@app.middleware("http")` über einer Funktion. @@ -35,9 +35,9 @@ Die Middleware-Funktion erhält: /// tip | Tipp -Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können. Verwenden Sie dafür das Präfix 'X-'. +Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können unter Verwendung des `X-`-Präfixes. -Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfigurationen ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der Starlette-CORS-Dokumentation dokumentiert ist. +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfiguration ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der Starlettes CORS-Dokumentation dokumentiert ist. /// @@ -49,7 +49,7 @@ Sie könnten auch `from starlette.requests import Request` verwenden. /// -### Vor und nach der `response` +### Vor und nach der `response` { #before-and-after-the-response } Sie können Code hinzufügen, der mit dem `request` ausgeführt wird, bevor dieser von einer beliebigen *Pfadoperation* empfangen wird. @@ -59,8 +59,37 @@ Sie könnten beispielsweise einen benutzerdefinierten Header `X-Process-Time` hi {* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *} -## Andere Middlewares +/// tip | Tipp -Sie können später mehr über andere Middlewares in [Handbuch für fortgeschrittene Benutzer: Fortgeschrittene Middleware](../advanced/middleware.md){.internal-link target=_blank} lesen. +Hier verwenden wir `time.perf_counter()` anstelle von `time.time()`, da es für diese Anwendungsfälle präziser sein kann. 🤓 -In der nächsten Sektion erfahren Sie, wie Sie CORS mit einer Middleware behandeln können. +/// + +## Ausführungsreihenfolge bei mehreren Middlewares { #multiple-middleware-execution-order } + +Wenn Sie mehrere Middlewares hinzufügen, entweder mit dem `@app.middleware()` Dekorator oder der Methode `app.add_middleware()`, umschließt jede neue Middleware die Anwendung und bildet einen Stapel. Die zuletzt hinzugefügte Middleware ist die *äußerste*, und die erste ist die *innerste*. + +Auf dem Requestpfad läuft die *äußerste* Middleware zuerst. + +Auf dem Responsepfad läuft sie zuletzt. + +Zum Beispiel: + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +Dies führt zu folgender Ausführungsreihenfolge: + +* **Request**: MiddlewareB → MiddlewareA → Route + +* **Response**: Route → MiddlewareA → MiddlewareB + +Dieses Stapelverhalten stellt sicher, dass Middlewares in einer vorhersehbaren und kontrollierbaren Reihenfolge ausgeführt werden. + +## Andere Middlewares { #other-middlewares } + +Sie können später mehr über andere Middlewares im [Handbuch für fortgeschrittene Benutzer: Fortgeschrittene Middleware](../advanced/middleware.md){.internal-link target=_blank} lesen. + +In der nächsten Sektion erfahren Sie, wie Sie CORS mit einer Middleware behandeln können. diff --git a/docs/de/docs/tutorial/path-operation-configuration.md b/docs/de/docs/tutorial/path-operation-configuration.md index 7473e515b..c483f4e40 100644 --- a/docs/de/docs/tutorial/path-operation-configuration.md +++ b/docs/de/docs/tutorial/path-operation-configuration.md @@ -1,6 +1,6 @@ -# Pfadoperation-Konfiguration +# Pfadoperation-Konfiguration { #path-operation-configuration } -Es gibt mehrere Konfigurations-Parameter, die Sie Ihrem *Pfadoperation-Dekorator* übergeben können. +Es gibt mehrere Parameter, die Sie Ihrem *Pfadoperation-Dekorator* übergeben können, um ihn zu konfigurieren. /// warning | Achtung @@ -8,13 +8,13 @@ Beachten Sie, dass diese Parameter direkt dem *Pfadoperation-Dekorator* übergeb /// -## Response-Statuscode +## Response-Statuscode { #response-status-code } -Sie können den (HTTP-)`status_code` definieren, den die Response Ihrer *Pfadoperation* verwenden soll. +Sie können den (HTTP-)`status_code` definieren, der in der Response Ihrer *Pfadoperation* verwendet werden soll. Sie können direkt den `int`-Code übergeben, etwa `404`. -Aber falls Sie sich nicht mehr erinnern, wofür jede Nummer steht, können Sie die Abkürzungs-Konstanten in `status` verwenden: +Aber falls Sie sich nicht mehr erinnern, wofür jeder Nummerncode steht, können Sie die Abkürzungs-Konstanten in `status` verwenden: {* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} @@ -28,9 +28,9 @@ Sie können auch `from starlette import status` verwenden. /// -## Tags +## Tags { #tags } -Sie können Ihrer *Pfadoperation* Tags hinzufügen, mittels des Parameters `tags`, dem eine `list`e von `str`s übergeben wird (in der Regel nur ein `str`): +Sie können Ihrer *Pfadoperation* Tags hinzufügen, indem Sie dem Parameter `tags` eine `list`e von `str`s übergeben (in der Regel nur ein `str`): {* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} @@ -38,47 +38,47 @@ Diese werden zum OpenAPI-Schema hinzugefügt und von den automatischen Dokumenta -### Tags mittels Enumeration +### Tags mittels Enumeration { #tags-with-enums } -Wenn Sie eine große Anwendung haben, können sich am Ende **viele Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** nehmen. +Wenn Sie eine große Anwendung haben, können sich am Ende **viele Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** verwenden. In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern. -**FastAPI** unterstützt diese genauso wie einfache Strings: +**FastAPI** unterstützt das auf die gleiche Weise wie einfache Strings: {* ../../docs_src/path_operation_configuration/tutorial002b.py hl[1,8:10,13,18] *} -## Zusammenfassung und Beschreibung +## Zusammenfassung und Beschreibung { #summary-and-description } -Sie können eine Zusammenfassung (`summary`) und eine Beschreibung (`description`) hinzufügen: +Sie können eine `summary` und eine `description` hinzufügen: {* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[18:19] *} -## Beschreibung mittels Docstring +## Beschreibung mittels Docstring { #description-from-docstring } Da Beschreibungen oft mehrere Zeilen lang sind, können Sie die Beschreibung der *Pfadoperation* im Docstring der Funktion deklarieren, und **FastAPI** wird sie daraus auslesen. -Sie können im Docstring Markdown schreiben, es wird korrekt interpretiert und angezeigt (die Einrückung des Docstring beachtend). +Sie können Markdown im Docstring schreiben, es wird korrekt interpretiert und angezeigt (unter Berücksichtigung der Einrückung des Docstring). {* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} -In der interaktiven Dokumentation sieht das dann so aus: +Es wird in der interaktiven Dokumentation verwendet: -## Beschreibung der Response +## Beschreibung der Response { #response-description } -Die Response können Sie mit dem Parameter `response_description` beschreiben: +Sie können die Response mit dem Parameter `response_description` beschreiben: {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[19] *} -/// info +/// info | Info -beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht. +Beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht. /// -/// check +/// check | Testen OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt. @@ -88,13 +88,13 @@ Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolg -## Eine *Pfadoperation* deprecaten +## Eine *Pfadoperation* deprecaten { #deprecate-a-path-operation } -Wenn Sie eine *Pfadoperation* als deprecated kennzeichnen möchten, ohne sie zu entfernen, fügen Sie den Parameter `deprecated` hinzu: +Wenn Sie eine *Pfadoperation* als deprecatet kennzeichnen möchten, ohne sie zu entfernen, fügen Sie den Parameter `deprecated` hinzu: {* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *} -Sie wird in der interaktiven Dokumentation gut sichtbar als deprecated markiert werden: +Sie wird in der interaktiven Dokumentation gut sichtbar als deprecatet markiert werden: @@ -102,6 +102,6 @@ Vergleichen Sie, wie deprecatete und nicht-deprecatete *Pfadoperationen* aussehe -## Zusammenfassung +## Zusammenfassung { #recap } Sie können auf einfache Weise Metadaten für Ihre *Pfadoperationen* definieren, indem Sie den *Pfadoperation-Dekoratoren* Parameter hinzufügen. diff --git a/docs/de/docs/tutorial/path-params-numeric-validations.md b/docs/de/docs/tutorial/path-params-numeric-validations.md index 1acdd5b4e..36f466059 100644 --- a/docs/de/docs/tutorial/path-params-numeric-validations.md +++ b/docs/de/docs/tutorial/path-params-numeric-validations.md @@ -1,60 +1,56 @@ -# Pfad-Parameter und Validierung von Zahlen +# Pfad-Parameter und Validierung von Zahlen { #path-parameters-and-numeric-validations } -So wie Sie mit `Query` für Query-Parameter zusätzliche Validierungen und Metadaten hinzufügen können, können Sie das mittels `Path` auch für Pfad-Parameter tun. +So wie Sie mit `Query` für Query-Parameter zusätzliche Validierungen und Metadaten deklarieren können, können Sie mit `Path` die gleichen Validierungen und Metadaten für Pfad-Parameter deklarieren. -## `Path` importieren +## `Path` importieren { #import-path } -Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`. +Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`: {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info +/// info | Info -FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0. +FastAPI hat in Version 0.95.0 Unterstützung für `Annotated` hinzugefügt und es zur Verwendung empfohlen. -Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden. +Wenn Sie eine ältere Version haben, würden Fehler angezeigt werden, wenn Sie versuchen, `Annotated` zu verwenden. -Bitte [aktualisieren Sie FastAPI](../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden. +Stellen Sie sicher, dass Sie [FastAPI aktualisieren](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}, auf mindestens Version 0.95.1, bevor Sie `Annotated` verwenden. /// -## Metadaten deklarieren +## Metadaten deklarieren { #declare-metadata } -Sie können die gleichen Parameter deklarieren wie für `Query`. +Sie können dieselben Parameter wie für `Query` deklarieren. -Um zum Beispiel einen `title`-Metadaten-Wert für den Pfad-Parameter `item_id` zu deklarieren, schreiben Sie: +Um zum Beispiel einen `title`-Metadaten-Wert für den Pfad-Parameter `item_id` zu deklarieren, können Sie schreiben: {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} /// note | Hinweis -Ein Pfad-Parameter ist immer erforderlich, weil er Teil des Pfads sein muss. - -Sie sollten ihn daher mit `...` deklarieren, um ihn als erforderlich auszuzeichnen. - -Doch selbst wenn Sie ihn mit `None` deklarieren, oder einen Defaultwert setzen, bewirkt das nichts, er bleibt immer erforderlich. +Ein Pfad-Parameter ist immer erforderlich, da er Teil des Pfads sein muss. Selbst wenn Sie ihn mit `None` deklarieren oder einen Defaultwert setzen, würde das nichts ändern, er wäre dennoch immer erforderlich. /// -## Sortieren Sie die Parameter, wie Sie möchten +## Die Parameter sortieren, wie Sie möchten { #order-the-parameters-as-you-need } /// tip | Tipp -Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig. +Das ist wahrscheinlich nicht so wichtig oder notwendig, wenn Sie `Annotated` verwenden. /// -Nehmen wir an, Sie möchten den Query-Parameter `q` als erforderlichen `str` deklarieren. +Angenommen, Sie möchten den Query-Parameter `q` als erforderlichen `str` deklarieren. -Und Sie müssen sonst nichts anderes für den Parameter deklarieren, Sie brauchen also nicht wirklich `Query`. +Und Sie müssen sonst nichts anderes für diesen Parameter deklarieren, Sie brauchen also `Query` nicht wirklich. -Aber Sie brauchen `Path` für den `item_id`-Pfad-Parameter. Und Sie möchten aus irgendeinem Grund nicht `Annotated` verwenden. +Aber Sie müssen dennoch `Path` für den `item_id`-Pfad-Parameter verwenden. Und aus irgendeinem Grund möchten Sie `Annotated` nicht verwenden. -Python wird sich beschweren, wenn Sie einen Parameter mit Defaultwert vor einen Parameter ohne Defaultwert setzen. +Python wird sich beschweren, wenn Sie einen Wert mit einem „Default“ vor einem Wert ohne „Default“ setzen. -Aber Sie können die Reihenfolge der Parameter ändern, den Query-Parameter ohne Defaultwert zuerst. +Aber Sie können die Reihenfolge ändern und den Wert ohne Default (den Query-Parameter `q`) zuerst setzen. -Für **FastAPI** ist es nicht wichtig. Es erkennt die Parameter anhand ihres Namens, ihrer Typen, und ihrer Defaultwerte (`Query`, `Path`, usw.). Es kümmert sich nicht um die Reihenfolge. +Für **FastAPI** spielt es keine Rolle. Es erkennt die Parameter anhand ihrer Namen, Typen und Default-Deklarationen (`Query`, `Path`, usw.), es kümmert sich nicht um die Reihenfolge. Sie können Ihre Funktion also so deklarieren: @@ -66,104 +62,103 @@ Bevorzugen Sie die `Annotated`-Version, falls möglich. /// -```Python hl_lines="7" -{!> ../../docs_src/path_params_numeric_validations/tutorial002.py!} -``` +{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} //// -Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da Sie nicht die Funktions-Parameter-Defaultwerte für `Query()` oder `Path()` verwenden. +Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da es nicht darauf ankommt, dass Sie keine Funktionsparameter-Defaultwerte für `Query()` oder `Path()` verwenden. -{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py hl[10] *} +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} -## Sortieren Sie die Parameter wie Sie möchten: Tricks +## Die Parameter sortieren, wie Sie möchten: Tricks { #order-the-parameters-as-you-need-tricks } /// tip | Tipp -Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig. +Das ist wahrscheinlich nicht so wichtig oder notwendig, wenn Sie `Annotated` verwenden. /// -Hier ein **kleiner Trick**, der nützlich sein kann, aber Sie werden ihn nicht oft brauchen. +Hier ist ein **kleiner Trick**, der nützlich sein kann, obwohl Sie ihn nicht oft benötigen werden. -Wenn Sie eines der folgenden Dinge tun möchten: +Wenn Sie: -* den `q`-Parameter ohne `Query` oder irgendeinem Defaultwert deklarieren -* den Pfad-Parameter `item_id` mittels `Path` deklarieren -* die Parameter in einer unterschiedlichen Reihenfolge haben -* `Annotated` nicht verwenden +* den `q`-Query-Parameter sowohl ohne `Query` als auch ohne Defaultwert deklarieren +* den Pfad-Parameter `item_id` mit `Path` deklarieren +* sie in einer anderen Reihenfolge haben +* nicht `Annotated` verwenden -... dann hat Python eine kleine Spezial-Syntax für Sie. +... möchten, dann hat Python eine kleine Spezial-Syntax dafür. -Übergeben Sie der Funktion `*` als ersten Parameter. +Übergeben Sie `*`, als den ersten Parameter der Funktion. -Python macht nichts mit diesem `*`, aber es wird wissen, dass alle folgenden Parameter als Keyword-Argumente (Schlüssel-Wert-Paare), auch bekannt als kwargs, verwendet werden. Selbst wenn diese keinen Defaultwert haben. +Python wird nichts mit diesem `*` machen, aber es wird wissen, dass alle folgenden Parameter als Schlüsselwortargumente (Schlüssel-Wert-Paare) verwendet werden sollen, auch bekannt als kwargs. Selbst wenn diese keinen Defaultwert haben. {* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *} -### Besser mit `Annotated` +### Besser mit `Annotated` { #better-with-annotated } -Bedenken Sie, dass Sie, wenn Sie `Annotated` verwenden, dieses Problem nicht haben, weil Sie keine Defaultwerte für Ihre Funktionsparameter haben. Sie müssen daher wahrscheinlich auch nicht `*` verwenden. +Bedenken Sie, dass Sie, wenn Sie `Annotated` verwenden, da Sie keine Funktionsparameter-Defaultwerte verwenden, dieses Problem nicht haben werden und wahrscheinlich nicht `*` verwenden müssen. {* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} -## Validierung von Zahlen: Größer oder gleich +## Validierung von Zahlen: Größer oder gleich { #number-validations-greater-than-or-equal } -Mit `Query` und `Path` (und anderen, die Sie später kennenlernen), können Sie Zahlenbeschränkungen deklarieren. +Mit `Query` und `Path` (und anderen, die Sie später sehen werden) können Sie Zahlenbeschränkungen deklarieren. + +Hier, mit `ge=1`, muss `item_id` eine ganze Zahl sein, die „`g`reater than or `e`qual to“ (größer oder gleich) `1` ist. -Hier, mit `ge=1`, wird festgelegt, dass `item_id` eine Ganzzahl benötigt, die größer oder gleich `1` ist (`g`reater than or `e`qual). {* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} -## Validierung von Zahlen: Größer und kleiner oder gleich +## Validierung von Zahlen: Größer und kleiner oder gleich { #number-validations-greater-than-and-less-than-or-equal } -Das Gleiche trifft zu auf: +Das Gleiche gilt für: -* `gt`: `g`reater `t`han – größer als -* `le`: `l`ess than or `e`qual – kleiner oder gleich +* `gt`: `g`reater `t`han (größer als) +* `le`: `l`ess than or `e`qual (kleiner oder gleich) {* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} -## Validierung von Zahlen: Floats, größer und kleiner +## Validierung von Zahlen: Floats, größer und kleiner { #number-validations-floats-greater-than-and-less-than } -Zahlenvalidierung funktioniert auch für `float`-Werte. +Zahlenvalidierung funktioniert auch für `float`-Werte. -Hier wird es wichtig, in der Lage zu sein, gt zu deklarieren, und nicht nur ge, da Sie hiermit bestimmen können, dass ein Wert, zum Beispiel, größer als `0` sein muss, obwohl er kleiner als `1` ist. +Hier wird es wichtig, in der Lage zu sein, gt und nicht nur ge zu deklarieren. Da Sie mit dieser Option erzwingen können, dass ein Wert größer als `0` sein muss, selbst wenn er kleiner als `1` ist. -`0.5` wäre also ein gültiger Wert, aber nicht `0.0` oder `0`. +Also wäre `0.5` ein gültiger Wert. Aber `0.0` oder `0` nicht. -Das gleiche gilt für lt. +Und das Gleiche gilt für lt. {* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} -## Zusammenfassung +## Zusammenfassung { #recap } -Mit `Query` und `Path` (und anderen, die Sie noch nicht gesehen haben) können Sie Metadaten und Stringvalidierungen deklarieren, so wie in [Query-Parameter und Stringvalidierungen](query-params-str-validations.md){.internal-link target=_blank} beschrieben. +Mit `Query`, `Path` (und anderen, die Sie noch nicht gesehen haben) können Sie Metadaten und Stringvalidierungen auf die gleichen Weisen deklarieren wie in [Query-Parameter und Stringvalidierungen](query-params-str-validations.md){.internal-link target=_blank} beschrieben. -Und Sie können auch Validierungen für Zahlen deklarieren: +Und Sie können auch Zahlenvalidierungen deklarieren: -* `gt`: `g`reater `t`han – größer als -* `ge`: `g`reater than or `e`qual – größer oder gleich -* `lt`: `l`ess `t`han – kleiner als -* `le`: `l`ess than or `e`qual – kleiner oder gleich +* `gt`: `g`reater `t`han (größer als) +* `ge`: `g`reater than or `e`qual (größer oder gleich) +* `lt`: `l`ess `t`han (kleiner als) +* `le`: `l`ess than or `e`qual (kleiner oder gleich) -/// info +/// info | Info -`Query`, `Path`, und andere Klassen, die Sie später kennenlernen, sind Unterklassen einer allgemeinen `Param`-Klasse. +`Query`, `Path`, und andere Klassen, die Sie später sehen werden, sind Unterklassen einer gemeinsamen `Param`-Klasse. -Sie alle teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben. +Alle von ihnen teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben. /// /// note | Technische Details -`Query`, `Path` und andere, die Sie von `fastapi` importieren, sind tatsächlich Funktionen. +Wenn Sie `Query`, `Path` und andere von `fastapi` importieren, sind sie tatsächlich Funktionen. -Die, wenn sie aufgerufen werden, Instanzen der Klassen mit demselben Namen zurückgeben. +Die, wenn sie aufgerufen werden, Instanzen von Klassen mit demselben Namen zurückgeben. -Sie importieren also `Query`, welches eine Funktion ist. Aber wenn Sie es aufrufen, gibt es eine Instanz der Klasse zurück, die auch `Query` genannt wird. +Sie importieren also `Query`, was eine Funktion ist. Und wenn Sie sie aufrufen, gibt sie eine Instanz einer Klasse zurück, die auch `Query` genannt wird. Diese Funktionen existieren (statt die Klassen direkt zu verwenden), damit Ihr Editor keine Fehlermeldungen über ihre Typen ausgibt. -Auf diese Weise können Sie Ihren Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten. +Auf diese Weise können Sie Ihren normalen Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten. /// diff --git a/docs/de/docs/tutorial/path-params.md b/docs/de/docs/tutorial/path-params.md index 0767a937b..1db288fb8 100644 --- a/docs/de/docs/tutorial/path-params.md +++ b/docs/de/docs/tutorial/path-params.md @@ -1,18 +1,18 @@ -# Pfad-Parameter +# Pfad-Parameter { #path-parameters } -Sie können Pfad-„Parameter“ oder -„Variablen“ mit der gleichen Syntax deklarieren, welche in Python-Format-Strings verwendet wird: +Sie können Pfad-„Parameter“ oder -„Variablen“ mit der gleichen Syntax deklarieren, welche in Python-Formatstrings verwendet wird: {* ../../docs_src/path_params/tutorial001.py hl[6:7] *} Der Wert des Pfad-Parameters `item_id` wird Ihrer Funktion als das Argument `item_id` übergeben. -Wenn Sie dieses Beispiel ausführen und auf http://127.0.0.1:8000/items/foo gehen, sehen Sie als Response: +Wenn Sie dieses Beispiel ausführen und auf http://127.0.0.1:8000/items/foo gehen, sehen Sie als Response: ```JSON {"item_id":"foo"} ``` -## Pfad-Parameter mit Typen +## Pfad-Parameter mit Typen { #path-parameters-with-types } Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion deklarieren, mit Standard-Python-Typannotationen: @@ -20,13 +20,13 @@ Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion dekl In diesem Fall wird `item_id` als `int` deklariert, also als Ganzzahl. -/// check +/// check | Testen Dadurch erhalten Sie Editor-Unterstützung innerhalb Ihrer Funktion, mit Fehlerprüfungen, Codevervollständigung, usw. /// -## Daten-Konversion +## Daten-Konversion { #data-conversion } Wenn Sie dieses Beispiel ausführen und Ihren Browser unter http://127.0.0.1:8000/items/3 öffnen, sehen Sie als Response: @@ -34,15 +34,15 @@ Wenn Sie dieses Beispiel ausführen und Ihren Browser unter „parsen“. +Sprich, mit dieser Typdeklaration wird **FastAPI** den Request automatisch „parsen“. /// -## Datenvalidierung +## Datenvalidierung { #data-validation } Wenn Sie aber im Browser http://127.0.0.1:8000/items/foo besuchen, erhalten Sie eine hübsche HTTP-Fehlermeldung: @@ -66,23 +66,23 @@ Der Pfad-Parameter `item_id` hatte den Wert `"foo"`, was kein `int` ist. Die gleiche Fehlermeldung würde angezeigt werden, wenn Sie ein `float` (also eine Kommazahl) statt eines `int`s übergeben würden, wie etwa in: http://127.0.0.1:8000/items/4.2 -/// check +/// check | Testen Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung. Beachten Sie, dass die Fehlermeldung auch direkt die Stelle anzeigt, wo die Validierung nicht erfolgreich war. -Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit ihrer API interagiert. +Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit Ihrer API interagiert. /// -## Dokumentation +## Dokumentation { #documentation } Wenn Sie die Seite http://127.0.0.1:8000/docs in Ihrem Browser öffnen, sehen Sie eine automatische, interaktive API-Dokumentation: -/// check +/// check | Testen Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche). @@ -90,7 +90,7 @@ Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist. /// -## Nützliche Standards. Alternative Dokumentation +## Nützliche Standards, alternative Dokumentation { #standards-based-benefits-alternative-documentation } Und weil das generierte Schema vom OpenAPI-Standard kommt, gibt es viele kompatible Tools. @@ -100,15 +100,15 @@ Zum Beispiel bietet **FastAPI** selbst eine alternative API-Dokumentation (verwe Und viele weitere kompatible Tools. Inklusive Codegenerierung für viele Sprachen. -## Pydantic +## Pydantic { #pydantic } -Die ganze Datenvalidierung wird hinter den Kulissen von Pydantic durchgeführt, Sie profitieren also von dessen Vorteilen. Und Sie wissen, dass Sie in guten Händen sind. +Die ganze Datenvalidierung wird hinter den Kulissen von Pydantic durchgeführt, Sie profitieren also von dessen Vorteilen. Und Sie wissen, dass Sie in guten Händen sind. -Sie können für Typ Deklarationen auch `str`, `float`, `bool` und viele andere komplexe Datentypen verwenden. +Sie können für Typdeklarationen auch `str`, `float`, `bool` und viele andere komplexe Datentypen verwenden. Mehrere davon werden wir in den nächsten Kapiteln erkunden. -## Die Reihenfolge ist wichtig +## Die Reihenfolge ist wichtig { #order-matters } Wenn Sie *Pfadoperationen* erstellen, haben Sie manchmal einen fixen Pfad. @@ -128,23 +128,23 @@ Sie können eine Pfadoperation auch nicht erneut definieren: Die erste Definition wird immer verwendet werden, da ihr Pfad zuerst übereinstimmt. -## Vordefinierte Parameterwerte +## Vordefinierte Parameterwerte { #predefined-values } -Wenn Sie eine *Pfadoperation* haben, welche einen *Pfad-Parameter* hat, aber Sie wollen, dass dessen gültige Werte vordefiniert sind, können Sie ein Standard-Python `Enum` verwenden. +Wenn Sie eine *Pfadoperation* haben, welche einen *Pfad-Parameter* hat, aber Sie wollen, dass dessen gültige Werte vordefiniert sind, können Sie ein Standard-Python `Enum` verwenden. -### Erstellen Sie eine `Enum`-Klasse +### Eine `Enum`-Klasse erstellen { #create-an-enum-class } Importieren Sie `Enum` und erstellen Sie eine Unterklasse, die von `str` und `Enum` erbt. -Indem Sie von `str` erben, weiß die API Dokumentation, dass die Werte des Enums vom Typ `str` sein müssen, und wird in der Lage sein, korrekt zu rendern. +Indem Sie von `str` erben, weiß die API-Dokumentation, dass die Werte vom Typ `str` sein müssen, und wird in der Lage sein, korrekt zu rendern. Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaubten Werte sein werden: {* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *} -/// info +/// info | Info -Enumerationen (oder kurz Enums) gibt es in Python seit Version 3.4. +Enumerationen (oder Enums) gibt es in Python seit Version 3.4. /// @@ -154,31 +154,31 @@ Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das /// -### Deklarieren Sie einen *Pfad-Parameter* +### Einen *Pfad-Parameter* deklarieren { #declare-a-path-parameter } Dann erstellen Sie einen *Pfad-Parameter*, der als Typ die gerade erstellte Enum-Klasse hat (`ModelName`): {* ../../docs_src/path_params/tutorial005.py hl[16] *} -### Testen Sie es in der API-Dokumentation +### Die API-Dokumentation testen { #check-the-docs } Weil die erlaubten Werte für den *Pfad-Parameter* nun vordefiniert sind, kann die interaktive Dokumentation sie als Auswahl-Drop-Down anzeigen: -### Mit Python-*Enums* arbeiten +### Mit Python-*Enumerationen* arbeiten { #working-with-python-enumerations } -Der *Pfad-Parameter* wird ein *Member eines Enums* sein. +Der *Pfad-Parameter* wird ein *Member einer Enumeration* sein. -#### *Enum-Member* vergleichen +#### *Enumeration-Member* vergleichen { #compare-enumeration-members } -Sie können ihn mit einem Member Ihres Enums `ModelName` vergleichen: +Sie können ihn mit einem Member Ihrer Enumeration `ModelName` vergleichen: {* ../../docs_src/path_params/tutorial005.py hl[17] *} -#### *Enum-Wert* erhalten +#### *Enumerations-Wert* erhalten { #get-the-enumeration-value } -Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.value`, oder generell, `ihr_enum_member.value`: +Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.value`, oder generell, `your_enum_member.value`: {* ../../docs_src/path_params/tutorial005.py hl[20] *} @@ -188,7 +188,7 @@ Sie können den Wert `"lenet"` außerdem mittels `ModelName.lenet.value` abrufen /// -#### *Enum-Member* zurückgeben +#### *Enumeration-Member* zurückgeben { #return-enumeration-members } Sie können *Enum-Member* in ihrer *Pfadoperation* zurückgeben, sogar verschachtelt in einem JSON-Body (z. B. als `dict`). @@ -205,7 +205,7 @@ In Ihrem Client erhalten Sie eine JSON-Response, wie etwa: } ``` -## Pfad Parameter die Pfade enthalten +## Pfad-Parameter, die Pfade enthalten { #path-parameters-containing-paths } Angenommen, Sie haben eine *Pfadoperation* mit einem Pfad `/files/{file_path}`. @@ -213,7 +213,7 @@ Aber `file_path` soll selbst einen *Pfad* enthalten, etwa `home/johndoe/myfile.t Sprich, die URL für diese Datei wäre etwas wie: `/files/home/johndoe/myfile.txt`. -### OpenAPI Unterstützung +### OpenAPI-Unterstützung { #openapi-support } OpenAPI bietet nicht die Möglichkeit, dass ein *Pfad-Parameter* seinerseits einen *Pfad* enthalten kann, das würde zu Szenarios führen, die schwierig zu testen und zu definieren sind. @@ -221,7 +221,7 @@ Trotzdem können Sie das in **FastAPI** tun, indem Sie eines der internen Tools Die Dokumentation würde weiterhin funktionieren, allerdings wird nicht dokumentiert werden, dass der Parameter ein Pfad sein sollte. -### Pfad Konverter +### Pfad-Konverter { #path-convertor } Mittels einer Option direkt von Starlette können Sie einen *Pfad-Parameter* deklarieren, der einen Pfad enthalten soll, indem Sie eine URL wie folgt definieren: @@ -243,12 +243,12 @@ In dem Fall wäre die URL: `/files//home/johndoe/myfile.txt`, mit einem doppelte /// -## Zusammenfassung +## Zusammenfassung { #recap } In **FastAPI** erhalten Sie mittels kurzer, intuitiver Typdeklarationen: * Editor-Unterstützung: Fehlerprüfungen, Codevervollständigung, usw. -* Daten "parsen" +* Daten "parsen" * Datenvalidierung * API-Annotationen und automatische Dokumentation diff --git a/docs/de/docs/tutorial/query-param-models.md b/docs/de/docs/tutorial/query-param-models.md new file mode 100644 index 000000000..7d3f2d32e --- /dev/null +++ b/docs/de/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# Query-Parameter-Modelle { #query-parameter-models } + +Wenn Sie eine Gruppe von **Query-Parametern** haben, die miteinander in Beziehung stehen, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren. + +Dadurch können Sie das **Modell an mehreren Stellen wiederverwenden** und gleichzeitig Validierungen und Metadaten für alle Parameter auf einmal deklarieren. 😎 + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓 + +/// + +## Query-Parameter mit einem Pydantic-Modell { #query-parameters-with-a-pydantic-model } + +Deklarieren Sie die benötigten **Query-Parameter** in einem **Pydantic-Modell** und dann den Parameter als `Query`: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den **Query-Parametern** des Request extrahieren und Ihnen das definierte Pydantic-Modell bereitstellen. + +## Die Dokumentation testen { #check-the-docs } + +Sie können die Query-Parameter in der Dokumentations-Oberfläche unter `/docs` einsehen: + +
+ +
+ +## Zusätzliche Query-Parameter verbieten { #forbid-extra-query-parameters } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Query-Parameter, die Sie empfangen möchten, **beschränken**. + +Sie können die Modellkonfiguration von Pydantic verwenden, um jegliche `extra` Felder zu `verbieten`: + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +Wenn ein Client versucht, einige **zusätzliche** Daten in den **Query-Parametern** zu senden, erhält er eine **Error-Response**. + +Wenn der Client beispielsweise versucht, einen `tool` Query-Parameter mit dem Wert `plumbus` zu senden, wie: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +erhält er eine **Error-Response**, die ihm mitteilt, dass der Query-Parameter `tool` nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## Zusammenfassung { #summary } + +Sie können **Pydantic-Modelle** verwenden, um **Query-Parameter** in **FastAPI** zu deklarieren. 😎 + +/// tip | Tipp + +Spoiler-Alarm: Sie können auch Pydantic-Modelle verwenden, um Cookies und Header zu deklarieren, aber darüber werden Sie später im Tutorial lesen. 🤫 + +/// diff --git a/docs/de/docs/tutorial/query-params-str-validations.md b/docs/de/docs/tutorial/query-params-str-validations.md index de8879ce8..744160baf 100644 --- a/docs/de/docs/tutorial/query-params-str-validations.md +++ b/docs/de/docs/tutorial/query-params-str-validations.md @@ -1,69 +1,49 @@ -# Query-Parameter und Stringvalidierung +# Query-Parameter und String-Validierungen { #query-parameters-and-string-validations } -**FastAPI** erlaubt es Ihnen, Ihre Parameter zusätzlich zu validieren, und zusätzliche Informationen hinzuzufügen. +**FastAPI** ermöglicht es Ihnen, zusätzliche Informationen und Validierungen für Ihre Parameter zu deklarieren. -Nehmen wir als Beispiel die folgende Anwendung: +Nehmen wir diese Anwendung als Beispiel: {* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} -Der Query-Parameter `q` hat den Typ `Union[str, None]` (oder `str | None` in Python 3.10), was bedeutet, er ist entweder ein `str` oder `None`. Der Defaultwert ist `None`, also weiß FastAPI, der Parameter ist nicht erforderlich. +Der Query-Parameter `q` hat den Typ `str | None`, das bedeutet, dass er vom Typ `str` sein kann, aber auch `None`, und tatsächlich ist der Defaultwert `None`, sodass FastAPI weiß, dass er nicht erforderlich ist. /// note | Hinweis -FastAPI weiß nur dank des definierten Defaultwertes `=None`, dass der Wert von `q` nicht erforderlich ist +FastAPI erkennt, dass der Wert von `q` nicht erforderlich ist, aufgrund des Defaultwertes `= None`. -`Union[str, None]` hingegen erlaubt ihren Editor, Sie besser zu unterstützen und Fehler zu erkennen. +Die Verwendung von `str | None` ermöglicht es Ihrem Editor, Ihnen bessere Unterstützung zu bieten und Fehler zu erkennen. /// -## Zusätzliche Validierung +## Zusätzliche Validierung { #additional-validation } -Wir werden bewirken, dass, obwohl `q` optional ist, wenn es gegeben ist, **seine Länge 50 Zeichen nicht überschreitet**. +Wir werden sicherstellen, dass, obwohl `q` optional ist, wann immer es bereitgestellt wird, **seine Länge 50 Zeichen nicht überschreitet**. -### `Query` und `Annotated` importieren +### `Query` und `Annotated` importieren { #import-query-and-annotated } -Importieren Sie zuerst: +Um dies zu erreichen, importieren Sie zuerst: * `Query` von `fastapi` -* `Annotated` von `typing` (oder von `typing_extensions` in Python unter 3.9) +* `Annotated` von `typing` -//// tab | Python 3.10+ +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -In Python 3.9 oder darüber, ist `Annotated` Teil der Standardbibliothek, also können Sie es von `typing` importieren. +/// info | Info -```Python hl_lines="1 3" -{!> ../../docs_src/query_params_str_validations/tutorial002_an_py310.py!} -``` +FastAPI hat Unterstützung für `Annotated` hinzugefügt (und begonnen, es zu empfehlen) in der Version 0.95.0. -//// +Wenn Sie eine ältere Version haben, würden Sie Fehler erhalten, beim Versuch, `Annotated` zu verwenden. -//// tab | Python 3.8+ - -In Versionen unter Python 3.9 importieren Sie `Annotated` von `typing_extensions`. - -Es wird bereits mit FastAPI installiert sein. - -```Python hl_lines="3-4" -{!> ../../docs_src/query_params_str_validations/tutorial002_an.py!} -``` - -//// - -/// info - -FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0. - -Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden. - -Bitte [aktualisieren Sie FastAPI](../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden. +Stellen Sie sicher, dass Sie [die FastAPI-Version aktualisieren](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}, auf mindestens Version 0.95.1, bevor Sie `Annotated` verwenden. /// -## `Annotated` im Typ des `q`-Parameters verwenden +## Verwenden von `Annotated` im Typ für den `q`-Parameter { #use-annotated-in-the-type-for-the-q-parameter } -Erinnern Sie sich, wie ich in [Einführung in Python-Typen](../python-types.md#typhinweise-mit-metadaten-annotationen){.internal-link target=_blank} sagte, dass Sie mittels `Annotated` Metadaten zu Ihren Parametern hinzufügen können? +Erinnern Sie sich, dass ich Ihnen zuvor in [Python-Typen-Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} gesagt habe, dass `Annotated` verwendet werden kann, um Metadaten zu Ihren Parametern hinzuzufügen? -Jetzt ist es an der Zeit, das mit FastAPI auszuprobieren. 🚀 +Jetzt ist es soweit, dies mit FastAPI zu verwenden. 🚀 Wir hatten diese Typannotation: @@ -83,7 +63,7 @@ q: Union[str, None] = None //// -Wir wrappen das nun in `Annotated`, sodass daraus wird: +Was wir tun werden, ist, dies mit `Annotated` zu wrappen, sodass es zu: //// tab | Python 3.10+ @@ -101,101 +81,75 @@ q: Annotated[Union[str, None]] = None //// -Beide Versionen bedeuten dasselbe: `q` ist ein Parameter, der `str` oder `None` sein kann. Standardmäßig ist er `None`. +Beide dieser Versionen bedeuten dasselbe: `q` ist ein Parameter, der ein `str` oder `None` sein kann, und standardmäßig ist er `None`. -Wenden wir uns jetzt den spannenden Dingen zu. 🎉 +Jetzt springen wir zu den spannenden Dingen. 🎉 -## `Query` zu `Annotated` im `q`-Parameter hinzufügen +## `Query` zu `Annotated` im `q`-Parameter hinzufügen { #add-query-to-annotated-in-the-q-parameter } -Jetzt, da wir `Annotated` für unsere Metadaten deklariert haben, fügen Sie `Query` hinzu, und setzen Sie den Parameter `max_length` auf `50`: +Da wir nun `Annotated` haben, in das wir mehr Informationen (in diesem Fall einige zusätzliche Validierungen) einfügen können, fügen Sie `Query` innerhalb von `Annotated` hinzu und setzen Sie den Parameter `max_length` auf `50`: {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} -Beachten Sie, dass der Defaultwert immer noch `None` ist, sodass der Parameter immer noch optional ist. +Beachten Sie, dass der Defaultwert weiterhin `None` ist, so dass der Parameter weiterhin optional ist. -Aber jetzt, mit `Query(max_length=50)` innerhalb von `Annotated`, sagen wir FastAPI, dass es diesen Wert aus den Query-Parametern extrahieren soll (das hätte es sowieso gemacht 🤷) und dass wir eine **zusätzliche Validierung** für diesen Wert haben wollen (darum machen wir das, um die zusätzliche Validierung zu bekommen). 😎 - -FastAPI wird nun: - -* Die Daten **validieren** und sicherstellen, dass sie nicht länger als 50 Zeichen sind -* Dem Client einen **verständlichen Fehler** anzeigen, wenn die Daten ungültig sind -* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentation** angezeigt wird) - -## Alternativ (alt): `Query` als Defaultwert - -Frühere Versionen von FastAPI (vor 0.95.0) benötigten `Query` als Defaultwert des Parameters, statt es innerhalb von `Annotated` unterzubringen. Die Chance ist groß, dass Sie Quellcode sehen, der das immer noch so macht, darum erkläre ich es Ihnen. +Aber jetzt, mit `Query(max_length=50)` innerhalb von `Annotated`, sagen wir FastAPI, dass wir eine **zusätzliche Validierung** für diesen Wert wünschen, wir wollen, dass er maximal 50 Zeichen hat. 😎 /// tip | Tipp -Verwenden Sie für neuen Code, und wann immer möglich, `Annotated`, wie oben erklärt. Es gibt mehrere Vorteile (unten erläutert) und keine Nachteile. 🍰 +Hier verwenden wir `Query()`, weil dies ein **Query-Parameter** ist. Später werden wir andere wie `Path()`, `Body()`, `Header()`, und `Cookie()` sehen, die auch dieselben Argumente wie `Query()` akzeptieren. /// -So würden Sie `Query()` als Defaultwert Ihres Funktionsparameters verwenden, den Parameter `max_length` auf 50 gesetzt: +FastAPI wird nun: + +* Die Daten **validieren**, um sicherzustellen, dass die Länge maximal 50 Zeichen beträgt +* Einen **klaren Fehler** für den Client anzeigen, wenn die Daten ungültig sind +* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentation** angezeigt wird) + +## Alternative (alt): `Query` als Defaultwert { #alternative-old-query-as-the-default-value } + +Frühere Versionen von FastAPI (vor 0.95.0) erforderten, dass Sie `Query` als den Defaultwert Ihres Parameters verwendeten, anstatt es innerhalb von `Annotated` zu platzieren. Es besteht eine hohe Wahrscheinlichkeit, dass Sie Code sehen, der es so verwendet, also werde ich es Ihnen erklären. + +/// tip | Tipp + +Für neuen Code und wann immer es möglich ist, verwenden Sie `Annotated` wie oben erklärt. Es gibt mehrere Vorteile (unten erläutert) und keine Nachteile. 🍰 + +/// + +So würden Sie `Query()` als den Defaultwert Ihres Funktionsparameters verwenden und den Parameter `max_length` auf 50 setzen: {* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} -Da wir in diesem Fall (ohne die Verwendung von `Annotated`) den Parameter-Defaultwert `None` mit `Query()` ersetzen, müssen wir nun dessen Defaultwert mit dem Parameter `Query(default=None)` deklarieren. Das dient demselben Zweck, `None` als Defaultwert für den Funktionsparameter zu setzen (zumindest für FastAPI). +Da wir in diesem Fall (ohne die Verwendung von `Annotated`) den Defaultwert `None` in der Funktion durch `Query()` ersetzen müssen, müssen wir nun den Defaultwert mit dem Parameter `Query(default=None)` setzen, er erfüllt den gleichen Zweck, diesen Defaultwert zu definieren (zumindest für FastAPI). -Sprich: - -```Python -q: Union[str, None] = Query(default=None) -``` - -... macht den Parameter optional, mit dem Defaultwert `None`, genauso wie: - -```Python -q: Union[str, None] = None -``` - -Und in Python 3.10 und darüber macht: +Also: ```Python q: str | None = Query(default=None) ``` -... den Parameter optional, mit dem Defaultwert `None`, genauso wie: +... macht den Parameter optional mit einem Defaultwert von `None`, genauso wie: ```Python q: str | None = None ``` -Nur, dass die `Query`-Versionen den Parameter explizit als Query-Parameter deklarieren. +Aber die `Query`-Version deklariert ihn explizit als Query-Parameter. -/// info - -Bedenken Sie, dass: +Dann können wir mehr Parameter an `Query` übergeben. In diesem Fall den `max_length`-Parameter, der auf Strings angewendet wird: ```Python -= None +q: str | None = Query(default=None, max_length=50) ``` -oder: +Dies wird die Daten validieren, einen klaren Fehler anzeigen, wenn die Daten nicht gültig sind, und den Parameter in der OpenAPI-Schema-*Pfadoperation* dokumentieren. -```Python -= Query(default=None) -``` +### `Query` als Defaultwert oder in `Annotated` { #query-as-the-default-value-or-in-annotated } -der wichtigste Teil ist, um einen Parameter optional zu machen, da dieses `None` der Defaultwert ist, und das ist es, was diesen Parameter **nicht erforderlich** macht. +Beachten Sie, dass wenn Sie `Query` innerhalb von `Annotated` verwenden, Sie den `default`-Parameter für `Query` nicht verwenden dürfen. -Der Teil mit `Union[str, None]` erlaubt es Ihrem Editor, Sie besser zu unterstützen, aber er sagt FastAPI nicht, dass dieser Parameter optional ist. - -/// - -Jetzt können wir `Query` weitere Parameter übergeben. Fangen wir mit dem `max_length` Parameter an, der auf Strings angewendet wird: - -```Python -q: Union[str, None] = Query(default=None, max_length=50) -``` - -Das wird die Daten validieren, einen verständlichen Fehler ausgeben, wenn die Daten nicht gültig sind, und den Parameter in der OpenAPI-Schema-*Pfadoperation* dokumentieren. - -### `Query` als Defaultwert oder in `Annotated` - -Bedenken Sie, dass wenn Sie `Query` innerhalb von `Annotated` benutzen, Sie den `default`-Parameter für `Query` nicht verwenden dürfen. - -Setzen Sie stattdessen den Defaultwert des Funktionsparameters, sonst wäre es inkonsistent. +Setzen Sie stattdessen den tatsächlichen Defaultwert des Funktionsparameters. Andernfalls wäre es inkonsistent. Zum Beispiel ist das nicht erlaubt: @@ -203,7 +157,7 @@ Zum Beispiel ist das nicht erlaubt: q: Annotated[str, Query(default="rick")] = "morty" ``` -... denn es wird nicht klar, ob der Defaultwert `"rick"` oder `"morty"` sein soll. +... denn es ist nicht klar, ob der Defaultwert `"rick"` oder `"morty"` sein soll. Sie würden also (bevorzugt) schreiben: @@ -211,49 +165,49 @@ Sie würden also (bevorzugt) schreiben: q: Annotated[str, Query()] = "rick" ``` -In älterem Code werden Sie auch finden: +... oder in älteren Codebasen finden Sie: ```Python q: str = Query(default="rick") ``` -### Vorzüge von `Annotated` +### Vorzüge von `Annotated` { #advantages-of-annotated } -**Es wird empfohlen, `Annotated` zu verwenden**, statt des Defaultwertes im Funktionsparameter, das ist aus mehreren Gründen **besser**: 🤓 +**Es wird empfohlen, `Annotated` zu verwenden**, anstelle des Defaultwertes in Funktionsparametern, es ist aus mehreren Gründen **besser**. 🤓 -Der **Default**wert des **Funktionsparameters** ist der **tatsächliche Default**wert, das spielt generell intuitiver mit Python zusammen. 😌 +Der **Default**wert des **Funktionsparameters** ist der **tatsächliche Default**wert, das ist in der Regel intuitiver mit Python. 😌 -Sie können die Funktion ohne FastAPI an **anderen Stellen aufrufen**, und es wird **wie erwartet funktionieren**. Wenn es einen **erforderlichen** Parameter gibt (ohne Defaultwert), und Sie führen die Funktion ohne den benötigten Parameter aus, dann wird Ihr **Editor** Sie das mit einem Fehler wissen lassen, und **Python** wird sich auch beschweren. +Sie könnten **diese gleiche Funktion** in **anderen Stellen** ohne FastAPI **aufrufen**, und es würde **wie erwartet funktionieren**. Wenn es einen **erforderlichen** Parameter gibt (ohne Defaultwert), wird Ihr **Editor** Ihnen dies mit einem Fehler mitteilen, außerdem wird **Python** sich beschweren, wenn Sie es ausführen, ohne den erforderlichen Parameter zu übergeben. -Wenn Sie aber nicht `Annotated` benutzen und stattdessen die **(alte) Variante mit einem Defaultwert**, dann müssen Sie, wenn Sie die Funktion ohne FastAPI an **anderen Stellen** aufrufen, sich daran **erinnern**, die Argumente der Funktion zu übergeben, damit es richtig funktioniert. Ansonsten erhalten Sie unerwartete Werte (z. B. `QueryInfo` oder etwas Ähnliches, statt `str`). Ihr Editor kann ihnen nicht helfen, und Python wird die Funktion ohne Beschwerden ausführen, es sei denn, die Operationen innerhalb lösen einen Fehler aus. +Wenn Sie `Annotated` nicht verwenden und stattdessen die **(alte) Defaultwert-Stilform** verwenden, müssen Sie sich daran **erinnern**, die Argumente der Funktion zu übergeben, wenn Sie diese Funktion ohne FastAPI in **anderen Stellen** aufrufen. Ansonsten sind die Werte anders als erwartet (z. B. `QueryInfo` oder etwas Ähnliches statt `str`). Ihr Editor kann Ihnen nicht helfen, und Python wird die Funktion ohne Klagen ausführen und sich nur beschweren wenn die Operationen innerhalb auf einen Fehler stoßen. -Da `Annotated` mehrere Metadaten haben kann, können Sie dieselbe Funktion auch mit anderen Tools verwenden, wie etwa Typer. 🚀 +Da `Annotated` mehr als eine Metadaten-Annotation haben kann, könnten Sie dieselbe Funktion sogar mit anderen Tools verwenden, wie z. B. Typer. 🚀 -## Mehr Validierungen hinzufügen +## Mehr Validierungen hinzufügen { #add-more-validations } -Sie können auch einen Parameter `min_length` hinzufügen: +Sie können auch einen `min_length`-Parameter hinzufügen: {* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} -## Reguläre Ausdrücke hinzufügen +## Reguläre Ausdrücke hinzufügen { #add-regular-expressions } -Sie können einen Regulären Ausdruck `pattern` definieren, mit dem der Parameter übereinstimmen muss: +Sie können einen regulären Ausdruck `pattern` definieren, mit dem der Parameter übereinstimmen muss: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} -Dieses bestimmte reguläre Suchmuster prüft, ob der erhaltene Parameter-Wert: +Dieses spezielle Suchmuster im regulären Ausdruck überprüft, dass der erhaltene Parameterwert: -* `^`: mit den nachfolgenden Zeichen startet, keine Zeichen davor hat. +* `^`: mit den nachfolgenden Zeichen beginnt, keine Zeichen davor hat. * `fixedquery`: den exakten Text `fixedquery` hat. -* `$`: danach endet, keine weiteren Zeichen hat als `fixedquery`. +* `$`: dort endet, keine weiteren Zeichen nach `fixedquery` hat. -Wenn Sie sich verloren fühlen bei all diesen **„Regulärer Ausdruck“**-Konzepten, keine Sorge. Reguläre Ausdrücke sind für viele Menschen ein schwieriges Thema. Sie können auch ohne reguläre Ausdrücke eine ganze Menge machen. +Wenn Sie sich mit all diesen **„regulärer Ausdruck“**-Ideen verloren fühlen, keine Sorge. Sie sind ein schwieriges Thema für viele Menschen. Sie können noch viele Dinge tun, ohne reguläre Ausdrücke direkt zu benötigen. -Aber wenn Sie sie brauchen und sie lernen, wissen Sie, dass Sie sie bereits direkt in **FastAPI** verwenden können. +Aber nun wissen Sie, dass Sie sie in **FastAPI** immer dann verwenden können, wenn Sie sie brauchen. -### Pydantic v1 `regex` statt `pattern` +### Pydantic v1 `regex` statt `pattern` { #pydantic-v1-regex-instead-of-pattern } -Vor Pydantic Version 2 und vor FastAPI Version 0.100.0, war der Name des Parameters `regex` statt `pattern`, aber das ist jetzt deprecated. +Vor Pydantic Version 2 und FastAPI 0.100.0, hieß der Parameter `regex` statt `pattern`, aber das ist jetzt obsolet. Sie könnten immer noch Code sehen, der den alten Namen verwendet: @@ -263,25 +217,25 @@ Sie könnten immer noch Code sehen, der den alten Namen verwendet: //// -Beachten Sie aber, dass das deprecated ist, und zum neuen Namen `pattern` geändert werden sollte. 🤓 +Beachten Sie aber, dass das obsolet ist und auf den neuen Parameter `pattern` aktualisiert werden sollte. 🤓 -## Defaultwerte +## Defaultwerte { #default-values } -Sie können natürlich andere Defaultwerte als `None` verwenden. +Natürlich können Sie Defaultwerte verwenden, die nicht `None` sind. -Beispielsweise könnten Sie den `q` Query-Parameter so deklarieren, dass er eine `min_length` von `3` hat, und den Defaultwert `"fixedquery"`: +Nehmen wir an, Sie möchten, dass der `q` Query-Parameter eine `min_length` von `3` hat und einen Defaultwert von `"fixedquery"`: {* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} /// note | Hinweis -Ein Parameter ist optional (nicht erforderlich), wenn er irgendeinen Defaultwert, auch `None`, hat. +Ein Defaultwert irgendeines Typs, einschließlich `None`, macht den Parameter optional (nicht erforderlich). /// -## Erforderliche Parameter +## Erforderliche Parameter { #required-parameters } -Wenn wir keine Validierungen oder Metadaten haben, können wir den `q` Query-Parameter erforderlich machen, indem wir einfach keinen Defaultwert deklarieren, wie in: +Wenn wir keine weiteren Validierungen oder Metadaten deklarieren müssen, können wir den `q` Query-Parameter erforderlich machen, indem wir einfach keinen Defaultwert deklarieren, wie: ```Python q: str @@ -290,56 +244,32 @@ q: str statt: ```Python -q: Union[str, None] = None +q: str | None = None ``` -Aber jetzt deklarieren wir den Parameter mit `Query`, wie in: - -//// tab | Annotiert +Aber jetzt deklarieren wir es mit `Query`, zum Beispiel so: ```Python -q: Annotated[Union[str, None], Query(min_length=3)] = None +q: Annotated[str | None, Query(min_length=3)] = None ``` -//// - -//// tab | Nicht annotiert - -```Python -q: Union[str, None] = Query(default=None, min_length=3) -``` - -//// - -Wenn Sie einen Parameter erforderlich machen wollen, während Sie `Query` verwenden, deklarieren Sie ebenfalls einfach keinen Defaultwert: +Wenn Sie einen Wert als erforderlich deklarieren müssen, während Sie `Query` verwenden, deklarieren Sie einfach keinen Defaultwert: {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} -### Erforderlich, kann `None` sein +### Erforderlich, kann `None` sein { #required-can-be-none } -Sie können deklarieren, dass ein Parameter `None` akzeptiert, aber dennoch erforderlich ist. Das zwingt Clients, den Wert zu senden, selbst wenn er `None` ist. +Sie können deklarieren, dass ein Parameter `None` akzeptieren kann, aber trotzdem erforderlich ist. Dadurch müssten Clients den Wert senden, selbst wenn der Wert `None` ist. -Um das zu machen, deklarieren Sie, dass `None` ein gültiger Typ ist, aber verwenden Sie dennoch `...` als Default: +Um das zu tun, können Sie deklarieren, dass `None` ein gültiger Typ ist, einfach indem Sie keinen Defaultwert deklarieren: {* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} -/// tip | Tipp +## Query-Parameter-Liste / Mehrere Werte { #query-parameter-list-multiple-values } -Pydantic, welches die gesamte Datenvalidierung und Serialisierung in FastAPI antreibt, hat ein spezielles Verhalten, wenn Sie `Optional` oder `Union[Something, None]` ohne Defaultwert verwenden, Sie können mehr darüber in der Pydantic-Dokumentation unter Required fields erfahren. +Wenn Sie einen Query-Parameter explizit mit `Query` definieren, können Sie ihn auch so deklarieren, dass er eine Liste von Werten empfängt, oder anders gesagt, dass er mehrere Werte empfangen kann. -/// - -/// tip | Tipp - -Denken Sie daran, dass Sie in den meisten Fällen, wenn etwas erforderlich ist, einfach den Defaultwert weglassen können. Sie müssen also normalerweise `...` nicht verwenden. - -/// - -## Query-Parameter-Liste / Mehrere Werte - -Wenn Sie einen Query-Parameter explizit mit `Query` auszeichnen, können Sie ihn auch eine Liste von Werten empfangen lassen, oder anders gesagt, mehrere Werte. - -Um zum Beispiel einen Query-Parameter `q` zu deklarieren, der mehrere Male in der URL vorkommen kann, schreiben Sie: +Um zum Beispiel einen Query-Parameter `q` zu deklarieren, der mehrmals in der URL vorkommen kann, schreiben Sie: {* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} @@ -349,9 +279,9 @@ Dann, mit einer URL wie: http://localhost:8000/items/?q=foo&q=bar ``` -bekommen Sie alle `q`-*Query-Parameter*-Werte (`foo` und `bar`) in einer Python-Liste – `list` – in ihrer *Pfadoperation-Funktion*, im Funktionsparameter `q`, überreicht. +würden Sie die mehreren `q`-*Query-Parameter*-Werte (`foo` und `bar`) in einer Python-`list` in Ihrer *Pfadoperation-Funktion* im *Funktionsparameter* `q` erhalten. -Die Response für diese URL wäre also: +So wäre die Response zu dieser URL: ```JSON { @@ -364,27 +294,27 @@ Die Response für diese URL wäre also: /// tip | Tipp -Um einen Query-Parameter vom Typ `list` zu deklarieren, wie im Beispiel oben, müssen Sie explizit `Query` verwenden, sonst würde der Parameter als Requestbody interpretiert werden. +Um einen Query-Parameter mit einem Typ `list` zu deklarieren, wie im obigen Beispiel, müssen Sie explizit `Query` verwenden, da er andernfalls als Requestbody interpretiert würde. /// -Die interaktive API-Dokumentation wird entsprechend aktualisiert und erlaubt jetzt mehrere Werte. +Die interaktive API-Dokumentation wird entsprechend aktualisiert, um mehrere Werte zu erlauben: -### Query-Parameter-Liste / Mehrere Werte mit Defaults +### Query-Parameter-Liste / Mehrere Werte mit Defaults { #query-parameter-list-multiple-values-with-defaults } -Und Sie können auch eine Default-`list`e von Werten definieren, wenn keine übergeben werden: +Sie können auch eine Default-`list` von Werten definieren, wenn keine bereitgestellt werden: {* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} -Wenn Sie auf: +Wenn Sie zu: ``` http://localhost:8000/items/ ``` -gehen, wird der Default für `q` verwendet: `["foo", "bar"]`, und als Response erhalten Sie: +gehen, wird der Default für `q` sein: `["foo", "bar"]`, und Ihre Response wird sein: ```JSON { @@ -395,9 +325,9 @@ gehen, wird der Default für `q` verwendet: `["foo", "bar"]`, und als Response e } ``` -#### `list` alleine verwenden +#### Nur `list` verwenden { #using-just-list } -Sie können auch `list` direkt verwenden, anstelle von `List[str]` (oder `list[str]` in Python 3.9+): +Sie können auch `list` direkt verwenden, anstelle von `list[str]`: {* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} @@ -405,35 +335,35 @@ Sie können auch `list` direkt verwenden, anstelle von `List[str]` (oder `list[s Beachten Sie, dass FastAPI in diesem Fall den Inhalt der Liste nicht überprüft. -Zum Beispiel würde `List[int]` überprüfen (und dokumentieren) dass die Liste Ganzzahlen enthält. `list` alleine macht das nicht. +Zum Beispiel würde `list[int]` überprüfen (und dokumentieren), dass der Inhalt der Liste Ganzzahlen sind. Aber `list` alleine würde das nicht. /// -## Deklarieren von mehr Metadaten +## Mehr Metadaten deklarieren { #declare-more-metadata } -Sie können mehr Informationen zum Parameter hinzufügen. +Sie können mehr Informationen über den Parameter hinzufügen. -Diese Informationen werden zur generierten OpenAPI hinzugefügt, und von den Dokumentations-Oberflächen und von externen Tools verwendet. +Diese Informationen werden in das generierte OpenAPI aufgenommen und von den Dokumentationsoberflächen und externen Tools verwendet. /// note | Hinweis -Beachten Sie, dass verschiedene Tools OpenAPI möglicherweise unterschiedlich gut unterstützen. +Beachten Sie, dass verschiedene Tools möglicherweise unterschiedliche Unterstützungslevels für OpenAPI haben. -Einige könnten noch nicht alle zusätzlichen Informationen anzeigen, die Sie deklariert haben, obwohl in den meisten Fällen geplant ist, das fehlende Feature zu implementieren. +Einige davon könnten noch nicht alle zusätzlichen Informationen anzuzeigen, die Sie erklärten, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist. /// -Sie können einen Titel hinzufügen – `title`: +Sie können einen `title` hinzufügen: {* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} -Und eine Beschreibung – `description`: +Und eine `description`: {* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} -## Alias-Parameter +## Alias-Parameter { #alias-parameters } -Stellen Sie sich vor, der Parameter soll `item-query` sein. +Stellen Sie sich vor, Sie möchten, dass der Parameter `item-query` ist. Wie in: @@ -443,37 +373,99 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Aber `item-query` ist kein gültiger Name für eine Variable in Python. -Am ähnlichsten wäre `item_query`. +Der am ähnlichsten wäre `item_query`. -Aber Sie möchten dennoch exakt `item-query` verwenden. +Aber Sie benötigen dennoch, dass er genau `item-query` ist ... -Dann können Sie einen `alias` deklarieren, und dieser Alias wird verwendet, um den Parameter-Wert zu finden: +Dann können Sie ein `alias` deklarieren, und dieser Alias wird verwendet, um den Parameterwert zu finden: {* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} -## Parameter als deprecated ausweisen +## Parameter als deprecatet ausweisen { #deprecating-parameters } -Nehmen wir an, Sie mögen diesen Parameter nicht mehr. +Nehmen wir an, Ihnen gefällt dieser Parameter nicht mehr. -Sie müssen ihn eine Weile dort belassen, weil Clients ihn benutzen, aber Sie möchten, dass die Dokumentation klar anzeigt, dass er deprecated ist. +Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als deprecatet anzeigt. -In diesem Fall fügen Sie den Parameter `deprecated=True` zu `Query` hinzu. +Dann übergeben Sie den Parameter `deprecated=True` an `Query`: {* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} -Die Dokumentation wird das so anzeigen: +Die Dokumentation wird es so anzeigen: -## Parameter von OpenAPI ausschließen +## Parameter von OpenAPI ausschließen { #exclude-parameters-from-openapi } -Um einen Query-Parameter vom generierten OpenAPI-Schema auszuschließen (und daher von automatischen Dokumentations-Systemen), setzen Sie den Parameter `include_in_schema` in `Query` auf `False`. +Um einen Query-Parameter aus dem generierten OpenAPI-Schema auszuschließen (und somit aus den automatischen Dokumentationssystemen), setzen Sie den Parameter `include_in_schema` von `Query` auf `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} -## Zusammenfassung +## Benutzerdefinierte Validierung { #custom-validation } -Sie können zusätzliche Validierungen und Metadaten zu ihren Parametern hinzufügen. +Es kann Fälle geben, in denen Sie eine **benutzerdefinierte Validierung** durchführen müssen, die nicht mit den oben gezeigten Parametern durchgeführt werden kann. + +In diesen Fällen können Sie eine **benutzerdefinierte Validierungsfunktion** verwenden, die nach der normalen Validierung angewendet wird (z. B. nach der Validierung, dass der Wert ein `str` ist). + +Sie können dies mit Pydantic's `AfterValidator` innerhalb von `Annotated` erreichen. + +/// tip | Tipp + +Pydantic unterstützt auch `BeforeValidator` und andere. 🤓 + +/// + +Zum Beispiel überprüft dieser benutzerdefinierte Validator, ob die Artikel-ID mit `isbn-` für eine ISBN-Buchnummer oder mit `imdb-` für eine IMDB-Film-URL-ID beginnt: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | Info + +Dies ist verfügbar seit Pydantic Version 2 oder höher. 😎 + +/// + +/// tip | Tipp + +Wenn Sie irgendeine Art von Validierung durchführen müssen, die eine Kommunikation mit einer **externen Komponente** erfordert, wie z. B. einer Datenbank oder einer anderen API, sollten Sie stattdessen **FastAPI-Abhängigkeiten** verwenden. Sie werden diese später kennenlernen. + +Diese benutzerdefinierten Validatoren sind für Dinge gedacht, die einfach mit denselben **Daten** überprüft werden können, die im Request bereitgestellt werden. + +/// + +### Dieses Codebeispiel verstehen { #understand-that-code } + +Der wichtige Punkt ist einfach die Verwendung von **`AfterValidator` mit einer Funktion innerhalb von `Annotated`**. Fühlen Sie sich frei, diesen Teil zu überspringen. 🤸 + +--- + +Aber wenn Sie neugierig auf dieses spezielle Codebeispiel sind und immer noch Spaß haben, hier sind einige zusätzliche Details. + +#### Zeichenkette mit `value.startswith()` { #string-with-value-startswith } + +Haben Sie bemerkt? Eine Zeichenkette mit `value.startswith()` kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### Ein zufälliges Item { #a-random-item } + +Mit `data.items()` erhalten wir ein iterierbares Objekt mit Tupeln, die Schlüssel und Wert für jedes Dictionary-Element enthalten. + +Wir konvertieren dieses iterierbare Objekt mit `list(data.items())` in eine richtige `list`. + +Dann können wir mit `random.choice()` einen **zufälligen Wert** aus der Liste erhalten, also bekommen wir ein Tuple mit `(id, name)`. Es wird etwas wie `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` sein. + +Dann **weisen wir diese beiden Werte** des Tupels den Variablen `id` und `name` zu. + +Wenn der Benutzer also keine Artikel-ID bereitgestellt hat, erhält er trotzdem einen zufälligen Vorschlag. + +... wir tun all dies in einer **einzelnen einfachen Zeile**. 🤯 Lieben Sie nicht auch Python? 🐍 + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## Zusammenfassung { #recap } + +Sie können zusätzliche Validierungen und Metadaten für Ihre Parameter deklarieren. Allgemeine Validierungen und Metadaten: @@ -482,12 +474,14 @@ Allgemeine Validierungen und Metadaten: * `description` * `deprecated` -Validierungen spezifisch für Strings: +Validierungen, die spezifisch für Strings sind: * `min_length` * `max_length` * `pattern` -In diesen Beispielen haben Sie gesehen, wie Sie Validierungen für Strings hinzufügen. +Benutzerdefinierte Validierungen mit `AfterValidator`. -In den nächsten Kapiteln sehen wir, wie man Validierungen für andere Typen hinzufügt, etwa für Zahlen. +In diesen Beispielen haben Sie gesehen, wie Sie Validierungen für `str`-Werte deklarieren. + +Sehen Sie sich die nächsten Kapitel an, um zu erfahren, wie Sie Validierungen für andere Typen, wie z. B. Zahlen, deklarieren. diff --git a/docs/de/docs/tutorial/query-params.md b/docs/de/docs/tutorial/query-params.md index 56f58dda9..e46f31ad0 100644 --- a/docs/de/docs/tutorial/query-params.md +++ b/docs/de/docs/tutorial/query-params.md @@ -1,10 +1,10 @@ -# Query-Parameter +# Query-Parameter { #query-parameters } -Wenn Sie in ihrer Funktion Parameter deklarieren, die nicht Teil der Pfad-Parameter sind, dann werden diese automatisch als „Query“-Parameter interpretiert. +Wenn Sie in Ihrer Funktion andere Parameter deklarieren, die nicht Teil der Pfad-Parameter sind, dann werden diese automatisch als „Query“-Parameter interpretiert. {* ../../docs_src/query_params/tutorial001.py hl[9] *} -Query-Parameter (Deutsch: Abfrage-Parameter) sind die Schlüssel-Wert-Paare, die nach dem `?` in einer URL aufgelistet sind, getrennt durch `&`-Zeichen. +Die Query ist die Menge von Schlüssel-Wert-Paaren, die nach dem `?` in einer URL folgen und durch `&`-Zeichen getrennt sind. Zum Beispiel sind in der URL: @@ -19,18 +19,18 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 Da sie Teil der URL sind, sind sie „naturgemäß“ Strings. -Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), werden sie zu diesem Typ konvertiert, und gegen diesen validiert. +Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), werden sie zu diesem Typ konvertiert und gegen diesen validiert. -Die gleichen Prozesse, die für Pfad-Parameter stattfinden, werden auch auf Query-Parameter angewendet: +Die gleichen Prozesse, die für Pfad-Parameter gelten, werden auch auf Query-Parameter angewendet: * Editor Unterstützung (natürlich) -* „Parsen“ der Daten +* Daten-„Parsen“ * Datenvalidierung * Automatische Dokumentation -## Defaultwerte +## Defaultwerte { #defaults } -Da Query-Parameter nicht ein festgelegter Teil des Pfades sind, können sie optional sein und Defaultwerte haben. +Da Query-Parameter kein fester Teil eines Pfades sind, können sie optional sein und Defaultwerte haben. Im obigen Beispiel haben sie die Defaultwerte `skip=0` und `limit=10`. @@ -52,28 +52,28 @@ Aber wenn Sie zum Beispiel zu: http://127.0.0.1:8000/items/?skip=20 ``` -gehen, werden die Parameter-Werte Ihrer Funktion sein: +gehen, werden die Parameterwerte Ihrer Funktion sein: * `skip=20`: da Sie das in der URL gesetzt haben * `limit=10`: weil das der Defaultwert ist -## Optionale Parameter +## Optionale Parameter { #optional-parameters } Auf die gleiche Weise können Sie optionale Query-Parameter deklarieren, indem Sie deren Defaultwert auf `None` setzen: {* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} -In diesem Fall wird der Funktionsparameter `q` optional, und standardmäßig `None` sein. +In diesem Fall wird der Funktionsparameter `q` optional und standardmäßig `None` sein. -/// check +/// check | Testen Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein. /// -## Query-Parameter Typkonvertierung +## Query-Parameter Typkonvertierung { #query-parameter-type-conversion } -Sie können auch `bool`-Typen deklarieren und sie werden konvertiert: +Sie können auch `bool`-Typen deklarieren, und sie werden konvertiert: {* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} @@ -109,9 +109,9 @@ http://127.0.0.1:8000/items/foo?short=yes gehen, oder zu irgendeiner anderen Variante der Groß-/Kleinschreibung (Alles groß, Anfangsbuchstabe groß, usw.), dann wird Ihre Funktion den Parameter `short` mit dem `bool`-Wert `True` sehen, ansonsten mit dem Wert `False`. -## Mehrere Pfad- und Query-Parameter +## Mehrere Pfad- und Query-Parameter { #multiple-path-and-query-parameters } -Sie können mehrere Pfad-Parameter und Query-Parameter gleichzeitig deklarieren, **FastAPI** weiß, was welches ist. +Sie können mehrere Pfad-Parameter und Query-Parameter gleichzeitig deklarieren, **FastAPI** weiß, welches welcher ist. Und Sie müssen sie auch nicht in einer spezifischen Reihenfolge deklarieren. @@ -119,7 +119,7 @@ Parameter werden anhand ihres Namens erkannt: {* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} -## Erforderliche Query-Parameter +## Erforderliche Query-Parameter { #required-query-parameters } Wenn Sie einen Defaultwert für Nicht-Pfad-Parameter deklarieren (Bis jetzt haben wir nur Query-Parameter gesehen), dann ist der Parameter nicht erforderlich. @@ -182,6 +182,6 @@ In diesem Fall gibt es drei Query-Parameter: /// tip | Tipp -Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#vordefinierte-parameterwerte){.internal-link target=_blank}. +Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#predefined-values){.internal-link target=_blank}. /// diff --git a/docs/de/docs/tutorial/request-files.md b/docs/de/docs/tutorial/request-files.md index 1f01b0d1e..0aee898b9 100644 --- a/docs/de/docs/tutorial/request-files.md +++ b/docs/de/docs/tutorial/request-files.md @@ -1,40 +1,44 @@ -# Dateien im Request +# Dateien im Request { #request-files } -Mit `File` können sie vom Client hochzuladende Dateien definieren. +Sie können Dateien, die vom Client hochgeladen werden, mithilfe von `File` definieren. -/// info +/// info | Info -Um hochgeladene Dateien zu empfangen, installieren Sie zuerst `python-multipart`. +Um hochgeladene Dateien zu empfangen, installieren Sie zuerst `python-multipart`. -Z. B. `pip install python-multipart`. +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann das Paket installieren, zum Beispiel: -Das, weil hochgeladene Dateien als „Formulardaten“ gesendet werden. +```console +$ pip install python-multipart +``` + +Das liegt daran, dass hochgeladene Dateien als „Formulardaten“ gesendet werden. /// -## `File` importieren +## `File` importieren { #import-file } Importieren Sie `File` und `UploadFile` von `fastapi`: {* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} -## `File`-Parameter definieren +## `File`-Parameter definieren { #define-file-parameters } Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` und `Form` machen würden: {* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} -/// info +/// info | Info `File` ist eine Klasse, die direkt von `Form` erbt. -Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `File` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben +Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `File` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben. /// /// tip | Tipp -Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden. +Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body (JSON)-Parameter interpretiert werden würden. /// @@ -46,7 +50,7 @@ Bedenken Sie, dass das bedeutet, dass sich der gesamte Inhalt der Datei im Arbei Aber es gibt viele Fälle, in denen Sie davon profitieren, `UploadFile` zu verwenden. -## Datei-Parameter mit `UploadFile` +## Datei-Parameter mit `UploadFile` { #file-parameters-with-uploadfile } Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`: @@ -55,20 +59,20 @@ Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`: `UploadFile` zu verwenden, hat mehrere Vorzüge gegenüber `bytes`: * Sie müssen `File()` nicht als Parameter-Defaultwert verwenden. -* Es wird eine „Spool“-Datei verwendet: +* Es wird eine „gespoolte“ Datei verwendet: * Eine Datei, die bis zu einem bestimmten Größen-Limit im Arbeitsspeicher behalten wird, und wenn das Limit überschritten wird, auf der Festplatte gespeichert wird. * Das bedeutet, es wird für große Dateien wie Bilder, Videos, große Binärdateien, usw. gut funktionieren, ohne den ganzen Arbeitsspeicher aufzubrauchen. * Sie können Metadaten aus der hochgeladenen Datei auslesen. -* Es hat eine file-like `async`hrone Schnittstelle. -* Es stellt ein tatsächliches Python-`SpooledTemporaryFile`-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten. +* Es hat eine dateiartige `async`hrone Schnittstelle. +* Es stellt ein tatsächliches Python-`SpooledTemporaryFile`-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten. -### `UploadFile` +### `UploadFile` { #uploadfile } `UploadFile` hat die folgenden Attribute: * `filename`: Ein `str` mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. `meinbild.jpg`). * `content_type`: Ein `str` mit dem Inhaltstyp (MIME-Typ / Medientyp) (z. B. `image/jpeg`). -* `file`: Ein `SpooledTemporaryFile` (ein file-like Objekt). Das ist das tatsächliche Python-Objekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten. +* `file`: Ein `SpooledTemporaryFile` (ein dateiartiges Objekt). Das ist das tatsächliche Python-Objekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten. `UploadFile` hat die folgenden `async`hronen Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern `SpooledTemporaryFile` verwendet wird). @@ -79,7 +83,7 @@ Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`: * Das ist besonders dann nützlich, wenn Sie `await myfile.read()` einmal ausführen und dann diese Inhalte erneut auslesen müssen. * `close()`: Schließt die Datei. -Da alle diese Methoden `async`hron sind, müssen Sie sie `await`en („erwarten“). +Da alle diese Methoden `async`hron sind, müssen Sie sie „await“en („erwarten“). Zum Beispiel können Sie innerhalb einer `async` *Pfadoperation-Funktion* den Inhalt wie folgt auslesen: @@ -105,9 +109,9 @@ Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden i /// -## Was sind „Formulardaten“ +## Was sind „Formulardaten“ { #what-is-form-data } -HTML-Formulare (`
`) senden die Daten in einer „speziellen“ Kodierung zum Server, welche sich von JSON unterscheidet. +Der Weg, wie HTML-Formulare (`
`) die Daten zum Server senden, verwendet normalerweise eine „spezielle“ Kodierung für diese Daten. Diese unterscheidet sich von JSON. **FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten. @@ -117,31 +121,31 @@ Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem < Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss. -Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die MDN-Webdokumentation für POST. +Wenn Sie mehr über diese Kodierungen und Formularfelder lesen möchten, besuchen Sie die MDN-Webdokumentation für POST. /// /// warning | Achtung -Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert. +Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert. Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls. /// -## Optionaler Datei-Upload +## Optionaler Datei-Upload { #optional-file-upload } Sie können eine Datei optional machen, indem Sie Standard-Typannotationen verwenden und den Defaultwert auf `None` setzen: {* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} -## `UploadFile` mit zusätzlichen Metadaten +## `UploadFile` mit zusätzlichen Metadaten { #uploadfile-with-additional-metadata } -Sie können auch `File()` zusammen mit `UploadFile` verwenden, um zum Beispiel zusätzliche Metadaten zu setzen: +Sie können auch `File()` mit `UploadFile` verwenden, um zum Beispiel zusätzliche Metadaten zu setzen: {* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} -## Mehrere Datei-Uploads +## Mehrere Datei-Uploads { #multiple-file-uploads } Es ist auch möglich, mehrere Dateien gleichzeitig hochzuladen. @@ -151,22 +155,22 @@ Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s: {* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} -Sie erhalten, wie deklariert, eine `list`e von `bytes` oder `UploadFile`s. +Sie erhalten, wie deklariert, eine `list` von `bytes` oder `UploadFile`s. /// note | Technische Details Sie können auch `from starlette.responses import HTMLResponse` verwenden. -**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. /// -### Mehrere Datei-Uploads mit zusätzlichen Metadaten +### Mehrere Datei-Uploads mit zusätzlichen Metadaten { #multiple-file-uploads-with-additional-metadata } Und so wie zuvor können Sie `File()` verwenden, um zusätzliche Parameter zu setzen, sogar für `UploadFile`: {* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} -## Zusammenfassung +## Zusammenfassung { #recap } Verwenden Sie `File`, `bytes` und `UploadFile`, um hochladbare Dateien im Request zu deklarieren, die als Formulardaten gesendet werden. diff --git a/docs/de/docs/tutorial/request-form-models.md b/docs/de/docs/tutorial/request-form-models.md new file mode 100644 index 000000000..fbc6c094c --- /dev/null +++ b/docs/de/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# Formularmodelle { #form-models } + +Sie können **Pydantic-Modelle** verwenden, um **Formularfelder** in FastAPI zu deklarieren. + +/// info | Info + +Um Formulare zu verwenden, installieren Sie zuerst `python-multipart`. + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und es dann installieren, zum Beispiel: + +```console +$ pip install python-multipart +``` + +/// + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.113.0` unterstützt. 🤓 + +/// + +## Pydantic-Modelle für Formulare { #pydantic-models-for-forms } + +Sie müssen nur ein **Pydantic-Modell** mit den Feldern deklarieren, die Sie als **Formularfelder** erhalten möchten, und dann den Parameter als `Form` deklarieren: + +{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den **Formulardaten** im Request **extrahieren** und Ihnen das von Ihnen definierte Pydantic-Modell übergeben. + +## Die Dokumentation testen { #check-the-docs } + +Sie können dies in der Dokumentations-UI unter `/docs` testen: + +
+ +
+ +## Zusätzliche Formularfelder verbieten { #forbid-extra-form-fields } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Formularfelder auf nur diejenigen beschränken, die im Pydantic-Modell deklariert sind, und jegliche **zusätzlichen** Felder **verbieten**. + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.114.0` unterstützt. 🤓 + +/// + +Sie können die Modellkonfiguration von Pydantic verwenden, um jegliche `extra` Felder zu `verbieten`: + +{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} + +Wenn ein Client versucht, einige zusätzliche Daten zu senden, erhält er eine **Error-Response**. + +Zum Beispiel, wenn der Client versucht, folgende Formularfelder zu senden: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +erhält er eine Error-Response, die ihm mitteilt, dass das Feld `extra` nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## Zusammenfassung { #summary } + +Sie können Pydantic-Modelle verwenden, um Formularfelder in FastAPI zu deklarieren. 😎 diff --git a/docs/de/docs/tutorial/request-forms-and-files.md b/docs/de/docs/tutorial/request-forms-and-files.md index 3c5e11adf..cda38bcc2 100644 --- a/docs/de/docs/tutorial/request-forms-and-files.md +++ b/docs/de/docs/tutorial/request-forms-and-files.md @@ -1,22 +1,26 @@ -# Formulardaten und Dateien im Request +# Formulardaten und Dateien im Request { #request-forms-and-files } Sie können gleichzeitig Dateien und Formulardaten mit `File` und `Form` definieren. -/// info +/// info | Info -Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst `python-multipart`. +Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst `python-multipart`. -Z. B. `pip install python-multipart`. +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, diese aktivieren und es dann installieren, z. B.: + +```console +$ pip install python-multipart +``` /// -## `File` und `Form` importieren +## `File` und `Form` importieren { #import-file-and-form } {* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} -## `File` und `Form`-Parameter definieren +## `File` und `Form`-Parameter definieren { #define-file-and-form-parameters } -Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` und `Query` machen würden: +Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` oder `Query` machen würden: {* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} @@ -26,12 +30,12 @@ Und Sie können einige der Dateien als `bytes` und einige als `UploadFile` dekla /// warning | Achtung -Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert. +Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht auch `Body`-Felder deklarieren, die Sie als JSON erwarten, da der Body des Request mittels `multipart/form-data` statt `application/json` kodiert sein wird. Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls. /// -## Zusammenfassung +## Zusammenfassung { #recap } Verwenden Sie `File` und `Form` zusammen, wenn Sie Daten und Dateien zusammen im selben Request empfangen müssen. diff --git a/docs/de/docs/tutorial/request-forms.md b/docs/de/docs/tutorial/request-forms.md index 2f88caaba..5c2ace67b 100644 --- a/docs/de/docs/tutorial/request-forms.md +++ b/docs/de/docs/tutorial/request-forms.md @@ -1,34 +1,38 @@ -# Formulardaten +# Formulardaten { #form-data } Wenn Sie Felder aus Formularen statt JSON empfangen müssen, können Sie `Form` verwenden. -/// info +/// info | Info -Um Formulare zu verwenden, installieren Sie zuerst `python-multipart`. +Um Formulare zu verwenden, installieren Sie zuerst `python-multipart`. -Z. B. `pip install python-multipart`. +Erstellen Sie unbedingt eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}, aktivieren Sie diese und installieren Sie dann das Paket, zum Beispiel: + +```console +$ pip install python-multipart +``` /// -## `Form` importieren +## `Form` importieren { #import-form } Importieren Sie `Form` von `fastapi`: {* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} -## `Form`-Parameter definieren +## `Form`-Parameter definieren { #define-form-parameters } Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` und `Query` machen würden: {* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} -Zum Beispiel stellt eine der Möglichkeiten, die OAuth2 Spezifikation zu verwenden (genannt „password flow“), die Bedingung, einen `username` und ein `password` als Formularfelder zu senden. +Zum Beispiel stellt eine der Möglichkeiten, die OAuth2-Spezifikation zu verwenden (genannt „password flow“), die Bedingung, einen `username` und ein `password` als Formularfelder zu senden. Die Spec erfordert, dass die Felder exakt `username` und `password` genannt werden und als Formularfelder, nicht JSON, gesendet werden. Mit `Form` haben Sie die gleichen Konfigurationsmöglichkeiten wie mit `Body` (und `Query`, `Path`, `Cookie`), inklusive Validierung, Beispielen, einem Alias (z. B. `user-name` statt `username`), usw. -/// info +/// info | Info `Form` ist eine Klasse, die direkt von `Body` erbt. @@ -36,34 +40,34 @@ Mit `Form` haben Sie die gleichen Konfigurationsmöglichkeiten wie mit `Body` (u /// tip | Tipp -Um Formularbodys zu deklarieren, verwenden Sie explizit `Form`, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden. +Um Formularbodys zu deklarieren, verwenden Sie explizit `Form`, da diese Parameter sonst als Query-Parameter oder Body (JSON)-Parameter interpretiert werden würden. /// -## Über „Formularfelder“ +## Über „Formularfelder“ { #about-form-fields } -HTML-Formulare (`
`) senden die Daten in einer „speziellen“ Kodierung zum Server, welche sich von JSON unterscheidet. +HTML-Formulare (`
`) senden die Daten in einer „speziellen“ Kodierung zum Server, die sich von JSON unterscheidet. **FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten. /// note | Technische Details -Daten aus Formularen werden normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. +Daten aus Formularen werden normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. Wenn das Formular stattdessen Dateien enthält, werden diese mit `multipart/form-data` kodiert. Im nächsten Kapitel erfahren Sie mehr über die Handhabung von Dateien. -Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die MDN-Webdokumentation für POST. +Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die MDN-Webdokumentation für POST. /// /// warning | Achtung -Sie können mehrere `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert. +Sie können mehrere `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert. Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls. /// -## Zusammenfassung +## Zusammenfassung { #recap } Verwenden Sie `Form`, um Eingabe-Parameter für Formulardaten zu deklarieren. diff --git a/docs/de/docs/tutorial/response-model.md b/docs/de/docs/tutorial/response-model.md index faf9be516..7b77125cb 100644 --- a/docs/de/docs/tutorial/response-model.md +++ b/docs/de/docs/tutorial/response-model.md @@ -1,6 +1,6 @@ -# Responsemodell – Rückgabetyp +# Responsemodell – Rückgabetyp { #response-model-return-type } -Sie können den Typ der Response deklarieren, indem Sie den **Rückgabetyp** der *Pfadoperation* annotieren. +Sie können den Typ der Response deklarieren, indem Sie den **Rückgabetyp** der *Pfadoperation* annotieren. Hierbei können Sie **Typannotationen** genauso verwenden, wie Sie es bei Werten von Funktions-**Parametern** machen; verwenden Sie Pydantic-Modelle, Listen, Dicts und skalare Werte wie Nummern, Booleans, usw. @@ -9,7 +9,7 @@ Hierbei können Sie **Typannotationen** genauso verwenden, wie Sie es bei Werten FastAPI wird diesen Rückgabetyp verwenden, um: * Die zurückzugebenden Daten zu **validieren**. - * Wenn die Daten ungültig sind (Sie haben z. B. ein Feld vergessen), bedeutet das, *Ihr* Anwendungscode ist fehlerhaft, er gibt nicht zurück, was er sollte, und daher wird ein Server-Error ausgegeben, statt falscher Daten. So können Sie und ihre Clients sicher sein, dass diese die erwarteten Daten, in der richtigen Form erhalten. + * Wenn die Daten ungültig sind (Sie haben z. B. ein Feld vergessen), bedeutet das, *Ihr* Anwendungscode ist fehlerhaft, er gibt nicht zurück, was er sollte, und daher wird ein Server-Error ausgegeben, statt falscher Daten. So können Sie und Ihre Clients sicher sein, dass diese die erwarteten Daten, in der richtigen Form erhalten. * In der OpenAPI *Pfadoperation* ein **JSON-Schema** für die Response hinzuzufügen. * Dieses wird von der **automatischen Dokumentation** verwendet. * Es wird auch von automatisch Client-Code-generierenden Tools verwendet. @@ -19,11 +19,11 @@ Aber am wichtigsten: * Es wird die Ausgabedaten auf das **limitieren und filtern**, was im Rückgabetyp definiert ist. * Das ist insbesondere für die **Sicherheit** wichtig, mehr dazu unten. -## `response_model`-Parameter +## `response_model`-Parameter { #response-model-parameter } Es gibt Fälle, da möchten oder müssen Sie Daten zurückgeben, die nicht genau dem entsprechen, was der Typ deklariert. -Zum Beispiel könnten Sie **ein Dict zurückgeben** wollen, oder ein Datenbank-Objekt, aber **es als Pydantic-Modell deklarieren**. Auf diese Weise übernimmt das Pydantic-Modell alle Datendokumentation, -validierung, usw. für das Objekt, welches Sie zurückgeben (z. B. ein Dict oder ein Datenbank-Objekt). +Zum Beispiel könnten Sie **ein Dictionary zurückgeben** wollen, oder ein Datenbank-Objekt, aber **es als Pydantic-Modell deklarieren**. Auf diese Weise übernimmt das Pydantic-Modell alle Datendokumentation, -validierung, usw. für das Objekt, welches Sie zurückgeben (z. B. ein Dictionary oder ein Datenbank-Objekt). Würden Sie eine hierfür eine Rückgabetyp-Annotation verwenden, dann würden Tools und Editoren (korrekterweise) Fehler ausgeben, die Ihnen sagen, dass Ihre Funktion einen Typ zurückgibt (z. B. ein Dict), der sich unterscheidet von dem, was Sie deklariert haben (z. B. ein Pydantic-Modell). @@ -41,7 +41,7 @@ Sie können `response_model` in jeder möglichen *Pfadoperation* verwenden: /// note | Hinweis -Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter. +Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body. /// @@ -51,32 +51,41 @@ FastAPI wird dieses `response_model` nehmen, um die Daten zu dokumentieren, vali /// tip | Tipp -Wenn Sie in Ihrem Editor strikte Typchecks haben, mypy, usw., können Sie den Funktions-Rückgabetyp als `Any` deklarieren. +Wenn Sie in Ihrem Editor strikte Typchecks haben, mypy, usw., können Sie den Funktions-Rückgabetyp als `Any` deklarieren. So sagen Sie dem Editor, dass Sie absichtlich *irgendetwas* zurückgeben. Aber FastAPI wird trotzdem die Dokumentation, Validierung, Filterung, usw. der Daten übernehmen, via `response_model`. /// -### `response_model`-Priorität +### `response_model`-Priorität { #response-model-priority } Wenn sowohl Rückgabetyp als auch `response_model` deklariert sind, hat `response_model` die Priorität und wird von FastAPI bevorzugt verwendet. -So können Sie korrekte Typannotationen zu ihrer Funktion hinzufügen, die von ihrem Editor und Tools wie mypy verwendet werden. Und dennoch übernimmt FastAPI die Validierung und Dokumentation, usw., der Daten anhand von `response_model`. +So können Sie korrekte Typannotationen zu Ihrer Funktion hinzufügen, die von Ihrem Editor und Tools wie mypy verwendet werden. Und dennoch übernimmt FastAPI die Validierung und Dokumentation, usw., der Daten anhand von `response_model`. -Sie können auch `response_model=None` verwenden, um das Erstellen eines Responsemodells für diese *Pfadoperation* zu unterbinden. Sie könnten das tun wollen, wenn sie Dinge annotieren, die nicht gültige Pydantic-Felder sind. Ein Beispiel dazu werden Sie in einer der Abschnitte unten sehen. +Sie können auch `response_model=None` verwenden, um das Erstellen eines Responsemodells für diese *Pfadoperation* zu unterbinden. Sie könnten das tun wollen, wenn Sie Dinge annotieren, die nicht gültige Pydantic-Felder sind. Ein Beispiel dazu werden Sie in einer der Abschnitte unten sehen. -## Dieselben Eingabedaten zurückgeben +## Dieselben Eingabedaten zurückgeben { #return-the-same-input-data } Im Folgenden deklarieren wir ein `UserIn`-Modell; es enthält ein Klartext-Passwort: {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info +/// info | Info Um `EmailStr` zu verwenden, installieren Sie zuerst `email-validator`. -Z. B. `pip install email-validator` -oder `pip install pydantic[email]`. +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und es dann installieren, zum Beispiel: + +```console +$ pip install email-validator +``` + +oder mit: + +```console +$ pip install "pydantic[email]" +``` /// @@ -96,7 +105,7 @@ Speichern Sie niemals das Klartext-Passwort eines Benutzers, oder versenden Sie /// -## Ausgabemodell hinzufügen +## Ausgabemodell hinzufügen { #add-an-output-model } Wir können stattdessen ein Eingabemodell mit dem Klartext-Passwort, und ein Ausgabemodell ohne das Passwort erstellen: @@ -112,7 +121,7 @@ Obwohl unsere *Pfadoperation-Funktion* hier denselben `user` von der Eingabe zur Darum wird **FastAPI** sich darum kümmern, dass alle Daten, die nicht im Ausgabemodell deklariert sind, herausgefiltert werden (mittels Pydantic). -### `response_model` oder Rückgabewert +### `response_model` oder Rückgabewert { #response-model-or-return-type } Da unsere zwei Modelle in diesem Fall unterschiedlich sind, würde, wenn wir den Rückgabewert der Funktion als `UserOut` deklarieren, der Editor sich beschweren, dass wir einen ungültigen Typ zurückgeben, weil das unterschiedliche Klassen sind. @@ -120,11 +129,11 @@ Darum müssen wir es in diesem Fall im `response_model`-Parameter deklarieren. ... aber lesen Sie weiter, um zu sehen, wie man das anders lösen kann. -## Rückgabewert und Datenfilterung +## Rückgabewert und Datenfilterung { #return-type-and-data-filtering } -Führen wir unser vorheriges Beispiel fort. Wir wollten **die Funktion mit einem Typ annotieren**, aber etwas zurückgeben, das **weniger Daten** enthält. +Führen wir unser vorheriges Beispiel fort. Wir wollten **die Funktion mit einem Typ annotieren**, aber wir wollten in der Funktion tatsächlich etwas zurückgeben, das **mehr Daten** enthält. -Wir möchten auch, dass FastAPI die Daten weiterhin, dem Responsemodell entsprechend, **filtert**. +Wir möchten, dass FastAPI die Daten weiterhin mithilfe des Responsemodells **filtert**. Selbst wenn die Funktion mehr Daten zurückgibt, soll die Response nur die Felder enthalten, die im Responsemodell deklariert sind. Im vorherigen Beispiel mussten wir den `response_model`-Parameter verwenden, weil die Klassen unterschiedlich waren. Das bedeutet aber auch, wir bekommen keine Unterstützung vom Editor und anderen Tools, die den Funktions-Rückgabewert überprüfen. @@ -138,17 +147,17 @@ Damit erhalten wir Tool-Unterstützung, vom Editor und mypy, da dieser Code hins Wie funktioniert das? Schauen wir uns das mal an. 🤓 -### Typannotationen und Tooling +### Typannotationen und Tooling { #type-annotations-and-tooling } Sehen wir uns zunächst an, wie Editor, mypy und andere Tools dies sehen würden. -`BaseUser` verfügt über die Basis-Felder. Dann erbt `UserIn` von `BaseUser` und fügt das Feld `Passwort` hinzu, sodass dass es nun alle Felder beider Modelle hat. +`BaseUser` verfügt über die Basis-Felder. Dann erbt `UserIn` von `BaseUser` und fügt das Feld `password` hinzu, sodass es nun alle Felder beider Modelle hat. Wir annotieren den Funktionsrückgabetyp als `BaseUser`, geben aber tatsächlich eine `UserIn`-Instanz zurück. Für den Editor, mypy und andere Tools ist das kein Problem, da `UserIn` eine Unterklasse von `BaseUser` ist (Salopp: `UserIn` ist ein `BaseUser`). Es handelt sich um einen *gültigen* Typ, solange irgendetwas überreicht wird, das ein `BaseUser` ist. -### FastAPI Datenfilterung +### FastAPI Datenfilterung { #fastapi-data-filtering } FastAPI seinerseits wird den Rückgabetyp sehen und sicherstellen, dass das, was zurückgegeben wird, **nur** diejenigen Felder enthält, welche im Typ deklariert sind. @@ -156,7 +165,7 @@ FastAPI macht intern mehrere Dinge mit Pydantic, um sicherzustellen, dass obige Auf diese Weise erhalten Sie das beste beider Welten: Sowohl Typannotationen mit **Tool-Unterstützung** als auch **Datenfilterung**. -## Anzeige in der Dokumentation +## Anzeige in der Dokumentation { #see-it-in-the-docs } Wenn Sie sich die automatische Dokumentation betrachten, können Sie sehen, dass Eingabe- und Ausgabemodell beide ihr eigenes JSON-Schema haben: @@ -166,11 +175,11 @@ Und beide Modelle werden auch in der interaktiven API-Dokumentation verwendet: -## Andere Rückgabetyp-Annotationen +## Andere Rückgabetyp-Annotationen { #other-return-type-annotations } Es kann Fälle geben, bei denen Sie etwas zurückgeben, das kein gültiges Pydantic-Feld ist, und Sie annotieren es in der Funktion nur, um Unterstützung von Tools zu erhalten (Editor, mypy, usw.). -### Eine Response direkt zurückgeben +### Eine Response direkt zurückgeben { #return-a-response-directly } Der häufigste Anwendungsfall ist, wenn Sie [eine Response direkt zurückgeben, wie es später im Handbuch für fortgeschrittene Benutzer erläutert wird](../advanced/response-directly.md){.internal-link target=_blank}. @@ -180,7 +189,7 @@ Dieser einfache Anwendungsfall wird automatisch von FastAPI gehandhabt, weil die Und Tools werden auch glücklich sein, weil sowohl `RedirectResponse` als auch `JSONResponse` Unterklassen von `Response` sind, die Typannotation ist daher korrekt. -### Eine Unterklasse von Response annotieren +### Eine Unterklasse von Response annotieren { #annotate-a-response-subclass } Sie können auch eine Unterklasse von `Response` in der Typannotation verwenden. @@ -188,17 +197,17 @@ Sie können auch eine Unterklasse von `Response` in der Typannotation verwenden. Das wird ebenfalls funktionieren, weil `RedirectResponse` eine Unterklasse von `Response` ist, und FastAPI sich um diesen einfachen Anwendungsfall automatisch kümmert. -### Ungültige Rückgabetyp-Annotationen +### Ungültige Rückgabetyp-Annotationen { #invalid-return-type-annotations } Aber wenn Sie ein beliebiges anderes Objekt zurückgeben, das kein gültiger Pydantic-Typ ist (z. B. ein Datenbank-Objekt), und Sie annotieren es so in der Funktion, wird FastAPI versuchen, ein Pydantic-Responsemodell von dieser Typannotation zu erstellen, und scheitern. -Das gleiche wird passieren, wenn Sie eine Union mehrerer Typen haben, und einer oder mehrere sind nicht gültige Pydantic-Typen. Zum Beispiel funktioniert folgendes nicht 💥: +Das gleiche wird passieren, wenn Sie eine Union mehrerer Typen haben, und einer oder mehrere sind nicht gültige Pydantic-Typen. Zum Beispiel funktioniert folgendes nicht 💥: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} ... das scheitert, da die Typannotation kein Pydantic-Typ ist, und auch keine einzelne `Response`-Klasse, oder -Unterklasse, es ist eine Union (eines von beiden) von `Response` und `dict`. -### Responsemodell deaktivieren +### Responsemodell deaktivieren { #disable-response-model } Beim Beispiel oben fortsetzend, mögen Sie vielleicht die standardmäßige Datenvalidierung, -Dokumentation, -Filterung, usw., die von FastAPI durchgeführt wird, nicht haben. @@ -210,7 +219,7 @@ In diesem Fall können Sie die Generierung des Responsemodells abschalten, indem Das bewirkt, dass FastAPI die Generierung des Responsemodells unterlässt, und damit können Sie jede gewünschte Rückgabetyp-Annotation haben, ohne dass es Ihre FastAPI-Anwendung beeinflusst. 🤓 -## Parameter für die Enkodierung des Responsemodells +## Parameter für die Enkodierung des Responsemodells { #response-model-encoding-parameters } Ihr Responsemodell könnte Defaultwerte haben, wie: @@ -224,7 +233,7 @@ Aber Sie möchten diese vielleicht vom Resultat ausschließen, wenn Sie gar nich Wenn Sie zum Beispiel Modelle mit vielen optionalen Attributen in einer NoSQL-Datenbank haben, und Sie möchten nicht ellenlange JSON-Responses voller Defaultwerte senden. -### Den `response_model_exclude_unset`-Parameter verwenden +### Den `response_model_exclude_unset`-Parameter verwenden { #use-the-response-model-exclude-unset-parameter } Sie können den *Pfadoperation-Dekorator*-Parameter `response_model_exclude_unset=True` setzen: @@ -241,21 +250,21 @@ Wenn Sie also den Artikel mit der ID `foo` bei der *Pfadoperation* anfragen, wir } ``` -/// info +/// info | Info -In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt. +In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecatet (aber immer noch unterstützt) und in `.model_dump()` umbenannt. Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können. /// -/// info +/// info | Info FastAPI verwendet `.dict()` von Pydantic Modellen, mit dessen `exclude_unset`-Parameter, um das zu erreichen. /// -/// info +/// info | Info Sie können auch: @@ -266,9 +275,9 @@ verwenden, wie in der Response mit dem Parameter `status_code` in jeder der *Pfadoperationen* deklarieren: * `@app.get()` * `@app.post()` @@ -12,90 +12,90 @@ So wie ein Responsemodell, können Sie auch einen HTTP-Statuscode für die Respo /// note | Hinweis -Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body. +Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, wie alle anderen Parameter und der Body. /// Dem `status_code`-Parameter wird eine Zahl mit dem HTTP-Statuscode übergeben. -/// info +/// info | Info -Alternativ kann `status_code` auch ein `IntEnum` erhalten, so wie Pythons `http.HTTPStatus`. +Alternativ kann `status_code` auch ein `IntEnum` erhalten, wie etwa Pythons `http.HTTPStatus`. /// -Das wird: +Dies wird: * Diesen Statuscode mit der Response zurücksenden. -* Ihn als solchen im OpenAPI-Schema dokumentieren (und somit in den Benutzeroberflächen): +* Diesen im OpenAPI-Schema dokumentieren (und somit in den Benutzeroberflächen): /// note | Hinweis -Einige Responsecodes (siehe nächster Abschnitt) kennzeichnen, dass die Response keinen Body hat. +Einige Responsecodes (siehe nächsten Abschnitt) kennzeichnen, dass die Response keinen Body hat. -FastAPI versteht das und wird in der OpenAPI-Dokumentation anzeigen, dass es keinen Responsebody gibt. +FastAPI erkennt dies und erstellt eine OpenAPI-Dokumentation, die zeigt, dass es keinen Responsebody gibt. /// -## Über HTTP-Statuscodes +## Über HTTP-Statuscodes { #about-http-status-codes } /// note | Hinweis -Wenn Sie bereits wissen, was HTTP-Statuscodes sind, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort. +Wenn Sie bereits wissen, was HTTP-Statuscodes sind, können Sie diesen Abschnitt überspringen und mit dem nächsten fortfahren. /// -In HTTP senden Sie als Teil der Response einen aus drei Ziffern bestehenden numerischen Statuscode. +In HTTP senden Sie einen numerischen Statuscode mit 3 Ziffern als Teil der Response. -Diese Statuscodes haben einen Namen zugeordnet, um sie besser zu erkennen, aber der wichtige Teil ist die Zahl. +Diese Statuscodes haben einen zugeordneten Namen, um sie leichter zu erkennen, aber der wichtige Teil ist die Zahl. -Kurz: +Kurz gefasst: -* `100` und darüber stehen für „Information“. Diese verwenden Sie selten direkt. Responses mit diesen Statuscodes können keinen Body haben. -* **`200`** und darüber stehen für Responses, die „Successful“ („Erfolgreich“) waren. Diese verwenden Sie am häufigsten. - * `200` ist der Default-Statuscode, welcher bedeutet, alles ist „OK“. - * Ein anderes Beispiel ist `201`, „Created“ („Erzeugt“). Wird in der Regel verwendet, wenn ein neuer Datensatz in der Datenbank erzeugt wurde. - * Ein spezieller Fall ist `204`, „No Content“ („Kein Inhalt“). Diese Response wird verwendet, wenn es keinen Inhalt gibt, der zum Client zurückgeschickt wird, diese Response hat also keinen Body. -* **`300`** und darüber steht für „Redirection“ („Umleitung“). Responses mit diesen Statuscodes können einen oder keinen Body haben, mit Ausnahme von `304`, „Not Modified“ („Nicht verändert“), welche keinen haben darf. -* **`400`** und darüber stehen für „Client error“-Responses („Client-Fehler“). Auch diese verwenden Sie am häufigsten. +* `100 - 199` stehen für „Information“. Sie verwenden diese selten direkt. Responses mit diesen Statuscodes dürfen keinen Body haben. +* **`200 - 299`** stehen für „Successful“-Responses („Erfolgreich“). Diese werden Sie am häufigsten verwenden. + * `200` ist der Default-Statuscode, was bedeutet, alles ist „OK“. + * Ein weiteres Beispiel wäre `201`, „Created“ („Erzeugt“). Dieser wird üblicherweise verwendet, nachdem ein neuer Datensatz in der Datenbank erstellt wurde. + * Ein spezieller Fall ist `204`, „No Content“ („Kein Inhalt“). Diese Response wird verwendet, wenn es keinen Inhalt gibt, der an den Client zurückgeschickt werden soll, und diese Response darf daher keinen Body haben. +* **`300 - 399`** stehen für „Redirection“ („Umleitung“). Responses mit diesen Statuscodes können einen Body haben oder nicht, außer bei `304`, „Not Modified“ („Nicht verändert“), die keinen haben darf. +* **`400 - 499`** stehen für „Client error“-Responses („Client-Fehler“). Diese sind die zweithäufigsten, die Sie vermutlich verwenden werden. * Ein Beispiel ist `404`, für eine „Not Found“-Response („Nicht gefunden“). * Für allgemeine Fehler beim Client können Sie einfach `400` verwenden. -* `500` und darüber stehen für Server-Fehler. Diese verwenden Sie fast nie direkt. Wenn etwas an irgendeiner Stelle in Ihrem Anwendungscode oder im Server schiefläuft, wird automatisch einer dieser Fehler-Statuscodes zurückgegeben. +* `500 - 599` stehen für Server-Fehler. Diese verwenden Sie fast nie direkt. Wenn in Ihrem Anwendungscode oder Server etwas schiefgeht, wird automatisch einer dieser Fehler-Statuscodes zurückgegeben. /// tip | Tipp -Um mehr über Statuscodes zu lernen, und welcher wofür verwendet wird, lesen Sie die MDN Dokumentation über HTTP-Statuscodes. +Um mehr über die einzelnen Statuscodes zu erfahren und welcher wofür verwendet wird, sehen Sie sich die MDN Dokumentation über HTTP-Statuscodes an. /// -## Abkürzung, um die Namen zu erinnern +## Abkürzung zur Erinnerung an die Namen { #shortcut-to-remember-the-names } -Schauen wir uns das vorherige Beispiel noch einmal an: +Lassen Sie uns das vorherige Beispiel noch einmal anschauen: {* ../../docs_src/response_status_code/tutorial001.py hl[6] *} `201` ist der Statuscode für „Created“ („Erzeugt“). -Aber Sie müssen sich nicht daran erinnern, welcher dieser Codes was bedeutet. +Aber Sie müssen sich nicht merken, was jeder dieser Codes bedeutet. -Sie können die Hilfsvariablen von `fastapi.status` verwenden. +Sie können die Annehmlichkeit von Variablen aus `fastapi.status` nutzen. {* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *} -Diese sind nur eine Annehmlichkeit und enthalten dieselbe Nummer, aber auf diese Weise können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden: +Diese sind nur eine Annehmlichkeit, sie enthalten dieselbe Zahl, aber so können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden: /// note | Technische Details -Sie können auch `from starlette import status` verwenden. +Sie könnten auch `from starlette import status` verwenden. -**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette. +**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, rein zu Ihrer Annehmlichkeit als Entwickler. Aber sie stammen direkt von Starlette. /// -## Den Defaultwert ändern +## Den Defaultwert ändern { #changing-the-default } -Später sehen Sie, im [Handbuch für fortgeschrittene Benutzer](../advanced/response-change-status-code.md){.internal-link target=_blank}, wie Sie einen anderen Statuscode zurückgeben können, als den Default, den Sie hier deklarieren. +Später im [Handbuch für fortgeschrittene Benutzer](../advanced/response-change-status-code.md){.internal-link target=_blank} werden Sie sehen, wie Sie einen anderen Statuscode zurückgeben können, als den Default, den Sie hier deklarieren. diff --git a/docs/de/docs/tutorial/schema-extra-example.md b/docs/de/docs/tutorial/schema-extra-example.md index f065ad4ca..e2ffed292 100644 --- a/docs/de/docs/tutorial/schema-extra-example.md +++ b/docs/de/docs/tutorial/schema-extra-example.md @@ -1,10 +1,10 @@ -# Beispiel-Request-Daten deklarieren +# Beispiel-Request-Daten deklarieren { #declare-request-example-data } -Sie können Beispiele für die Daten deklarieren, die Ihre Anwendung empfangen kann. +Sie können Beispiele für die Daten deklarieren, die Ihre App empfangen kann. Hier sind mehrere Möglichkeiten, das zu tun. -## Zusätzliche JSON-Schemadaten in Pydantic-Modellen +## Zusätzliche JSON-Schemadaten in Pydantic-Modellen { #extra-json-schema-data-in-pydantic-models } Sie können `examples` („Beispiele“) für ein Pydantic-Modell deklarieren, welche dem generierten JSON-Schema hinzugefügt werden. @@ -24,7 +24,7 @@ Diese zusätzlichen Informationen werden unverändert zum für dieses Modell aus //// tab | Pydantic v2 -In Pydantic Version 2 würden Sie das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in Pydantic-Dokumentation: Configuration. +In Pydantic Version 2 würden Sie das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in Pydantic-Dokumentation: Configuration. Sie können `json_schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`. @@ -46,23 +46,23 @@ Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benut /// -/// info +/// info | Info OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für `examples` hinzugefügt, was Teil des **JSON Schema** Standards ist. -Zuvor unterstützte es nur das Schlüsselwort `example` mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch deprecated und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von `example` nach `examples` zu migrieren. 🤓 +Zuvor unterstützte es nur das Schlüsselwort `example` mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch deprecatet und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von `example` nach `examples` zu migrieren. 🤓 Mehr erfahren Sie am Ende dieser Seite. /// -## Zusätzliche Argumente für `Field` +## Zusätzliche Argumente für `Field` { #field-additional-arguments } Wenn Sie `Field()` mit Pydantic-Modellen verwenden, können Sie ebenfalls zusätzliche `examples` deklarieren: {* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} -## `examples` im JSON-Schema – OpenAPI +## `examples` im JSON-Schema – OpenAPI { #examples-in-json-schema-openapi } Bei Verwendung von: @@ -76,19 +76,19 @@ Bei Verwendung von: können Sie auch eine Gruppe von `examples` mit zusätzlichen Informationen deklarieren, die zu ihren **JSON-Schemas** innerhalb von **OpenAPI** hinzugefügt werden. -### `Body` mit `examples` +### `Body` mit `examples` { #body-with-examples } Hier übergeben wir `examples`, welches ein einzelnes Beispiel für die in `Body()` erwarteten Daten enthält: {* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} -### Beispiel in der Dokumentations-Benutzeroberfläche +### Beispiel in der Dokumentations-Benutzeroberfläche { #example-in-the-docs-ui } Mit jeder der oben genannten Methoden würde es in `/docs` so aussehen: -### `Body` mit mehreren `examples` +### `Body` mit mehreren `examples` { #body-with-multiple-examples } Sie können natürlich auch mehrere `examples` übergeben: @@ -96,9 +96,9 @@ Sie können natürlich auch mehrere `examples` übergeben: Wenn Sie das tun, werden die Beispiele Teil des internen **JSON-Schemas** für diese Body-Daten. -Während dies geschrieben wird, unterstützt Swagger UI, das für die Anzeige der Dokumentations-Benutzeroberfläche zuständige Tool, jedoch nicht die Anzeige mehrerer Beispiele für die Daten in **JSON Schema**. Aber lesen Sie unten für einen Workaround weiter. +Während dies geschrieben wird, unterstützt Swagger UI, das für die Anzeige der Dokumentations-Benutzeroberfläche zuständige Tool, jedoch nicht die Anzeige mehrerer Beispiele für die Daten in **JSON Schema**. Aber lesen Sie unten für einen Workaround weiter. -### OpenAPI-spezifische `examples` +### OpenAPI-spezifische `examples` { #openapi-specific-examples } Schon bevor **JSON Schema** `examples` unterstützte, unterstützte OpenAPI ein anderes Feld, das auch `examples` genannt wurde. @@ -106,11 +106,11 @@ Diese **OpenAPI-spezifischen** `examples` finden sich in einem anderen Abschnitt Und Swagger UI unterstützt dieses spezielle Feld `examples` schon seit einiger Zeit. Sie können es also verwenden, um verschiedene **Beispiele in der Benutzeroberfläche der Dokumentation anzuzeigen**. -Das Format dieses OpenAPI-spezifischen Felds `examples` ist ein `dict` mit **mehreren Beispielen** (anstelle einer `list`e), jedes mit zusätzlichen Informationen, die auch zu **OpenAPI** hinzugefügt werden. +Das Format dieses OpenAPI-spezifischen Felds `examples` ist ein `dict` mit **mehreren Beispielen** (anstelle einer `list`), jedes mit zusätzlichen Informationen, die auch zu **OpenAPI** hinzugefügt werden. Dies erfolgt nicht innerhalb jedes in OpenAPI enthaltenen JSON-Schemas, sondern außerhalb, in der *Pfadoperation*. -### Verwendung des Parameters `openapi_examples` +### Verwendung des Parameters `openapi_examples` { #using-the-openapi-examples-parameter } Sie können die OpenAPI-spezifischen `examples` in FastAPI mit dem Parameter `openapi_examples` deklarieren, für: @@ -122,7 +122,7 @@ Sie können die OpenAPI-spezifischen `examples` in FastAPI mit dem Parameter `op * `Form()` * `File()` -Die Schlüssel des `dict` identifizieren jedes Beispiel, und jeder Wert (`"value"`) ist ein weiteres `dict`. +Die Schlüssel des `dict` identifizieren jedes Beispiel, und jeder Wert ist ein weiteres `dict`. Jedes spezifische Beispiel-`dict` in den `examples` kann Folgendes enthalten: @@ -135,13 +135,13 @@ Sie können es so verwenden: {* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} -### OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche +### OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche { #openapi-examples-in-the-docs-ui } Wenn `openapi_examples` zu `Body()` hinzugefügt wird, würde `/docs` so aussehen: -## Technische Details +## Technische Details { #technical-details } /// tip | Tipp @@ -177,23 +177,23 @@ OpenAPI fügte auch die Felder `example` und `examples` zu anderen Teilen der Sp * `File()` * `Form()` -/// info +/// info | Info Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`. /// -### JSON Schemas Feld `examples` +### JSON Schemas Feld `examples` { #json-schemas-examples-field } Aber dann fügte JSON Schema ein `examples`-Feld zu einer neuen Version der Spezifikation hinzu. Und dann basierte das neue OpenAPI 3.1.0 auf der neuesten Version (JSON Schema 2020-12), die dieses neue Feld `examples` enthielt. -Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdefinierten) `example`-Feld, im Singular, das jetzt deprecated ist. +Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdefinierten) `example`-Feld, im Singular, das jetzt deprecatet ist. -Dieses neue `examples`-Feld in JSON Schema ist **nur eine `list`e** von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben). +Dieses neue `examples`-Feld in JSON Schema ist **nur eine `list`** von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben). -/// info +/// info | Info Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉). @@ -201,7 +201,7 @@ Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Version /// -### Pydantic- und FastAPI-`examples` +### Pydantic- und FastAPI-`examples` { #pydantic-and-fastapi-examples } Wenn Sie `examples` innerhalb eines Pydantic-Modells hinzufügen, indem Sie `schema_extra` oder `Field(examples=["something"])` verwenden, wird dieses Beispiel dem **JSON-Schema** für dieses Pydantic-Modell hinzugefügt. @@ -211,14 +211,14 @@ In Versionen von FastAPI vor 0.99.0 (0.99.0 und höher verwenden das neuere Open Aber jetzt, da FastAPI 0.99.0 und höher, OpenAPI 3.1.0 verwendet, das JSON Schema 2020-12 verwendet, und Swagger UI 5.0.0 und höher, ist alles konsistenter und die Beispiele sind in JSON Schema enthalten. -### Swagger-Benutzeroberfläche und OpenAPI-spezifische `examples`. +### Swagger-Benutzeroberfläche und OpenAPI-spezifische `examples` { #swagger-ui-and-openapi-specific-examples } Da die Swagger-Benutzeroberfläche derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen. Um dieses Problem zu lösen, hat FastAPI `0.103.0` **Unterstützung** für die Deklaration desselben alten **OpenAPI-spezifischen** `examples`-Felds mit dem neuen Parameter `openapi_examples` hinzugefügt. 🤓 -### Zusammenfassung +### Zusammenfassung { #summary } Ich habe immer gesagt, dass ich Geschichte nicht so sehr mag ... und jetzt schauen Sie mich an, wie ich „Technikgeschichte“-Unterricht gebe. 😅 -Kurz gesagt: **Upgraden Sie auf FastAPI 0.99.0 oder höher**, und die Dinge sind viel **einfacher, konsistenter und intuitiver**, und Sie müssen nicht alle diese historischen Details kennen. 😎 +Kurz gesagt: **Aktualisieren Sie auf FastAPI 0.99.0 oder höher**, und die Dinge sind viel **einfacher, konsistenter und intuitiver**, und Sie müssen nicht alle diese historischen Details kennen. 😎 diff --git a/docs/de/docs/tutorial/security/first-steps.md b/docs/de/docs/tutorial/security/first-steps.md index 8fa33db7e..20fcd0c00 100644 --- a/docs/de/docs/tutorial/security/first-steps.md +++ b/docs/de/docs/tutorial/security/first-steps.md @@ -1,8 +1,8 @@ -# Sicherheit – Erste Schritte +# Sicherheit – Erste Schritte { #security-first-steps } Stellen wir uns vor, dass Sie Ihre **Backend**-API auf einer Domain haben. -Und Sie haben ein **Frontend** auf einer anderen Domain oder in einem anderen Pfad derselben Domain (oder in einer mobilen Anwendung). +Und Sie haben ein **Frontend** auf einer anderen Domain oder in einem anderen Pfad derselben Domain (oder in einer Mobile-Anwendung). Und Sie möchten eine Möglichkeit haben, dass sich das Frontend mithilfe eines **Benutzernamens** und eines **Passworts** beim Backend authentisieren kann. @@ -12,25 +12,33 @@ Aber ersparen wir Ihnen die Zeit, die gesamte lange Spezifikation zu lesen, nur Lassen Sie uns die von **FastAPI** bereitgestellten Tools verwenden, um Sicherheit zu gewährleisten. -## Wie es aussieht +## Wie es aussieht { #how-it-looks } Lassen Sie uns zunächst einfach den Code verwenden und sehen, wie er funktioniert, und dann kommen wir zurück, um zu verstehen, was passiert. -## `main.py` erstellen +## `main.py` erstellen { #create-main-py } Kopieren Sie das Beispiel in eine Datei `main.py`: {* ../../docs_src/security/tutorial001_an_py39.py *} -## Ausführen +## Ausführen { #run-it } -/// info +/// info | Info -Um hochgeladene Dateien zu empfangen, installieren Sie zuerst `python-multipart`. +Das Paket `python-multipart` wird automatisch mit **FastAPI** installiert, wenn Sie den Befehl `pip install "fastapi[standard]"` ausführen. -Z. B. `pip install python-multipart`. +Wenn Sie jedoch den Befehl `pip install fastapi` verwenden, ist das Paket `python-multipart` nicht standardmäßig enthalten. -Das, weil **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet. +Um es manuell zu installieren, stellen Sie sicher, dass Sie eine [Virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und es dann mit: + +```console +$ pip install python-multipart +``` + +installieren. + +Das liegt daran, dass **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet. /// @@ -39,14 +47,14 @@ Führen Sie das Beispiel aus mit:
```console -$ uvicorn main:app --reload +$ fastapi dev main.py INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ```
-## Überprüfen +## Es testen { #check-it } Gehen Sie zu der interaktiven Dokumentation unter: http://127.0.0.1:8000/docs. @@ -80,7 +88,7 @@ Es kann von Anwendungen und Systemen Dritter verwendet werden. Und es kann auch von Ihnen selbst verwendet werden, um dieselbe Anwendung zu debuggen, zu prüfen und zu testen. -## Der `password`-Flow +## Der `password`-Flow { #the-password-flow } Lassen Sie uns nun etwas zurückgehen und verstehen, was das alles ist. @@ -103,16 +111,16 @@ Betrachten wir es also aus dieser vereinfachten Sicht: * Der Benutzer klickt im Frontend, um zu einem anderen Abschnitt der Frontend-Web-Anwendung zu gelangen. * Das Frontend muss weitere Daten von der API abrufen. * Es benötigt jedoch eine Authentifizierung für diesen bestimmten Endpunkt. - * Um sich also bei unserer API zu authentifizieren, sendet es einen Header `Authorization` mit dem Wert `Bearer` plus dem Token. + * Um sich also bei unserer API zu authentifizieren, sendet es einen Header `Authorization` mit dem Wert `Bearer ` plus dem Token. * Wenn der Token `foobar` enthielte, wäre der Inhalt des `Authorization`-Headers: `Bearer foobar`. -## **FastAPI**s `OAuth2PasswordBearer` +## **FastAPI**s `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } **FastAPI** bietet mehrere Tools auf unterschiedlichen Abstraktionsebenen zur Implementierung dieser Sicherheitsfunktionen. In diesem Beispiel verwenden wir **OAuth2** mit dem **Password**-Flow und einem **Bearer**-Token. Wir machen das mit der Klasse `OAuth2PasswordBearer`. -/// info +/// info | Info Ein „Bearer“-Token ist nicht die einzige Option. @@ -142,7 +150,7 @@ Dieser Parameter erstellt nicht diesen Endpunkt / diese *Pfadoperation*, sondern Wir werden demnächst auch die eigentliche Pfadoperation erstellen. -/// info +/// info | Info Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`. @@ -160,7 +168,7 @@ oauth2_scheme(some, parameters) Es kann also mit `Depends` verwendet werden. -### Verwendung +### Verwenden { #use-it } Jetzt können Sie dieses `oauth2_scheme` als Abhängigkeit `Depends` übergeben. @@ -178,11 +186,11 @@ Alle Sicherheits-Werkzeuge, die in OpenAPI integriert sind (und die automatische /// -## Was es macht +## Was es macht { #what-it-does } -FastAPI wird im Request nach diesem `Authorization`-Header suchen, prüfen, ob der Wert `Bearer` plus ein Token ist, und den Token als `str` zurückgeben. +FastAPI wird im Request nach diesem `Authorization`-Header suchen, prüfen, ob der Wert `Bearer ` plus ein Token ist, und den Token als `str` zurückgeben. -Wenn es keinen `Authorization`-Header sieht, oder der Wert keinen `Bearer`-Token hat, antwortet es direkt mit einem 401-Statuscode-Error (`UNAUTHORIZED`). +Wenn es keinen `Authorization`-Header sieht, oder der Wert keinen `Bearer `-Token hat, antwortet es direkt mit einem 401-Statuscode-Error (`UNAUTHORIZED`). Sie müssen nicht einmal prüfen, ob der Token existiert, um einen Fehler zurückzugeben. Seien Sie sicher, dass Ihre Funktion, wenn sie ausgeführt wird, ein `str` in diesem Token enthält. @@ -192,6 +200,6 @@ Sie können das bereits in der interaktiven Dokumentation ausprobieren: Wir überprüfen im Moment noch nicht die Gültigkeit des Tokens, aber das ist bereits ein Anfang. -## Zusammenfassung +## Zusammenfassung { #recap } -Mit nur drei oder vier zusätzlichen Zeilen haben Sie also bereits eine primitive Form der Sicherheit. +Mit nur drei oder vier zusätzlichen Zeilen haben Sie so bereits eine primitive Form der Sicherheit. diff --git a/docs/de/docs/tutorial/security/get-current-user.md b/docs/de/docs/tutorial/security/get-current-user.md index 38f7ffcbf..e32e36669 100644 --- a/docs/de/docs/tutorial/security/get-current-user.md +++ b/docs/de/docs/tutorial/security/get-current-user.md @@ -1,4 +1,4 @@ -# Aktuellen Benutzer abrufen +# Aktuellen Benutzer abrufen { #get-current-user } Im vorherigen Kapitel hat das Sicherheitssystem (das auf dem Dependency Injection System basiert) der *Pfadoperation-Funktion* einen `token` vom Typ `str` überreicht: @@ -8,15 +8,15 @@ Aber das ist immer noch nicht so nützlich. Lassen wir es uns den aktuellen Benutzer überreichen. -## Ein Benutzermodell erstellen +## Ein Benutzermodell erstellen { #create-a-user-model } Erstellen wir zunächst ein Pydantic-Benutzermodell. So wie wir Pydantic zum Deklarieren von Bodys verwenden, können wir es auch überall sonst verwenden: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} -## Eine `get_current_user`-Abhängigkeit erstellen +## Eine `get_current_user`-Abhängigkeit erstellen { #create-a-get-current-user-dependency } Erstellen wir eine Abhängigkeit `get_current_user`. @@ -28,13 +28,13 @@ So wie wir es zuvor in der *Pfadoperation* direkt gemacht haben, erhält unsere {* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} -## Den Benutzer holen +## Den Benutzer abrufen { #get-the-user } `get_current_user` wird eine von uns erstellte (gefakte) Hilfsfunktion verwenden, welche einen Token vom Typ `str` entgegennimmt und unser Pydantic-`User`-Modell zurückgibt: {* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} -## Den aktuellen Benutzer einfügen +## Den aktuellen Benutzer einfügen { #inject-the-current-user } Und jetzt können wir wiederum `Depends` mit unserem `get_current_user` in der *Pfadoperation* verwenden: @@ -46,13 +46,13 @@ Das wird uns innerhalb der Funktion bei Codevervollständigung und Typprüfungen /// tip | Tipp -Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden. +Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden. Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt. /// -/// check +/// check | Testen Die Art und Weise, wie dieses System von Abhängigkeiten konzipiert ist, ermöglicht es uns, verschiedene Abhängigkeiten (verschiedene „Dependables“) zu haben, die alle ein `User`-Modell zurückgeben. @@ -60,7 +60,7 @@ Wir sind nicht darauf beschränkt, nur eine Abhängigkeit zu haben, die diesen T /// -## Andere Modelle +## Andere Modelle { #other-models } Sie können jetzt den aktuellen Benutzer direkt in den *Pfadoperation-Funktionen* abrufen und die Sicherheitsmechanismen auf **Dependency Injection** Ebene handhaben, mittels `Depends`. @@ -76,7 +76,7 @@ Sie haben eigentlich keine Benutzer, die sich bei Ihrer Anwendung anmelden, sond Verwenden Sie einfach jede Art von Modell, jede Art von Klasse, jede Art von Datenbank, die Sie für Ihre Anwendung benötigen. **FastAPI** deckt das alles mit seinem Dependency Injection System ab. -## Codegröße +## Codegröße { #code-size } Dieses Beispiel mag ausführlich erscheinen. Bedenken Sie, dass wir Sicherheit, Datenmodelle, Hilfsfunktionen und *Pfadoperationen* in derselben Datei vermischen. @@ -94,7 +94,7 @@ Und alle diese Tausenden von *Pfadoperationen* können nur drei Zeilen lang sein {* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} -## Zusammenfassung +## Zusammenfassung { #recap } Sie können jetzt den aktuellen Benutzer direkt in Ihrer *Pfadoperation-Funktion* abrufen. diff --git a/docs/de/docs/tutorial/security/index.md b/docs/de/docs/tutorial/security/index.md index a31ec2239..39b0b93c9 100644 --- a/docs/de/docs/tutorial/security/index.md +++ b/docs/de/docs/tutorial/security/index.md @@ -1,4 +1,4 @@ -# Sicherheit +# Sicherheit { #security } Es gibt viele Wege, Sicherheit, Authentifizierung und Autorisierung zu handhaben. @@ -10,11 +10,11 @@ In vielen Frameworks und Systemen erfordert allein die Handhabung von Sicherheit Aber schauen wir uns zunächst ein paar kleine Konzepte an. -## In Eile? +## In Eile? { #in-a-hurry } Wenn Ihnen diese Begriffe egal sind und Sie einfach *jetzt* Sicherheit mit Authentifizierung basierend auf Benutzername und Passwort hinzufügen müssen, fahren Sie mit den nächsten Kapiteln fort. -## OAuth2 +## OAuth2 { #oauth2 } OAuth2 ist eine Spezifikation, die verschiedene Möglichkeiten zur Handhabung von Authentifizierung und Autorisierung definiert. @@ -24,7 +24,7 @@ Sie umfasst Möglichkeiten zur Authentifizierung mithilfe eines „Dritten“ ( Das ist es, was alle diese „Login mit Facebook, Google, X (Twitter), GitHub“-Systeme unter der Haube verwenden. -### OAuth 1 +### OAuth 1 { #oauth-1 } Es gab ein OAuth 1, das sich stark von OAuth2 unterscheidet und komplexer ist, da es direkte Spezifikationen enthält, wie die Kommunikation verschlüsselt wird. @@ -38,7 +38,7 @@ Im Abschnitt über **Deployment** erfahren Sie, wie Sie HTTPS mithilfe von Traef /// -## OpenID Connect +## OpenID Connect { #openid-connect } OpenID Connect ist eine weitere Spezifikation, die auf **OAuth2** basiert. @@ -48,7 +48,7 @@ Beispielsweise verwendet der Google Login OpenID Connect (welches seinerseits OA Aber der Facebook Login unterstützt OpenID Connect nicht. Es hat seine eigene Variante von OAuth2. -### OpenID (nicht „OpenID Connect“) +### OpenID (nicht „OpenID Connect“) { #openid-not-openid-connect } Es gab auch eine „OpenID“-Spezifikation. Sie versuchte das Gleiche zu lösen wie **OpenID Connect**, basierte aber nicht auf OAuth2. @@ -56,7 +56,7 @@ Es handelte sich also um ein komplett zusätzliches System. Heutzutage ist es nicht sehr populär und wird kaum verwendet. -## OpenAPI +## OpenAPI { #openapi } OpenAPI (früher bekannt als Swagger) ist die offene Spezifikation zum Erstellen von APIs (jetzt Teil der Linux Foundation). @@ -75,7 +75,7 @@ OpenAPI definiert die folgenden Sicherheitsschemas: * Einem Header. * Einem Cookie. * `http`: Standard-HTTP-Authentifizierungssysteme, einschließlich: - * `bearer`: ein Header `Authorization` mit dem Wert `Bearer` plus einem Token. Dies wird von OAuth2 geerbt. + * `bearer`: ein Header `Authorization` mit dem Wert `Bearer ` plus einem Token. Dies wird von OAuth2 geerbt. * HTTP Basic Authentication. * HTTP Digest, usw. * `oauth2`: Alle OAuth2-Methoden zum Umgang mit Sicherheit (genannt „Flows“). @@ -97,7 +97,7 @@ Das komplexeste Problem besteht darin, einen Authentifizierungs-/Autorisierungsa /// -## **FastAPI** Tools +## **FastAPI** Tools { #fastapi-utilities } FastAPI stellt für jedes dieser Sicherheitsschemas im Modul `fastapi.security` verschiedene Tools bereit, die die Verwendung dieser Sicherheitsmechanismen vereinfachen. diff --git a/docs/de/docs/tutorial/security/oauth2-jwt.md b/docs/de/docs/tutorial/security/oauth2-jwt.md index bf46ce59b..4b81c8069 100644 --- a/docs/de/docs/tutorial/security/oauth2-jwt.md +++ b/docs/de/docs/tutorial/security/oauth2-jwt.md @@ -1,4 +1,4 @@ -# OAuth2 mit Password (und Hashing), Bearer mit JWT-Tokens +# OAuth2 mit Passwort (und Hashing), Bearer mit JWT-Tokens { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } Da wir nun über den gesamten Sicherheitsablauf verfügen, machen wir die Anwendung tatsächlich sicher, indem wir JWT-Tokens und sicheres Passwort-Hashing verwenden. @@ -6,7 +6,7 @@ Diesen Code können Sie tatsächlich in Ihrer Anwendung verwenden, die Passwort- Wir bauen auf dem vorherigen Kapitel auf. -## Über JWT +## Über JWT { #about-jwt } JWT bedeutet „JSON Web Tokens“. @@ -26,33 +26,31 @@ Nach einer Woche läuft der Token ab und der Benutzer wird nicht autorisiert und Wenn Sie mit JWT-Tokens spielen und sehen möchten, wie sie funktionieren, schauen Sie sich https://jwt.io an. -## `python-jose` installieren. +## `PyJWT` installieren { #install-pyjwt } -Wir müssen `python-jose` installieren, um die JWT-Tokens in Python zu generieren und zu verifizieren: +Wir müssen `PyJWT` installieren, um die JWT-Tokens in Python zu generieren und zu verifizieren. + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann `pyjwt` installieren:
```console -$ pip install "python-jose[cryptography]" +$ pip install pyjwt ---> 100% ```
-python-jose erfordert zusätzlich ein kryptografisches Backend. +/// info | Info -Hier verwenden wir das empfohlene: pyca/cryptography. +Wenn Sie planen, digitale Signaturalgorithmen wie RSA oder ECDSA zu verwenden, sollten Sie die Kryptografie-Abhängigkeit `pyjwt[crypto]` installieren. -/// tip | Tipp - -Dieses Tutorial verwendete zuvor PyJWT. - -Es wurde jedoch aktualisiert, stattdessen python-jose zu verwenden, da dieses alle Funktionen von PyJWT sowie einige Extras bietet, die Sie später möglicherweise benötigen, wenn Sie Integrationen mit anderen Tools erstellen. +Weitere Informationen finden Sie in der PyJWT-Installationsdokumentation. /// -## Passwort-Hashing +## Passwort-Hashing { #password-hashing } „Hashing“ bedeutet: Konvertieren eines Inhalts (in diesem Fall eines Passworts) in eine Folge von Bytes (ein schlichter String), die wie Kauderwelsch aussieht. @@ -60,13 +58,13 @@ Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren. -### Warum Passwort-Hashing verwenden? +### Warum Passwort-Hashing verwenden { #why-use-password-hashing } Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes. Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen System zu verwenden (da viele Benutzer überall das gleiche Passwort verwenden, wäre dies gefährlich). -## `passlib` installieren +## `passlib` installieren { #install-passlib } PassLib ist ein großartiges Python-Package, um Passwort-Hashes zu handhaben. @@ -74,7 +72,7 @@ Es unterstützt viele sichere Hashing-Algorithmen und Werkzeuge, um mit diesen z Der empfohlene Algorithmus ist „Bcrypt“. -Installieren Sie also PassLib mit Bcrypt: +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren, und installieren Sie dann PassLib mit Bcrypt:
@@ -96,7 +94,7 @@ Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ih /// -## Die Passwörter hashen und überprüfen +## Die Passwörter hashen und überprüfen { #hash-and-verify-the-passwords } Importieren Sie die benötigten Tools aus `passlib`. @@ -104,7 +102,7 @@ Erstellen Sie einen PassLib-„Kontext“. Der wird für das Hashen und Verifizi /// tip | Tipp -Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich deprecateter Alter, um etwa nur eine Verifizierung usw. zu ermöglichen. +Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich deprecateter Alter, um etwa nur eine Verifizierung usw. zu ermöglichen. Sie könnten ihn beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Bcrypt zu hashen. @@ -118,7 +116,7 @@ Und eine weitere, um zu überprüfen, ob ein empfangenes Passwort mit dem gespei Und noch eine, um einen Benutzer zu authentifizieren und zurückzugeben. -{* ../../docs_src/security/tutorial004_an_py310.py hl[7,48,55:56,59:60,69:75] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} /// note | Hinweis @@ -126,7 +124,7 @@ Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, /// -## JWT-Token verarbeiten +## JWT-Token verarbeiten { #handle-jwt-tokens } Importieren Sie die installierten Module. @@ -150,13 +148,13 @@ Erstellen Sie eine Variable `ALGORITHM` für den Algorithmus, der zum Signieren Erstellen Sie eine Variable für das Ablaufdatum des Tokens. -Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt für die Response verwendet wird. +Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt für die Response verwendet wird. Erstellen Sie eine Hilfsfunktion, um einen neuen Zugriffstoken zu generieren. -{* ../../docs_src/security/tutorial004_an_py310.py hl[6,12:14,28:30,78:86] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} -## Die Abhängigkeiten aktualisieren +## Die Abhängigkeiten aktualisieren { #update-the-dependencies } Aktualisieren Sie `get_current_user`, um den gleichen Token wie zuvor zu erhalten, dieses Mal jedoch unter Verwendung von JWT-Tokens. @@ -164,17 +162,17 @@ Dekodieren Sie den empfangenen Token, validieren Sie ihn und geben Sie den aktue Wenn der Token ungültig ist, geben Sie sofort einen HTTP-Fehler zurück. -{* ../../docs_src/security/tutorial004_an_py310.py hl[89:106] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} -## Die *Pfadoperation* `/token` aktualisieren +## Die *Pfadoperation* `/token` aktualisieren { #update-the-token-path-operation } Erstellen Sie ein `timedelta` mit der Ablaufzeit des Tokens. Erstellen Sie einen echten JWT-Zugriffstoken und geben Sie ihn zurück. -{* ../../docs_src/security/tutorial004_an_py310.py hl[117:132] *} +{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} -### Technische Details zum JWT-„Subjekt“ `sub` +### Technische Details zum JWT-„Subjekt“ `sub` { #technical-details-about-the-jwt-subject-sub } Die JWT-Spezifikation besagt, dass es einen Schlüssel `sub` mit dem Subjekt des Tokens gibt. @@ -196,7 +194,7 @@ Deshalb, um ID-Kollisionen zu vermeiden, könnten Sie beim Erstellen des JWT-Tok Der wesentliche Punkt ist, dass der `sub`-Schlüssel in der gesamten Anwendung eine eindeutige Kennung haben sollte, und er sollte ein String sein. -## Es testen +## Es testen { #check-it } Führen Sie den Server aus und gehen Sie zur Dokumentation: http://127.0.0.1:8000/docs. @@ -209,11 +207,11 @@ Melden Sie sich bei der Anwendung auf die gleiche Weise wie zuvor an. Verwenden Sie die Anmeldeinformationen: Benutzername: `johndoe` -Passwort: `secret`. +Passwort: `secret` -/// check +/// check | Testen -Beachten Sie, dass im Code nirgendwo das Klartext-Passwort "`secret`" steht, wir haben nur die gehashte Version. +Beachten Sie, dass im Code nirgendwo das Klartext-Passwort „`secret`“ steht, wir haben nur die gehashte Version. /// @@ -232,17 +230,17 @@ Rufen Sie den Endpunkt `/users/me/` auf, Sie erhalten die Response: -Wenn Sie die Developer Tools öffnen, können Sie sehen, dass die gesendeten Daten nur den Token enthalten. Das Passwort wird nur bei der ersten Anfrage gesendet, um den Benutzer zu authentisieren und diesen Zugriffstoken zu erhalten, aber nicht mehr danach: +Wenn Sie die Developer Tools öffnen, können Sie sehen, dass die gesendeten Daten nur den Token enthalten. Das Passwort wird nur beim ersten Request gesendet, um den Benutzer zu authentisieren und diesen Zugriffstoken zu erhalten, aber nicht mehr danach: /// note | Hinweis -Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer` beginnt. +Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer ` beginnt. /// -## Fortgeschrittene Verwendung mit `scopes` +## Fortgeschrittene Verwendung mit `scopes` { #advanced-usage-with-scopes } OAuth2 hat ein Konzept von „Scopes“. @@ -252,7 +250,7 @@ Anschließend können Sie diesen Token einem Benutzer direkt oder einem Dritten Wie Sie sie verwenden und wie sie in **FastAPI** integriert sind, erfahren Sie später im **Handbuch für fortgeschrittene Benutzer**. -## Zusammenfassung +## Zusammenfassung { #recap } Mit dem, was Sie bis hier gesehen haben, können Sie eine sichere **FastAPI**-Anwendung mithilfe von Standards wie OAuth2 und JWT einrichten. @@ -266,7 +264,7 @@ Viele Packages, die es stark vereinfachen, müssen viele Kompromisse beim Datenm Es gibt Ihnen die volle Flexibilität, diejenigen auszuwählen, die am besten zu Ihrem Projekt passen. -Und Sie können viele gut gepflegte und weit verbreitete Packages wie `passlib` und `python-jose` direkt verwenden, da **FastAPI** keine komplexen Mechanismen zur Integration externer Pakete erfordert. +Und Sie können viele gut gepflegte und weit verbreitete Packages wie `passlib` und `PyJWT` direkt verwenden, da **FastAPI** keine komplexen Mechanismen zur Integration externer Pakete erfordert. Aber es bietet Ihnen die Werkzeuge, um den Prozess so weit wie möglich zu vereinfachen, ohne Kompromisse bei Flexibilität, Robustheit oder Sicherheit einzugehen. diff --git a/docs/de/docs/tutorial/security/simple-oauth2.md b/docs/de/docs/tutorial/security/simple-oauth2.md index c0c93cd26..28cb83ba9 100644 --- a/docs/de/docs/tutorial/security/simple-oauth2.md +++ b/docs/de/docs/tutorial/security/simple-oauth2.md @@ -1,8 +1,8 @@ -# Einfaches OAuth2 mit Password und Bearer +# Einfaches OAuth2 mit Password und Bearer { #simple-oauth2-with-password-and-bearer } Lassen Sie uns nun auf dem vorherigen Kapitel aufbauen und die fehlenden Teile hinzufügen, um einen vollständigen Sicherheits-Flow zu erhalten. -## `username` und `password` entgegennehmen +## `username` und `password` entgegennehmen { #get-the-username-and-password } Wir werden **FastAPIs** Sicherheits-Werkzeuge verwenden, um den `username` und das `password` entgegenzunehmen. @@ -18,7 +18,7 @@ Aber für die Login-*Pfadoperation* müssen wir diese Namen verwenden, um mit de Die Spezifikation besagt auch, dass `username` und `password` als Formulardaten gesendet werden müssen (hier also kein JSON). -### `scope` +### `scope` { #scope } Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld "`scope`" („Geltungsbereich“) senden kann. @@ -32,7 +32,7 @@ Diese werden normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu * `instagram_basic` wird von Facebook / Instagram verwendet. * `https://www.googleapis.com/auth/drive` wird von Google verwendet. -/// info +/// info | Info In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert. @@ -44,11 +44,11 @@ Für OAuth2 sind es einfach nur Strings. /// -## Code, um `username` und `password` entgegenzunehmen. +## Code, um `username` und `password` entgegenzunehmen { #code-to-get-the-username-and-password } Lassen Sie uns nun die von **FastAPI** bereitgestellten Werkzeuge verwenden, um das zu erledigen. -### `OAuth2PasswordRequestForm` +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als Abhängigkeit mit `Depends` in der *Pfadoperation* für `/token`: @@ -59,7 +59,7 @@ Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als A * Dem `username`. * Dem `password`. * Einem optionalen `scope`-Feld als langem String, bestehend aus durch Leerzeichen getrennten Strings. -* Einem optionalen `grant_type` („Art der Anmeldung“). +* Einem optionalen `grant_type`. /// tip | Tipp @@ -72,7 +72,7 @@ Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` a * Eine optionale `client_id` (benötigen wir für unser Beispiel nicht). * Ein optionales `client_secret` (benötigen wir für unser Beispiel nicht). -/// info +/// info | Info `OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`. @@ -84,7 +84,7 @@ Da es sich jedoch um einen häufigen Anwendungsfall handelt, wird er zur Vereinf /// -### Die Formulardaten verwenden +### Die Formulardaten verwenden { #use-the-form-data } /// tip | Tipp @@ -102,7 +102,7 @@ Für den Fehler verwenden wir die Exception `HTTPException`: {* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} -### Das Passwort überprüfen +### Das Passwort überprüfen { #check-the-password } Zu diesem Zeitpunkt liegen uns die Benutzerdaten aus unserer Datenbank vor, das Passwort haben wir jedoch noch nicht überprüft. @@ -112,7 +112,7 @@ Sie sollten niemals Klartext-Passwörter speichern, daher verwenden wir ein (gef Wenn die Passwörter nicht übereinstimmen, geben wir denselben Fehler zurück. -#### Passwort-Hashing +#### Passwort-Hashing { #password-hashing } „Hashing“ bedeutet: Konvertieren eines Inhalts (in diesem Fall eines Passworts) in eine Folge von Bytes (ein schlichter String), die wie Kauderwelsch aussieht. @@ -120,7 +120,7 @@ Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren. -##### Warum Passwort-Hashing verwenden? +##### Warum Passwort-Hashing verwenden? { #why-use-password-hashing } Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes. @@ -128,7 +128,7 @@ Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen Sy {* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} -#### Über `**user_dict` +#### Über `**user_dict` { #about-user-dict } `UserInDB(**user_dict)` bedeutet: @@ -144,15 +144,15 @@ UserInDB( ) ``` -/// info +/// info | Info -Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#uber-user_indict){.internal-link target=_blank}. +Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#about-user-in-dict){.internal-link target=_blank}. /// -## Den Token zurückgeben +## Den Token zurückgeben { #return-the-token } -Die Response des `token`-Endpunkts muss ein JSON-Objekt sein. +Die Response des `token`-Endpunkts muss ein JSON-Objekt sein. Es sollte einen `token_type` haben. Da wir in unserem Fall „Bearer“-Token verwenden, sollte der Token-Typ "`bearer`" sein. @@ -182,7 +182,7 @@ Den Rest erledigt **FastAPI** für Sie. /// -## Die Abhängigkeiten aktualisieren +## Die Abhängigkeiten aktualisieren { #update-the-dependencies } Jetzt werden wir unsere Abhängigkeiten aktualisieren. @@ -196,7 +196,7 @@ In unserem Endpunkt erhalten wir also nur dann einen Benutzer, wenn der Benutzer {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info +/// info | Info Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation. @@ -214,11 +214,11 @@ Das ist der Vorteil von Standards ... /// -## Es in Aktion sehen +## Es in Aktion sehen { #see-it-in-action } Öffnen Sie die interaktive Dokumentation: http://127.0.0.1:8000/docs. -### Authentifizieren +### Authentifizieren { #authenticate } Klicken Sie auf den Button „Authorize“. @@ -234,7 +234,7 @@ Nach der Authentifizierung im System sehen Sie Folgendes: -### Die eigenen Benutzerdaten ansehen +### Die eigenen Benutzerdaten ansehen { #get-your-own-user-data } Verwenden Sie nun die Operation `GET` mit dem Pfad `/users/me`. @@ -260,7 +260,7 @@ Wenn Sie auf das Schlosssymbol klicken und sich abmelden und dann den gleichen V } ``` -### Inaktiver Benutzer +### Inaktiver Benutzer { #inactive-user } Versuchen Sie es nun mit einem inaktiven Benutzer und authentisieren Sie sich mit: @@ -278,7 +278,7 @@ Sie erhalten die Fehlermeldung „Inactive user“: } ``` -## Zusammenfassung +## Zusammenfassung { #recap } Sie verfügen jetzt über die Tools, um ein vollständiges Sicherheitssystem basierend auf `username` und `password` für Ihre API zu implementieren. diff --git a/docs/de/docs/tutorial/sql-databases.md b/docs/de/docs/tutorial/sql-databases.md new file mode 100644 index 000000000..cf9731aee --- /dev/null +++ b/docs/de/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# SQL (Relationale) Datenbanken { #sql-relational-databases } + +**FastAPI** erfordert nicht, dass Sie eine SQL (relationale) Datenbank verwenden. Sondern Sie können **jede beliebige Datenbank** verwenden, die Sie möchten. + +Hier werden wir ein Beispiel mit SQLModel sehen. + +**SQLModel** basiert auf SQLAlchemy und Pydantic. Es wurde vom selben Autor wie **FastAPI** entwickelt, um die perfekte Ergänzung für FastAPI-Anwendungen zu sein, die **SQL-Datenbanken** verwenden müssen. + +/// tip | Tipp + +Sie könnten jede andere SQL- oder NoSQL-Datenbankbibliothek verwenden, die Sie möchten (in einigen Fällen als „ORMs“ bezeichnet), FastAPI zwingt Sie nicht, irgendetwas zu verwenden. 😎 + +/// + +Da SQLModel auf SQLAlchemy basiert, können Sie problemlos **jede von SQLAlchemy unterstützte Datenbank** verwenden (was auch bedeutet, dass sie von SQLModel unterstützt werden), wie: + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server, usw. + +In diesem Beispiel verwenden wir **SQLite**, da es eine einzelne Datei verwendet und Python integrierte Unterstützung bietet. Sie können also dieses Beispiel kopieren und direkt ausführen. + +Später, für Ihre Produktionsanwendung, möchten Sie möglicherweise einen Datenbankserver wie **PostgreSQL** verwenden. + +/// tip | Tipp + +Es gibt einen offiziellen Projektgenerator mit **FastAPI** und **PostgreSQL**, einschließlich eines Frontends und weiterer Tools: https://github.com/fastapi/full-stack-fastapi-template + +/// + +Dies ist ein sehr einfaches und kurzes Tutorial. Wenn Sie mehr über Datenbanken im Allgemeinen, über SQL oder fortgeschrittenere Funktionen erfahren möchten, besuchen Sie die SQLModel-Dokumentation. + +## `SQLModel` installieren { #install-sqlmodel } + +Stellen Sie zunächst sicher, dass Sie Ihre [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren und dann `sqlmodel` installieren: + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## Die App mit einem einzelnen Modell erstellen { #create-the-app-with-a-single-model } + +Wir erstellen zuerst die einfachste erste Version der App mit einem einzigen **SQLModel**-Modell. + +Später werden wir sie verbessern, indem wir unter der Haube **mehrere Modelle** verwenden, um Sicherheit und Vielseitigkeit zu erhöhen. 🤓 + +### Modelle erstellen { #create-models } + +Importieren Sie `SQLModel` und erstellen Sie ein Datenbankmodell: + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +Die `Hero`-Klasse ist einem Pydantic-Modell sehr ähnlich (faktisch ist sie darunter tatsächlich *ein Pydantic-Modell*). + +Es gibt ein paar Unterschiede: + +* `table=True` sagt SQLModel, dass dies ein *Tabellenmodell* ist, es soll eine **Tabelle** in der SQL-Datenbank darstellen, es ist nicht nur ein *Datenmodell* (wie es jede andere reguläre Pydantic-Klasse wäre). + +* `Field(primary_key=True)` sagt SQLModel, dass die `id` der **Primärschlüssel** in der SQL-Datenbank ist (Sie können mehr über SQL-Primärschlüssel in der SQLModel-Dokumentation erfahren). + + Durch das Festlegen des Typs als `int | None` wird SQLModel wissen, dass diese Spalte ein `INTEGER` in der SQL-Datenbank sein sollte und dass sie `NULLABLE` sein sollte. + +* `Field(index=True)` sagt SQLModel, dass es einen **SQL-Index** für diese Spalte erstellen soll, was schnelleres Suchen in der Datenbank ermöglicht, wenn Daten mittels dieser Spalte gefiltert werden. + + SQLModel wird verstehen, dass etwas, das als `str` deklariert ist, eine SQL-Spalte des Typs `TEXT` (oder `VARCHAR`, abhängig von der Datenbank) sein wird. + +### Eine Engine erstellen { #create-an-engine } + +Eine SQLModel-`engine` (darunter ist es tatsächlich eine SQLAlchemy-`engine`) ist das, was die **Verbindungen** zur Datenbank hält. + +Sie hätten **ein einziges `engine`-Objekt** für Ihren gesamten Code, um sich mit derselben Datenbank zu verbinden. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +Die Verwendung von `check_same_thread=False` erlaubt FastAPI, dieselbe SQLite-Datenbank in verschiedenen Threads zu verwenden. Dies ist notwendig, da **ein einzelner Request** **mehr als einen Thread** verwenden könnte (zum Beispiel in Abhängigkeiten). + +Keine Sorge, so wie der Code strukturiert ist, werden wir später sicherstellen, dass wir **eine einzige SQLModel-*Session* pro Request** verwenden, das ist eigentlich das, was `check_same_thread` erreichen möchte. + +### Die Tabellen erstellen { #create-the-tables } + +Dann fügen wir eine Funktion hinzu, die `SQLModel.metadata.create_all(engine)` verwendet, um die **Tabellen für alle *Tabellenmodelle* zu erstellen**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} + +### Eine Session-Abhängigkeit erstellen { #create-a-session-dependency } + +Eine **`Session`** speichert die **Objekte im Speicher** und verfolgt alle Änderungen, die an den Daten vorgenommen werden müssen, dann **verwendet sie die `engine`**, um mit der Datenbank zu kommunizieren. + +Wir werden eine FastAPI **Abhängigkeit** mit `yield` erstellen, die eine neue `Session` für jeden Request bereitstellt. Das ist es, was sicherstellt, dass wir eine einzige Session pro Request verwenden. 🤓 + +Dann erstellen wir eine `Annotated`-Abhängigkeit `SessionDep`, um den Rest des Codes zu vereinfachen, der diese Abhängigkeit nutzen wird. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### Die Datenbanktabellen beim Start erstellen { #create-database-tables-on-startup } + +Wir werden die Datenbanktabellen erstellen, wenn die Anwendung startet. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +Hier erstellen wir die Tabellen bei einem Anwendungsstart-Event. + +Für die Produktion würden Sie wahrscheinlich ein Migrationsskript verwenden, das ausgeführt wird, bevor Sie Ihre App starten. 🤓 + +/// tip | Tipp + +SQLModel wird Migrationstools haben, die Alembic wrappen, aber im Moment können Sie Alembic direkt verwenden. + +/// + +### Einen Helden erstellen { #create-a-hero } + +Da jedes SQLModel-Modell auch ein Pydantic-Modell ist, können Sie es in denselben **Typannotationen** verwenden, die Sie für Pydantic-Modelle verwenden könnten. + +Wenn Sie beispielsweise einen Parameter vom Typ `Hero` deklarieren, wird er aus dem **JSON-Body** gelesen. + +Auf die gleiche Weise können Sie es als **Rückgabetyp** der Funktion deklarieren, und dann wird die Form der Daten in der automatischen API-Dokumentation angezeigt. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +Hier verwenden wir die `SessionDep`-Abhängigkeit (eine `Session`), um den neuen `Hero` zur `Session`-Instanz hinzuzufügen, die Änderungen an der Datenbank zu committen, die Daten im `hero` zu aktualisieren und ihn anschließend zurückzugeben. + +### Helden lesen { #read-heroes } + +Wir können `Hero`s aus der Datenbank mit einem `select()` **lesen**. Wir können ein `limit` und `offset` hinzufügen, um die Ergebnisse zu paginieren. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### Einen Helden lesen { #read-one-hero } + +Wir können einen einzelnen `Hero` **lesen**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### Einen Helden löschen { #delete-a-hero } + +Wir können auch einen `Hero` **löschen**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### Die App ausführen { #run-the-app } + +Sie können die App ausführen: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Gehen Sie dann zur `/docs`-UI, Sie werden sehen, dass **FastAPI** diese **Modelle** verwendet, um die API zu **dokumentieren**, und es wird sie auch verwenden, um die Daten zu **serialisieren** und zu **validieren**. + +
+ +
+ +## Die App mit mehreren Modellen aktualisieren { #update-the-app-with-multiple-models } + +Jetzt lassen Sie uns diese App ein wenig **refaktorisieren**, um die **Sicherheit** und **Vielseitigkeit** zu erhöhen. + +Wenn Sie die vorherige App überprüfen, können Sie in der UI sehen, dass sie bis jetzt dem Client erlaubt, die `id` des zu erstellenden `Hero` zu bestimmen. 😱 + +Das sollten wir nicht zulassen, sie könnten eine `id` überschreiben, die wir bereits in der DB zugewiesen haben. Die Entscheidung über die `id` sollte vom **Backend** oder der **Datenbank** getroffen werden, **nicht vom Client**. + +Außerdem erstellen wir einen `secret_name` für den Helden, aber bisher geben wir ihn überall zurück, das ist nicht sehr **geheim** ... 😅 + +Wir werden diese Dinge beheben, indem wir ein paar **zusätzliche Modelle** hinzufügen. Hier wird SQLModel glänzen. ✨ + +### Mehrere Modelle erstellen { #create-multiple-models } + +In **SQLModel** ist jede Modellklasse, die `table=True` hat, ein **Tabellenmodell**. + +Und jede Modellklasse, die `table=True` nicht hat, ist ein **Datenmodell**, diese sind tatsächlich nur Pydantic-Modelle (mit ein paar kleinen zusätzlichen Funktionen). 🤓 + +Mit SQLModel können wir **Vererbung** verwenden, um **doppelte Felder** in allen Fällen zu **vermeiden**. + +#### `HeroBase` – die Basisklasse { #herobase-the-base-class } + +Fangen wir mit einem `HeroBase`-Modell an, das alle **Felder hat, die von allen Modellen geteilt werden**: + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` – das *Tabellenmodell* { #hero-the-table-model } + +Dann erstellen wir `Hero`, das tatsächliche *Tabellenmodell*, mit den **zusätzlichen Feldern**, die nicht immer in den anderen Modellen enthalten sind: + +* `id` +* `secret_name` + +Da `Hero` von `HeroBase` erbt, hat es **auch** die **Felder**, die in `HeroBase` deklariert sind, also sind alle Felder von `Hero`: + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` – das öffentliche *Datenmodell* { #heropublic-the-public-data-model } + +Als nächstes erstellen wir ein `HeroPublic`-Modell, das an die API-Clients **zurückgegeben** wird. + +Es hat dieselben Felder wie `HeroBase`, sodass es `secret_name` nicht enthält. + +Endlich ist die Identität unserer Helden geschützt! 🥷 + +Es deklariert auch `id: int` erneut. Indem wir dies tun, machen wir einen **Vertrag** mit den API-Clients, damit sie immer damit rechnen können, dass die `id` vorhanden ist und ein `int` ist (sie wird niemals `None` sein). + +/// tip | Tipp + +Es ist sehr nützlich für die API-Clients, wenn das Rückgabemodell sicherstellt, dass ein Wert immer verfügbar und immer `int` (nicht `None`) ist, sie können viel einfacheren Code schreiben, wenn sie diese Sicherheit haben. + +Auch **automatisch generierte Clients** werden einfachere Schnittstellen haben, damit die Entwickler, die mit Ihrer API kommunizieren, viel mehr Freude an der Arbeit mit Ihrer API haben können. 😎 + +/// + +Alle Felder in `HeroPublic` sind dieselben wie in `HeroBase`, mit `id`, das als `int` (nicht `None`) deklariert ist: + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` – das *Datenmodell* zum Erstellen eines Helden { #herocreate-the-data-model-to-create-a-hero } + +Nun erstellen wir ein `HeroCreate`-Modell, das die Daten der Clients **validiert**. + +Es hat dieselben Felder wie `HeroBase`, und es hat auch `secret_name`. + +Wenn die Clients **einen neuen Helden erstellen**, senden sie jetzt den `secret_name`, er wird in der Datenbank gespeichert, aber diese geheimen Namen werden den API-Clients nicht zurückgegeben. + +/// tip | Tipp + +So würden Sie **Passwörter** handhaben. Empfangen Sie sie, aber geben Sie sie nicht in der API zurück. + +Sie würden auch die Werte der Passwörter **hashen**, bevor Sie sie speichern, und sie **niemals im Klartext** speichern. + +/// + +Die Felder von `HeroCreate` sind: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` – das *Datenmodell* zum Aktualisieren eines Helden { #heroupdate-the-data-model-to-update-a-hero } + +In der vorherigen Version der App hatten wir keine Möglichkeit, einen Helden **zu aktualisieren**, aber jetzt mit **mehreren Modellen** können wir es. 🎉 + +Das `HeroUpdate`-*Datenmodell* ist etwas Besonderes, es hat **die selben Felder**, die benötigt werden, um einen neuen Helden zu erstellen, aber alle Felder sind **optional** (sie haben alle einen Defaultwert). Auf diese Weise, wenn Sie einen Helden aktualisieren, können Sie nur die Felder senden, die Sie aktualisieren möchten. + +Da sich tatsächlich **alle Felder ändern** (der Typ enthält jetzt `None` und sie haben jetzt einen Standardwert von `None`), müssen wir sie erneut **deklarieren**. + +Wir müssen wirklich nicht von `HeroBase` erben, weil wir alle Felder neu deklarieren. Ich lasse es aus Konsistenzgründen erben, aber das ist nicht notwendig. Es ist mehr eine Frage des persönlichen Geschmacks. 🤷 + +Die Felder von `HeroUpdate` sind: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### Mit `HeroCreate` erstellen und ein `HeroPublic` zurückgeben { #create-with-herocreate-and-return-a-heropublic } + +Nun, da wir **mehrere Modelle** haben, können wir die Teile der App aktualisieren, die sie verwenden. + +Wir empfangen im Request ein `HeroCreate`-*Datenmodell* und daraus erstellen wir ein `Hero`-*Tabellenmodell*. + +Dieses neue *Tabellenmodell* `Hero` wird die vom Client gesendeten Felder haben und zusätzlich eine `id`, die von der Datenbank generiert wird. + +Dann geben wir das gleiche *Tabellenmodell* `Hero` von der Funktion zurück. Aber da wir das `response_model` mit dem `HeroPublic`-*Datenmodell* deklarieren, wird **FastAPI** `HeroPublic` verwenden, um die Daten zu validieren und zu serialisieren. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} + +/// tip | Tipp + +Jetzt verwenden wir `response_model=HeroPublic` anstelle der **Rückgabetyp-Annotation** `-> HeroPublic`, weil der Wert, den wir zurückgeben, tatsächlich *kein* `HeroPublic` ist. + +Wenn wir `-> HeroPublic` deklariert hätten, würden Ihr Editor und Linter (zu Recht) reklamieren, dass Sie ein `Hero` anstelle eines `HeroPublic` zurückgeben. + +Durch die Deklaration in `response_model` sagen wir **FastAPI**, dass es seine Aufgabe erledigen soll, ohne die Typannotationen und die Hilfe von Ihrem Editor und anderen Tools zu beeinträchtigen. + +/// + +### Helden mit `HeroPublic` lesen { #read-heroes-with-heropublic } + +Wir können dasselbe wie zuvor tun, um `Hero`s zu **lesen**, und erneut verwenden wir `response_model=list[HeroPublic]`, um sicherzustellen, dass die Daten ordnungsgemäß validiert und serialisiert werden. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} + +### Einen einzelnen Helden mit `HeroPublic` lesen { #read-one-hero-with-heropublic } + +Wir können einen einzelnen Helden **lesen**: + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### Einen Helden mit `HeroUpdate` aktualisieren { #update-a-hero-with-heroupdate } + +Wir können einen Helden **aktualisieren**. Dafür verwenden wir eine HTTP-`PATCH`-Operation. + +Und im Code erhalten wir ein `dict` mit allen Daten, die vom Client gesendet wurden, **nur die Daten, die vom Client gesendet wurden**, unter Ausschluss von Werten, die dort nur als Defaultwerte vorhanden wären. Um dies zu tun, verwenden wir `exclude_unset=True`. Das ist der Haupttrick. 🪄 + +Dann verwenden wir `hero_db.sqlmodel_update(hero_data)`, um die `hero_db` mit den Daten aus `hero_data` zu aktualisieren. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### Einen Helden wieder löschen { #delete-a-hero-again } + +Das **Löschen** eines Helden bleibt ziemlich gleich. + +Wir werden dieses Mal nicht dem Wunsch nachgeben, alles zu refaktorisieren. 😅 + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### Die App erneut ausführen { #run-the-app-again } + +Sie können die App erneut ausführen: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Wenn Sie zur `/docs`-API-UI gehen, werden Sie sehen, dass sie jetzt aktualisiert ist und nicht mehr erwarten wird, die `id` vom Client beim Erstellen eines Helden zu erhalten, usw. + +
+ +
+ +## Zusammenfassung { #recap } + +Sie können **SQLModel** verwenden, um mit einer SQL-Datenbank zu interagieren und den Code mit *Datenmodellen* und *Tabellenmodellen* zu vereinfachen. + +Sie können viel mehr in der **SQLModel**-Dokumentation lernen, es gibt ein längeres Mini-Tutorial zur Verwendung von SQLModel mit **FastAPI**. 🚀 diff --git a/docs/de/docs/tutorial/static-files.md b/docs/de/docs/tutorial/static-files.md index 50e86d68e..5a6cfcb2b 100644 --- a/docs/de/docs/tutorial/static-files.md +++ b/docs/de/docs/tutorial/static-files.md @@ -1,8 +1,8 @@ -# Statische Dateien +# Statische Dateien { #static-files } Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisch bereitstellen. -## `StaticFiles` verwenden +## `StaticFiles` verwenden { #use-staticfiles } * Importieren Sie `StaticFiles`. * „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad. @@ -17,7 +17,7 @@ Sie könnten auch `from starlette.staticfiles import StaticFiles` verwenden. /// -### Was ist „Mounten“? +### Was ist „Mounten“ { #what-is-mounting } „Mounten“ bedeutet das Hinzufügen einer vollständigen „unabhängigen“ Anwendung an einem bestimmten Pfad, die sich dann um die Handhabung aller Unterpfade kümmert. @@ -25,7 +25,7 @@ Dies unterscheidet sich von der Verwendung eines `APIRouter`, da eine gemountete Weitere Informationen hierzu finden Sie im [Handbuch für fortgeschrittene Benutzer](../advanced/index.md){.internal-link target=_blank}. -## Einzelheiten +## Einzelheiten { #details } Das erste `"/static"` bezieht sich auf den Unterpfad, auf dem diese „Unteranwendung“ „gemountet“ wird. Daher wird jeder Pfad, der mit `"/static"` beginnt, von ihr verarbeitet. @@ -33,8 +33,8 @@ Das `directory="static"` bezieht sich auf den Namen des Verzeichnisses, das Ihre Das `name="static"` gibt dieser Unteranwendung einen Namen, der intern von **FastAPI** verwendet werden kann. -Alle diese Parameter können anders als "`static`" lauten, passen Sie sie an die Bedürfnisse und spezifischen Details Ihrer eigenen Anwendung an. +Alle diese Parameter können anders als „`static`“ lauten, passen Sie sie an die Bedürfnisse und spezifischen Details Ihrer eigenen Anwendung an. -## Weitere Informationen +## Weitere Informationen { #more-info } Weitere Details und Optionen finden Sie in der Dokumentation von Starlette zu statischen Dateien. diff --git a/docs/de/docs/tutorial/testing.md b/docs/de/docs/tutorial/testing.md index e7c1dda95..75ee9fade 100644 --- a/docs/de/docs/tutorial/testing.md +++ b/docs/de/docs/tutorial/testing.md @@ -1,18 +1,22 @@ -# Testen +# Testen { #testing } Dank Starlette ist das Testen von **FastAPI**-Anwendungen einfach und macht Spaß. -Es basiert auf HTTPX, welches wiederum auf der Grundlage von requests konzipiert wurde, es ist also sehr vertraut und intuitiv. +Es basiert auf HTTPX, welches wiederum auf der Grundlage von Requests konzipiert wurde, es ist also sehr vertraut und intuitiv. Damit können Sie pytest direkt mit **FastAPI** verwenden. -## Verwendung von `TestClient` +## `TestClient` verwenden { #using-testclient } -/// info +/// info | Info Um `TestClient` zu verwenden, installieren Sie zunächst `httpx`. -Z. B. `pip install httpx`. +Erstellen Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}, aktivieren Sie sie und installieren Sie es dann, z. B.: + +```console +$ pip install httpx +``` /// @@ -48,17 +52,17 @@ Sie könnten auch `from starlette.testclient import TestClient` verwenden. /// tip | Tipp -Wenn Sie in Ihren Tests neben dem Senden von Anfragen an Ihre FastAPI-Anwendung auch `async`-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die [Async-Tests](../advanced/async-tests.md){.internal-link target=_blank} im Handbuch für fortgeschrittene Benutzer. +Wenn Sie in Ihren Tests neben dem Senden von Requests an Ihre FastAPI-Anwendung auch `async`-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die [Async-Tests](../advanced/async-tests.md){.internal-link target=_blank} im Handbuch für fortgeschrittene Benutzer. /// -## Tests separieren +## Tests separieren { #separating-tests } In einer echten Anwendung würden Sie Ihre Tests wahrscheinlich in einer anderen Datei haben. Und Ihre **FastAPI**-Anwendung könnte auch aus mehreren Dateien/Modulen, usw. bestehen. -### **FastAPI** Anwendungsdatei +### **FastAPI** Anwendungsdatei { #fastapi-app-file } Nehmen wir an, Sie haben eine Dateistruktur wie in [Größere Anwendungen](bigger-applications.md){.internal-link target=_blank} beschrieben: @@ -75,7 +79,7 @@ In der Datei `main.py` haben Sie Ihre **FastAPI**-Anwendung: {* ../../docs_src/app_testing/main.py *} -### Testdatei +### Testdatei { #testing-file } Dann könnten Sie eine Datei `test_main.py` mit Ihren Tests haben. Sie könnte sich im selben Python-Package befinden (dasselbe Verzeichnis mit einer `__init__.py`-Datei): @@ -94,11 +98,11 @@ Da sich diese Datei im selben Package befindet, können Sie relative Importe ver ... und haben den Code für die Tests wie zuvor. -## Testen: erweitertes Beispiel +## Testen: erweitertes Beispiel { #testing-extended-example } Nun erweitern wir dieses Beispiel und fügen weitere Details hinzu, um zu sehen, wie verschiedene Teile getestet werden. -### Erweiterte **FastAPI**-Anwendungsdatei +### Erweiterte **FastAPI**-Anwendungsdatei { #extended-fastapi-app-file } Fahren wir mit der gleichen Dateistruktur wie zuvor fort: @@ -170,7 +174,7 @@ Bevorzugen Sie die `Annotated`-Version, falls möglich. //// -### Erweiterte Testdatei +### Erweiterte Testdatei { #extended-testing-file } Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisieren: @@ -184,14 +188,14 @@ Dann machen Sie in Ihren Tests einfach das gleiche. Z. B.: * Um einen *Pfad*- oder *Query*-Parameter zu übergeben, fügen Sie ihn der URL selbst hinzu. -* Um einen JSON-Body zu übergeben, übergeben Sie ein Python-Objekt (z. B. ein `dict`) an den Parameter `json`. +* Um einen JSON-Body zu übergeben, übergeben Sie ein Python-Objekt (z. B. ein `dict`) an den Parameter `json`. * Wenn Sie *Formulardaten* anstelle von JSON senden müssen, verwenden Sie stattdessen den `data`-Parameter. * Um *Header* zu übergeben, verwenden Sie ein `dict` im `headers`-Parameter. * Für *Cookies* ein `dict` im `cookies`-Parameter. Weitere Informationen zum Übergeben von Daten an das Backend (mithilfe von `httpx` oder dem `TestClient`) finden Sie in der HTTPX-Dokumentation. -/// info +/// info | Info Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle. @@ -199,9 +203,11 @@ Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des T /// -## Tests ausführen +## Tests ausführen { #run-it } -Danach müssen Sie nur noch `pytest` installieren: +Danach müssen Sie nur noch `pytest` installieren. + +Erstellen Sie eine [virtuelle Umgebung](../virtual-environments.md){.internal-link target=_blank}, aktivieren Sie sie und installieren Sie es dann, z. B.:
diff --git a/docs/de/docs/virtual-environments.md b/docs/de/docs/virtual-environments.md new file mode 100644 index 000000000..497f1b44d --- /dev/null +++ b/docs/de/docs/virtual-environments.md @@ -0,0 +1,842 @@ +# Virtuelle Umgebungen { #virtual-environments } + +Wenn Sie an Python-Projekten arbeiten, sollten Sie wahrscheinlich eine **virtuelle Umgebung** (oder einen ähnlichen Mechanismus) verwenden, um die Packages, die Sie für jedes Projekt installieren, zu isolieren. + +/// info | Info + +Wenn Sie bereits über virtuelle Umgebungen Bescheid wissen, wie man sie erstellt und verwendet, möchten Sie diesen Abschnitt vielleicht überspringen. 🤓 + +/// + +/// tip | Tipp + +Eine **virtuelle Umgebung** unterscheidet sich von einer **Umgebungsvariable**. + +Eine **Umgebungsvariable** ist eine Variable im System, die von Programmen verwendet werden kann. + +Eine **virtuelle Umgebung** ist ein Verzeichnis mit einigen Dateien darin. + +/// + +/// info | Info + +Diese Seite wird Ihnen beibringen, wie Sie **virtuelle Umgebungen** verwenden und wie sie funktionieren. + +Wenn Sie bereit sind, ein **Tool zu verwenden, das alles für Sie verwaltet** (einschließlich der Installation von Python), probieren Sie uv. + +/// + +## Ein Projekt erstellen { #create-a-project } + +Erstellen Sie zuerst ein Verzeichnis für Ihr Projekt. + +Was ich normalerweise mache, ist, dass ich ein Verzeichnis namens `code` in meinem Home/Benutzerverzeichnis erstelle. + +Und darin erstelle ich ein Verzeichnis pro Projekt. + +
+ +```console +// Gehe zum Home-Verzeichnis +$ cd +// Erstelle ein Verzeichnis für alle Ihre Code-Projekte +$ mkdir code +// Gehe in dieses Code-Verzeichnis +$ cd code +// Erstelle ein Verzeichnis für dieses Projekt +$ mkdir awesome-project +// Gehe in dieses Projektverzeichnis +$ cd awesome-project +``` + +
+ +## Eine virtuelle Umgebung erstellen { #create-a-virtual-environment } + +Wenn Sie zum **ersten Mal** an einem Python-Projekt arbeiten, erstellen Sie eine virtuelle Umgebung **innerhalb Ihres Projekts**. + +/// tip | Tipp + +Sie müssen dies nur **einmal pro Projekt** tun, nicht jedes Mal, wenn Sie daran arbeiten. + +/// + +//// tab | `venv` + +Um eine virtuelle Umgebung zu erstellen, können Sie das `venv`-Modul verwenden, das mit Python geliefert wird. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | Was dieser Befehl bedeutet + +* `python`: das Programm namens `python` verwenden +* `-m`: ein Modul als Skript aufrufen, wir geben als nächstes an, welches Modul +* `venv`: das Modul namens `venv` verwenden, das normalerweise mit Python installiert wird +* `.venv`: die virtuelle Umgebung im neuen Verzeichnis `.venv` erstellen + +/// + +//// + +//// tab | `uv` + +Wenn Sie `uv` installiert haben, können Sie es verwenden, um eine virtuelle Umgebung zu erstellen. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | Tipp + +Standardmäßig erstellt `uv` eine virtuelle Umgebung in einem Verzeichnis namens `.venv`. + +Aber Sie könnten es anpassen, indem Sie ein zusätzliches Argument mit dem Verzeichnisnamen übergeben. + +/// + +//// + +Dieser Befehl erstellt eine neue virtuelle Umgebung in einem Verzeichnis namens `.venv`. + +/// details | `.venv` oder ein anderer Name + +Sie könnten die virtuelle Umgebung in einem anderen Verzeichnis erstellen, aber es ist eine Konvention, sie `.venv` zu nennen. + +/// + +## Die virtuelle Umgebung aktivieren { #activate-the-virtual-environment } + +Aktivieren Sie die neue virtuelle Umgebung, damit jeder Python-Befehl, den Sie ausführen oder jedes Paket, das Sie installieren, diese Umgebung verwendet. + +/// tip | Tipp + +Tun Sie dies **jedes Mal**, wenn Sie eine **neue Terminalsitzung** starten, um an dem Projekt zu arbeiten. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Oder wenn Sie Bash für Windows verwenden (z. B. Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | Tipp + +Jedes Mal, wenn Sie ein **neues Paket** in dieser Umgebung installieren, aktivieren Sie die Umgebung erneut. + +So stellen Sie sicher, dass, wenn Sie ein **Terminalprogramm (CLI)** verwenden, das durch dieses Paket installiert wurde, Sie das aus Ihrer virtuellen Umgebung verwenden und nicht eines, das global installiert ist, wahrscheinlich mit einer anderen Version als der, die Sie benötigen. + +/// + +## Testen, ob die virtuelle Umgebung aktiv ist { #check-the-virtual-environment-is-active } + +Testen Sie, dass die virtuelle Umgebung aktiv ist (der vorherige Befehl funktioniert hat). + +/// tip | Tipp + +Dies ist **optional**, aber es ist eine gute Möglichkeit, **zu überprüfen**, ob alles wie erwartet funktioniert und Sie die beabsichtigte virtuelle Umgebung verwenden. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +Wenn es das `python`-Binary in `.venv/bin/python` anzeigt, innerhalb Ihres Projekts (in diesem Fall `awesome-project`), dann hat es funktioniert. 🎉 + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +Wenn es das `python`-Binary in `.venv\Scripts\python` anzeigt, innerhalb Ihres Projekts (in diesem Fall `awesome-project`), dann hat es funktioniert. 🎉 + +//// + +## `pip` aktualisieren { #upgrade-pip } + +/// tip | Tipp + +Wenn Sie `uv` verwenden, würden Sie das verwenden, um Dinge zu installieren anstelle von `pip`, sodass Sie `pip` nicht aktualisieren müssen. 😎 + +/// + +Wenn Sie `pip` verwenden, um Pakete zu installieren (es wird standardmäßig mit Python geliefert), sollten Sie es auf die neueste Version **aktualisieren**. + +Viele exotische Fehler beim Installieren eines Pakets werden einfach dadurch gelöst, dass zuerst `pip` aktualisiert wird. + +/// tip | Tipp + +Normalerweise würden Sie dies **einmal** tun, unmittelbar nachdem Sie die virtuelle Umgebung erstellt haben. + +/// + +Stellen Sie sicher, dass die virtuelle Umgebung aktiv ist (mit dem obigen Befehl) und führen Sie dann aus: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +## `.gitignore` hinzufügen { #add-gitignore } + +Wenn Sie **Git** verwenden (was Sie sollten), fügen Sie eine `.gitignore`-Datei hinzu, um alles in Ihrem `.venv` von Git auszuschließen. + +/// tip | Tipp + +Wenn Sie `uv` verwendet haben, um die virtuelle Umgebung zu erstellen, hat es dies bereits für Sie getan, Sie können diesen Schritt überspringen. 😎 + +/// + +/// tip | Tipp + +Tun Sie dies **einmal**, unmittelbar nachdem Sie die virtuelle Umgebung erstellt haben. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | Was dieser Befehl bedeutet + +* `echo "*"`: wird den Text `*` im Terminal „drucken“ (der nächste Teil ändert das ein wenig) +* `>`: alles, was durch den Befehl links von `>` im Terminal ausgegeben wird, sollte nicht gedruckt, sondern stattdessen in die Datei geschrieben werden, die rechts von `>` kommt +* `.gitignore`: der Name der Datei, in die der Text geschrieben werden soll + +Und `*` bedeutet für Git „alles“. Also wird alles im `.venv`-Verzeichnis ignoriert. + +Dieser Befehl erstellt eine Datei `.gitignore` mit dem Inhalt: + +```gitignore +* +``` + +/// + +## Pakete installieren { #install-packages } + +Nachdem Sie die Umgebung aktiviert haben, können Sie Pakete darin installieren. + +/// tip | Tipp + +Tun Sie dies **einmal**, wenn Sie die Pakete installieren oder aktualisieren, die Ihr Projekt benötigt. + +Wenn Sie eine Version aktualisieren oder ein neues Paket hinzufügen müssen, würden Sie **dies erneut tun**. + +/// + +### Pakete direkt installieren { #install-packages-directly } + +Wenn Sie es eilig haben und keine Datei verwenden möchten, um die Paketanforderungen Ihres Projekts zu deklarieren, können Sie sie direkt installieren. + +/// tip | Tipp + +Es ist eine (sehr) gute Idee, die Pakete und Versionen, die Ihr Programm benötigt, in einer Datei zu speichern (zum Beispiel `requirements.txt` oder `pyproject.toml`). + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Wenn Sie `uv` haben: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### Installation von `requirements.txt` { #install-from-requirements-txt } + +Wenn Sie eine `requirements.txt` haben, können Sie diese nun verwenden, um deren Pakete zu installieren. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Wenn Sie `uv` haben: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +Eine `requirements.txt` mit einigen Paketen könnte folgendermaßen aussehen: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## Ihr Programm ausführen { #run-your-program } + +Nachdem Sie die virtuelle Umgebung aktiviert haben, können Sie Ihr Programm ausführen, und es wird das Python innerhalb Ihrer virtuellen Umgebung mit den Paketen verwenden, die Sie dort installiert haben. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## Ihren Editor konfigurieren { #configure-your-editor } + +Sie würden wahrscheinlich einen Editor verwenden, stellen Sie sicher, dass Sie ihn so konfigurieren, dass er dieselbe virtuelle Umgebung verwendet, die Sie erstellt haben (er wird sie wahrscheinlich automatisch erkennen), sodass Sie Autovervollständigungen und Inline-Fehler erhalten können. + +Zum Beispiel: + +* VS Code +* PyCharm + +/// tip | Tipp + +Normalerweise müssen Sie dies nur **einmal** tun, wenn Sie die virtuelle Umgebung erstellen. + +/// + +## Die virtuelle Umgebung deaktivieren { #deactivate-the-virtual-environment } + +Sobald Sie mit der Arbeit an Ihrem Projekt fertig sind, können Sie die virtuelle Umgebung **deaktivieren**. + +
+ +```console +$ deactivate +``` + +
+ +Auf diese Weise, wenn Sie `python` ausführen, wird nicht versucht, es aus dieser virtuellen Umgebung mit den dort installierten Paketen auszuführen. + +## Bereit zu arbeiten { #ready-to-work } + +Jetzt sind Sie bereit, mit Ihrem Projekt zu arbeiten. + +/// tip | Tipp + +Möchten Sie verstehen, was das alles oben bedeutet? + +Lesen Sie weiter. 👇🤓 + +/// + +## Warum virtuelle Umgebungen { #why-virtual-environments } + +Um mit FastAPI zu arbeiten, müssen Sie Python installieren. + +Danach müssen Sie FastAPI und alle anderen Pakete, die Sie verwenden möchten, **installieren**. + +Um Pakete zu installieren, würden Sie normalerweise den `pip`-Befehl verwenden, der mit Python geliefert wird (oder ähnliche Alternativen). + +Wenn Sie jedoch `pip` direkt verwenden, werden die Pakete in Ihrer **globalen Python-Umgebung** (der globalen Installation von Python) installiert. + +### Das Problem { #the-problem } + +Was ist also das Problem beim Installieren von Paketen in der globalen Python-Umgebung? + +Irgendwann werden Sie wahrscheinlich viele verschiedene Programme schreiben, die von **verschiedenen Paketen** abhängen. Und einige dieser Projekte, an denen Sie arbeiten, werden von **verschiedenen Versionen** desselben Pakets abhängen. 😱 + +Zum Beispiel könnten Sie ein Projekt namens `philosophers-stone` erstellen, dieses Programm hängt von einem anderen Paket namens **`harry`, Version `1`** ab. Also müssen Sie `harry` installieren. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|benötigt| harry-1[harry v1] +``` + +Dann erstellen Sie zu einem späteren Zeitpunkt ein weiteres Projekt namens `prisoner-of-azkaban`, und dieses Projekt hängt ebenfalls von `harry` ab, aber dieses Projekt benötigt **`harry` Version `3`**. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |benötigt| harry-3[harry v3] +``` + +Aber jetzt ist das Problem, wenn Sie die Pakete global (in der globalen Umgebung) installieren anstatt in einer lokalen **virtuellen Umgebung**, müssen Sie wählen, welche Version von `harry` zu installieren ist. + +Wenn Sie `philosophers-stone` ausführen möchten, müssen Sie zuerst `harry` Version `1` installieren, zum Beispiel mit: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +Und dann hätten Sie `harry` Version `1` in Ihrer globalen Python-Umgebung installiert. + +```mermaid +flowchart LR + subgraph global[globale Umgebung] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) -->|benötigt| harry-1 + end +``` + +Aber dann, wenn Sie `prisoner-of-azkaban` ausführen möchten, müssen Sie `harry` Version `1` deinstallieren und `harry` Version `3` installieren (oder einfach die Version `3` installieren, was die Version `1` automatisch deinstallieren würde). + +
+ +```console +$ pip install "harry==3" +``` + +
+ +Und dann hätten Sie `harry` Version `3` in Ihrer globalen Python-Umgebung installiert. + +Und wenn Sie versuchen, `philosophers-stone` erneut auszuführen, besteht die Möglichkeit, dass es **nicht funktioniert**, weil es `harry` Version `1` benötigt. + +```mermaid +flowchart LR + subgraph global[globale Umgebung] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) -.-x|⛔️| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban-Projekt] + azkaban(prisoner-of-azkaban) --> |benötigt| harry-3 + end +``` + +/// tip | Tipp + +Es ist sehr üblich in Python-Paketen, alles zu versuchen, **Breaking Changes** in **neuen Versionen** zu vermeiden, aber es ist besser, auf Nummer sicher zu gehen und neue Versionen absichtlich zu installieren und wenn Sie die Tests ausführen können, sicherzustellen, dass alles korrekt funktioniert. + +/// + +Stellen Sie sich das jetzt mit **vielen** anderen **Paketen** vor, von denen alle Ihre **Projekte abhängen**. Das ist sehr schwierig zu verwalten. Und Sie würden wahrscheinlich einige Projekte mit einigen **inkompatiblen Versionen** der Pakete ausführen und nicht wissen, warum etwas nicht funktioniert. + +Darüber hinaus könnte es je nach Ihrem Betriebssystem (z. B. Linux, Windows, macOS) bereits mit installiertem Python geliefert worden sein. Und in diesem Fall hatte es wahrscheinlich einige Pakete mit bestimmten Versionen **installiert**, die von Ihrem System benötigt werden. Wenn Sie Pakete in der globalen Python-Umgebung installieren, könnten Sie einige der Programme, die mit Ihrem Betriebssystem geliefert wurden, **kaputtmachen**. + +## Wo werden Pakete installiert { #where-are-packages-installed } + +Wenn Sie Python installieren, werden einige Verzeichnisse mit einigen Dateien auf Ihrem Rechner erstellt. + +Einige dieser Verzeichnisse sind dafür zuständig, alle Pakete, die Sie installieren, aufzunehmen. + +Wenn Sie ausführen: + +
+ +```console +// Führen Sie dies jetzt nicht aus, es ist nur ein Beispiel 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +Das lädt eine komprimierte Datei mit dem FastAPI-Code herunter, normalerweise von PyPI. + +Es wird auch Dateien für andere Pakete **herunterladen**, von denen FastAPI abhängt. + +Dann wird es all diese Dateien **extrahieren** und sie in ein Verzeichnis auf Ihrem Rechner legen. + +Standardmäßig werden diese heruntergeladenen und extrahierten Dateien in das Verzeichnis gelegt, das mit Ihrer Python-Installation kommt, das ist die **globale Umgebung**. + +## Was sind virtuelle Umgebungen { #what-are-virtual-environments } + +Die Lösung für die Probleme, alle Pakete in der globalen Umgebung zu haben, besteht darin, eine **virtuelle Umgebung für jedes Projekt** zu verwenden, an dem Sie arbeiten. + +Eine virtuelle Umgebung ist ein **Verzeichnis**, sehr ähnlich zu dem globalen, in dem Sie die Pakete für ein Projekt installieren können. + +Auf diese Weise hat jedes Projekt seine eigene virtuelle Umgebung (`.venv`-Verzeichnis) mit seinen eigenen Paketen. + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) --->|benötigt| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban-Projekt] + azkaban(prisoner-of-azkaban) --->|benötigt| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## Was bedeutet das Aktivieren einer virtuellen Umgebung { #what-does-activating-a-virtual-environment-mean } + +Wenn Sie eine virtuelle Umgebung aktivieren, zum Beispiel mit: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Oder wenn Sie Bash für Windows verwenden (z. B. Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +Dieser Befehl erstellt oder ändert einige [Umgebungsvariablen](environment-variables.md){.internal-link target=_blank}, die für die nächsten Befehle verfügbar sein werden. + +Eine dieser Variablen ist die `PATH`-Variable. + +/// tip | Tipp + +Sie können mehr über die `PATH`-Umgebungsvariable im Abschnitt [Umgebungsvariablen](environment-variables.md#path-environment-variable){.internal-link target=_blank} erfahren. + +/// + +Das Aktivieren einer virtuellen Umgebung fügt deren Pfad `.venv/bin` (auf Linux und macOS) oder `.venv\Scripts` (auf Windows) zur `PATH`-Umgebungsvariable hinzu. + +Angenommen, die `PATH`-Variable sah vor dem Aktivieren der Umgebung so aus: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +Das bedeutet, dass das System nach Programmen sucht in: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +Das bedeutet, dass das System nach Programmen sucht in: + +* `C:\Windows\System32` + +//// + +Nach dem Aktivieren der virtuellen Umgebung würde die `PATH`-Variable folgendermaßen aussehen: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Das bedeutet, dass das System nun zuerst nach Programmen sucht in: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +bevor es in den anderen Verzeichnissen sucht. + +Wenn Sie also `python` im Terminal eingeben, wird das System das Python-Programm in + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +finden und dieses verwenden. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +Das bedeutet, dass das System nun zuerst nach Programmen sucht in: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +bevor es in den anderen Verzeichnissen sucht. + +Wenn Sie also `python` im Terminal eingeben, wird das System das Python-Programm in + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +finden und dieses verwenden. + +//// + +Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Variable platziert. Das System wird es **vor** allen anderen verfügbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausführen, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). + +Das Aktivieren einer virtuellen Umgebung ändert auch ein paar andere Dinge, aber dies ist eines der wichtigsten Dinge, die es tut. + +## Testen einer virtuellen Umgebung { #checking-a-virtual-environment } + +Wenn Sie testen, ob eine virtuelle Umgebung aktiv ist, zum Beispiel mit: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +bedeutet das, dass das `python`-Programm, das verwendet wird, das in der **virtuellen Umgebung** ist. + +Sie verwenden `which` auf Linux und macOS und `Get-Command` in Windows PowerShell. + +So funktioniert dieser Befehl: Er wird in der `PATH`-Umgebungsvariable nachsehen und **jeden Pfad in der Reihenfolge durchgehen**, um das Programm namens `python` zu finden. Sobald er es findet, wird er Ihnen **den Pfad** zu diesem Programm anzeigen. + +Der wichtigste Punkt ist, dass, wenn Sie `python` aufrufen, genau dieses „`python`“ ausgeführt wird. + +So können Sie überprüfen, ob Sie sich in der richtigen virtuellen Umgebung befinden. + +/// tip | Tipp + +Es ist einfach, eine virtuelle Umgebung zu aktivieren, ein Python zu bekommen und dann **zu einem anderen Projekt zu wechseln**. + +Und das zweite Projekt **würde nicht funktionieren**, weil Sie das **falsche Python** verwenden, aus einer virtuellen Umgebung für ein anderes Projekt. + +Es ist nützlich, überprüfen zu können, welches `python` verwendet wird. 🤓 + +/// + +## Warum eine virtuelle Umgebung deaktivieren { #why-deactivate-a-virtual-environment } + +Zum Beispiel könnten Sie an einem Projekt `philosophers-stone` arbeiten, diese virtuelle Umgebung **aktivieren**, Pakete installieren und mit dieser Umgebung arbeiten. + +Und dann möchten Sie an **einem anderen Projekt** `prisoner-of-azkaban` arbeiten. + +Sie gehen zu diesem Projekt: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +Wenn Sie die virtuelle Umgebung für `philosophers-stone` nicht deaktivieren, wird beim Ausführen von `python` im Terminal versucht, das Python von `philosophers-stone` zu verwenden. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// Fehler beim Importieren von sirius, es ist nicht installiert 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +Wenn Sie jedoch die virtuelle Umgebung deaktivieren und die neue für `prisoner-of-askaban` aktivieren, wird beim Ausführen von `python` das Python aus der virtuellen Umgebung in `prisoner-of-azkaban` verwendet. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// Sie müssen nicht im alten Verzeichnis sein, um zu deaktivieren, Sie können dies überall tun, sogar nachdem Sie zum anderen Projekt gewechselt haben 😎 +$ deactivate + +// Die virtuelle Umgebung in prisoner-of-azkaban/.venv 🚀 aktivieren +$ source .venv/bin/activate + +// Jetzt, wenn Sie python ausführen, wird das Paket sirius in dieser virtuellen Umgebung gefunden ✨ +$ python main.py + +I solemnly swear 🐺 +``` + +
+ +## Alternativen { #alternatives } + +Dies ist ein einfacher Leitfaden, um Ihnen den Einstieg zu erleichtern und Ihnen beizubringen, wie alles **unter der Haube** funktioniert. + +Es gibt viele **Alternativen** zur Verwaltung von virtuellen Umgebungen, Paketabhängigkeiten (Anforderungen), Projekten. + +Sobald Sie bereit sind und ein Tool verwenden möchten, das **das gesamte Projekt verwaltet**, Paketabhängigkeiten, virtuelle Umgebungen usw., würde ich Ihnen vorschlagen, uv auszuprobieren. + +`uv` kann viele Dinge tun, es kann: + +* **Python für Sie installieren**, einschließlich verschiedener Versionen +* Die **virtuelle Umgebung** für Ihre Projekte verwalten +* **Pakete installieren** +* Paket**abhängigkeiten und Versionen** für Ihr Projekt verwalten +* Sicherstellen, dass Sie eine **exakte** Menge an Paketen und Versionen zur Installation haben, einschließlich ihrer Abhängigkeiten, damit Sie sicher sein können, dass Sie Ihr Projekt in der Produktionsumgebung genauso ausführen können wie auf Ihrem Rechner während der Entwicklung, dies wird **Locking** genannt +* Und viele andere Dinge + +## Fazit { #conclusion } + +Wenn Sie das alles gelesen und verstanden haben, wissen Sie jetzt **viel mehr** über virtuelle Umgebungen als viele Entwickler da draußen. 🤓 + +Das Wissen über diese Details wird in Zukunft wahrscheinlich nützlich sein, wenn Sie etwas debuggen, das komplex erscheint, aber Sie werden wissen, **wie alles unter der Haube funktioniert**. 😎 diff --git a/docs/de/llm-prompt.md b/docs/de/llm-prompt.md new file mode 100644 index 000000000..23c111d2d --- /dev/null +++ b/docs/de/llm-prompt.md @@ -0,0 +1,338 @@ +### Target language + +Translate to German (Deutsch). + +Language code: de. + + +### Definitions + +"hyphen" + The character «-» + Unicode U+002D (HYPHEN-MINUS) + Alternative names: hyphen, dash, minus sign + +"dash" + The character «–» + Unicode U+2013 (EN DASH) + German name: Halbgeviertstrich + + +### Grammar to use when talking to the reader + +Use the formal grammar (use «Sie» instead of «Du»). + + +### Quotes + +1) Convert neutral double quotes («"») and English double typographic quotes («“» and «”») to German double typographic quotes («„» and «“»). Convert neutral single quotes («'») and English single typographic quotes («‘» and «’») to German single typographic quotes («‚» and «‘»). Do NOT convert «`"» to «„», do NOT convert «"`» to «“». + +Examples: + + Source (English): + + ««« + "Hello world" + “Hello Universe” + "He said: 'Hello'" + “my name is ‘Nils’” + `"__main__"` + `"items"` + »»» + + Result (German): + + ««« + „Hallo Welt“ + „Hallo Universum“ + „Er sagte: ‚Hallo‘“ + „Mein Name ist ‚Nils‘“ + `"__main__"` + `"items"` + »»» + + +### Ellipsis + +1) Make sure there is a space between an ellipsis and a word following or preceding the ellipsis. + +Examples: + + Source (English): + + ««« + ...as we intended. + ...this would work: + ...etc. + others... + More to come... + »»» + + Result (German): + + ««« + ... wie wir es beabsichtigt hatten. + ... das würde funktionieren: + ... usw. + Andere ... + Später mehr ... + »»» + +2) This does not apply in URLs, code blocks, and code snippets. Do not remove or add spaces there. + + +### Headings + +1) Translate headings using the infinite form. + +Examples: + + Source (English): + + ««« + ## Create a Project { #create-a-project } + »»» + + Translate with (German): + + ««« + ## Ein Projekt erstellen { #create-a-project } + »»» + + Do NOT translate with (German): + + ««« + ## Erstellen Sie ein Projekt { #create-a-project } + »»» + + Source (English): + + ««« + # Install Packages { #install-packages } + »»» + + Translate with (German): + + ««« + # Pakete installieren { #install-packages } + »»» + + Do NOT translate with (German): + + ««« + # Installieren Sie Pakete { #install-packages } + »»» + + Source (English): + + ««« + ### Run Your Program { #run-your-program } + »»» + + Translate with (German): + + ««« + ### Ihr Programm ausführen { #run-your-program } + »»» + + Do NOT translate with (German): + + ««« + ### Führen Sie Ihr Programm aus { #run-your-program } + »»» + +2) Make sure that the translated part of the heading does not end with a period. + +Example: + + Source (English): + + ««« + ## Another module with `APIRouter` { #another-module-with-apirouter } + »»» + + Translate with (German): + + ««« + ## Ein weiteres Modul mit `APIRouter` { #another-module-with-apirouter } + »»» + + Do NOT translate with (German) – notice the added period: + + ««« + ## Ein weiteres Modul mit `APIRouter`. { #another-module-with-apirouter } + »»» + +3) Replace occurrences of literal « - » (a space followed by a hyphen followed by a space) with « – » (a space followed by a dash followed by a space) in the translated part of the heading. + +Example: + + Source (English): + + ««« + # FastAPI in Containers - Docker { #fastapi-in-containers-docker } + »»» + + Translate with (German) – notice the dash: + + ««« + # FastAPI in Containern – Docker { #fastapi-in-containers-docker } + »»» + + Do NOT translate with (German) – notice the hyphen: + + ««« + # FastAPI in Containern - Docker { #fastapi-in-containers-docker } + »»» + +3.1) Do not apply rule 3 when there is no space before or no space after the dash. + +Example: + + Source (English): + + ««« + ## Type hints and annotations { #type-hints-and-annotations } + »»» + + Translate with (German) – use a short dash: + + ««« + ## Typhinweise und -annotationen { #type-hints-and-annotations } + »»» + + Do NOT translate with (German): + + ««« + ## Typhinweise und –annotationen { #type-hints-and-annotations } + »»» + +3.2) Do not apply rule 3 to the untranslated part of the heading inside curly brackets, which you shall not translate. + + +### German instructions, when to use and when not to use hyphens in words (written in first person, which is you) + +In der Regel versuche ich so weit wie möglich Worte zusammenzuschreiben, also ohne Bindestrich, es sei denn, es ist Konkretesding-Klassevondingen, etwa «Pydantic-Modell» (aber: «Datenbankmodell»), «Python-Modul» (aber: «Standardmodul»). Ich setze auch einen Bindestrich, wenn er die gleichen Buchstaben verbindet, etwa «Enum-Member», «Cloud-Dienst», «Template-Engine». Oder wenn das Wort sonst einfach zu lang wird, etwa, «Performance-Optimierung». Oder um etwas visuell besser zu dokumentieren, etwa «Pfadoperation-Dekorator», «Pfadoperation-Funktion». + + +### German instructions about difficult to translate technical terms (written in first person, which is you) + +Ich versuche nicht, alles einzudeutschen. Das bezieht sich besonders auf Begriffe aus dem Bereich der Programmierung. Ich wandele zwar korrekt in Großschreibung um und setze Bindestriche, wo notwendig, aber ansonsten lasse ich solch ein Wort unverändert. Beispielsweise wird aus dem englischen Wort «string» in der deutschen Übersetzung «String», aber nicht «Zeichenkette». Oder aus dem englischen Wort «request body» wird in der deutschen Übersetzung «Requestbody», aber nicht «Anfragekörper». Oder aus dem englischen «response» wird im Deutschen «Response», aber nicht «Antwort». + + +### List of English terms and their preferred German translations + +Below is a list of English terms and their preferred German translations, separated by a colon («:»). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. A term or a translation may be followed by an explanation in brackets, which explains when to translate the term this way. If a translation is preceded by «NOT», then that means: do NOT use this translation for this term. English nouns, starting with the word «the», have the German genus – «der», «die», «das» – prepended to their German translation, to help you to grammatically decline them in the translation. They are given in singular case, unless they have «(plural)» attached, which means they are given in plural case. Verbs are given in the full infinitive – starting with the word «to». + +* «/// check»: «/// check | Testen» +* «/// danger»: «/// danger | Gefahr» +* «/// info»: «/// info | Info» +* «/// note | Technical Details»: «/// note | Technische Details» +* «/// note»: «/// note | Hinweis» +* «/// tip»: «/// tip | Tipp» +* «/// warning»: «/// warning | Achtung» +* «you»: «Sie» +* «your»: «Ihr» +* «e.g»: «z. B.» +* «etc.»: «usw.» +* «ref»: «Ref.» +* «the Tutorial - User guide»: «das Tutorial – Benutzerhandbuch» +* «the Advanced User Guide»: «das Handbuch für fortgeschrittene Benutzer» +* «the SQLModel docs»: «die SQLModel-Dokumentation» +* «the docs»: «die Dokumentation» (use singular case) +* «the env var»: «die Umgebungsvariable» +* «the `PATH` environment variable»: «die `PATH`-Umgebungsvariable» +* «the `PATH`»: «der `PATH`» +* «the `requirements.txt`»: «die `requirements.txt`» +* «the API Router»: «der API-Router» +* «the Authorization-Header»: «der Autorisierungsheader» +* «the `Authorization`-Header»: «der `Authorization`-Header» +* «the background task»: «der Hintergrundtask» +* «the button»: «der Button» +* «the cloud provider»: «der Cloudanbieter» +* «the CLI»: «Das CLI» +* «the command line interface»: «Das Kommandozeileninterface» +* «the default value»: «der Defaultwert» +* «the default value»: NOT «der Standardwert» +* «the default declaration»: «die Default-Deklaration» +* «the dict»: «das Dict» +* «the dictionary»: «das Dictionary» +* «the enumeration»: «die Enumeration» +* «the enum»: «das Enum» +* «the engine»: «die Engine» +* «the error response»: «die Error-Response» +* «the event»: «das Event» +* «the exception»: «die Exception» +* «the exception handler»: «der Exceptionhandler» +* «the form model»: «das Formularmodell» +* «the form body»: «der Formularbody» +* «the header»: «der Header» +* «the headers» (plural): «die Header» +* «in headers» (plural): «in Headern» +* «the forwarded header»: «der Forwarded-Header» +* «the lifespan event»: «das Lifespan-Event» +* «the lock»: «der Lock» +* «the locking»: «das Locking» +* «the mobile application»: «die Mobile-Anwendung» +* «the model object»: «das Modellobjekt» +* «the mounting»: «das Mounten» +* «mounted»: «gemountet» +* «the origin»: «das Origin» +* «the override»: «Die Überschreibung» +* «the parameter»: «der Parameter» +* «the parameters» (plural): «die Parameter» +* «the function parameter»: «der Funktionsparameter» +* «the default parameter»: «der Defaultparameter» +* «the body parameter»: «der Body-Parameter» +* «the request body parameter»: «der Requestbody-Parameter» +* «the path parameter»: «der Pfad-Parameter» +* «the query parameter»: «der Query-Parameter» +* «the cookie parameter»: «der Cookie-Parameter» +* «the header parameter»: «der Header-Parameter» +* «the form parameter»: «der Formular-Parameter» +* «the payload»: «die Payload» +* «the performance»: NOT «die Performance» +* «the query»: «die Query» +* «the recap»: «die Zusammenfassung» +* «the request» (what the client sends to the server): «der Request» +* «the request body»: «der Requestbody» +* «the request bodies» (plural): «die Requestbodys» +* «the response» (what the server sends back to the client): «die Response» +* «the return type»: «der Rückgabetyp» +* «the return value»: «der Rückgabewert» +* «the startup» (the event of the app): «der Startup» +* «the shutdown» (the event of the app): «der Shutdown» +* «the startup event»: «das Startup-Event» +* «the shutdown event»: «das Shutdown-Event» +* «the startup» (of the server): «das Hochfahren» +* «the startup» (the company): «das Startup» +* «the SDK»: «das SDK» +* «the tag»: «der Tag» +* «the type annotation»: «die Typannotation» +* «the type hint»: «der Typhinweis» +* «the wildcard»: «die Wildcard» +* «the worker class»: «die Workerklasse» +* «the worker class»: NOT «die Arbeiterklasse» +* «the worker process»: «der Workerprozess» +* «the worker process»: NOT «der Arbeiterprozess» +* «to commit»: «committen» +* «to modify»: «ändern» +* «to serve» (an application): «bereitstellen» +* «to serve» (a response): «ausliefern» +* «to serve»: NOT «bedienen» +* «to upgrade»: «aktualisieren» +* «to wrap»: «wrappen» +* «to wrap»: NOT «hüllen» +* «`foo` as a `type`»: «`foo` vom Typ `type`» +* «`foo` as a `type`»: «`foo`, ein `type`» +* «FastAPI's X»: «FastAPIs X» +* «Starlette's Y»: «Starlettes Y» +* «X is case-sensitive»: «Groß-/Klein­schrei­bung ist relevant in X» +* «X is case-insensitive»: «Groß-/Klein­schrei­bung ist nicht relevant in X» +* «standard Python»: «Standard-Python» +* «deprecated»: «deprecatet» + + +### Other rules + +Preserve indentation. Keep emoticons. Encode in utf-8. Use Linux line breaks (LF). From d2da9e8e46042d5358feb5944044972e7e894ee6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 15:10:36 +0000 Subject: [PATCH 402/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2cf52b730..b0a863f60 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -19,6 +19,10 @@ hide: * 📝 Fix and Improve English Documentation. PR [#14048](https://github.com/fastapi/fastapi/pull/14048) by [@nilslindemann](https://github.com/nilslindemann). +### Translations + +* 📝 Update prompts and German translation. PR [#14015](https://github.com/fastapi/fastapi/pull/14015) by [@nilslindemann](https://github.com/nilslindemann). + ### Internal * ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). From fe4542279d59bb5a74ac5b4c84e8edf0efb9ef5b Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Sat, 20 Sep 2025 18:23:06 +0200 Subject: [PATCH 403/455] =?UTF-8?q?=F0=9F=9A=A8=20Install=20pydantic.mypy?= =?UTF-8?q?=20plugin=20(#14081)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/security/api_key.py | 6 +++--- pyproject.toml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py index 70c2dca8a..6d6dd01d9 100644 --- a/fastapi/security/api_key.py +++ b/fastapi/security/api_key.py @@ -100,7 +100,7 @@ class APIKeyQuery(APIKeyBase): ] = True, ): self.model: APIKey = APIKey( - **{"in": APIKeyIn.query}, # type: ignore[arg-type] + **{"in": APIKeyIn.query}, name=name, description=description, ) @@ -188,7 +188,7 @@ class APIKeyHeader(APIKeyBase): ] = True, ): self.model: APIKey = APIKey( - **{"in": APIKeyIn.header}, # type: ignore[arg-type] + **{"in": APIKeyIn.header}, name=name, description=description, ) @@ -276,7 +276,7 @@ class APIKeyCookie(APIKeyBase): ] = True, ): self.model: APIKey = APIKey( - **{"in": APIKeyIn.cookie}, # type: ignore[arg-type] + **{"in": APIKeyIn.cookie}, name=name, description=description, ) diff --git a/pyproject.toml b/pyproject.toml index 6ec72374c..fbfdea79a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -142,6 +142,7 @@ source-includes = [ name = "fastapi-slim" [tool.mypy] +plugins = ["pydantic.mypy"] strict = true [[tool.mypy.overrides]] From c8a29944f4404f16a6ee2feb98bf456af059dd56 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 16:23:31 +0000 Subject: [PATCH 404/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b0a863f60..5a47c244d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -25,6 +25,7 @@ hide: ### Internal +* 🚨 Install pydantic.mypy plugin. PR [#14081](https://github.com/fastapi/fastapi/pull/14081) by [@svlandeg](https://github.com/svlandeg). * ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). * 🔨 Update translations script. PR [#13968](https://github.com/fastapi/fastapi/pull/13968) by [@YuriiMotov](https://github.com/YuriiMotov). * 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). From 11d424c3dc4e7feb2fcf8be32957bf3951a07e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=B1=E5=B4=8E=E3=83=92=E3=82=AB=E3=83=AB?= Date: Sun, 21 Sep 2025 00:26:21 +0800 Subject: [PATCH 405/455] =?UTF-8?q?=E2=9C=85=20Simplify=20tests=20for=20re?= =?UTF-8?q?sponse=5Fmodel=20(#14062)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_response_model/test_tutorial003.py | 25 ++- .../test_tutorial003_04.py | 17 +- .../test_tutorial003_04_py310.py | 12 -- .../test_tutorial003_py310.py | 160 ------------------ 4 files changed, 33 insertions(+), 181 deletions(-) delete mode 100644 tests/test_tutorial/test_response_model/test_tutorial003_04_py310.py delete mode 100644 tests/test_tutorial/test_response_model/test_tutorial003_py310.py diff --git a/tests/test_tutorial/test_response_model/test_tutorial003.py b/tests/test_tutorial/test_response_model/test_tutorial003.py index 384c8e0f1..70cfd6e4c 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003.py @@ -1,12 +1,27 @@ +import importlib + +import pytest from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient -from docs_src.response_model.tutorial003 import app - -client = TestClient(app) +from ...utils import needs_py310 -def test_post_user(): +@pytest.fixture( + name="client", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.response_model.{request.param}") + + client = TestClient(mod.app) + return client + + +def test_post_user(client: TestClient): response = client.post( "/user/", json={ @@ -24,7 +39,7 @@ def test_post_user(): } -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_04.py b/tests/test_tutorial/test_response_model/test_tutorial003_04.py index 4aa80145a..f32e93ddc 100644 --- a/tests/test_tutorial/test_response_model/test_tutorial003_04.py +++ b/tests/test_tutorial/test_response_model/test_tutorial003_04.py @@ -1,9 +1,18 @@ +import importlib + import pytest from fastapi.exceptions import FastAPIError +from ...utils import needs_py310 -def test_invalid_response_model(): + +@pytest.mark.parametrize( + "module_name", + [ + "tutorial003_04", + pytest.param("tutorial003_04_py310", marks=needs_py310), + ], +) +def test_invalid_response_model(module_name: str) -> None: with pytest.raises(FastAPIError): - from docs_src.response_model.tutorial003_04 import app - - assert app # pragma: no cover + importlib.import_module(f"docs_src.response_model.{module_name}") diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_04_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_04_py310.py deleted file mode 100644 index b876facc8..000000000 --- a/tests/test_tutorial/test_response_model/test_tutorial003_04_py310.py +++ /dev/null @@ -1,12 +0,0 @@ -import pytest -from fastapi.exceptions import FastAPIError - -from ...utils import needs_py310 - - -@needs_py310 -def test_invalid_response_model(): - with pytest.raises(FastAPIError): - from docs_src.response_model.tutorial003_04_py310 import app - - assert app # pragma: no cover diff --git a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py b/tests/test_tutorial/test_response_model/test_tutorial003_py310.py deleted file mode 100644 index 3a3aee38a..000000000 --- a/tests/test_tutorial/test_response_model/test_tutorial003_py310.py +++ /dev/null @@ -1,160 +0,0 @@ -import pytest -from dirty_equals import IsDict, IsOneOf -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.response_model.tutorial003_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_post_user(client: TestClient): - response = client.post( - "/user/", - json={ - "username": "foo", - "password": "fighter", - "email": "foo@example.com", - "full_name": "Grave Dohl", - }, - ) - assert response.status_code == 200, response.text - assert response.json() == { - "username": "foo", - "email": "foo@example.com", - "full_name": "Grave Dohl", - } - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/user/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/UserOut"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create User", - "operationId": "create_user_user__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/UserIn"} - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "UserOut": { - "title": "UserOut", - "required": IsOneOf( - ["username", "email", "full_name"], - # TODO: remove when deprecating Pydantic v1 - ["username", "email"], - ), - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "email": { - "title": "Email", - "type": "string", - "format": "email", - }, - "full_name": IsDict( - { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Full Name", "type": "string"} - ), - }, - }, - "UserIn": { - "title": "UserIn", - "required": ["username", "password", "email"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "password": {"title": "Password", "type": "string"}, - "email": { - "title": "Email", - "type": "string", - "format": "email", - }, - "full_name": IsDict( - { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Full Name", "type": "string"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, - } From 651603cb37d728f4b814ce7b160354546b8d6a04 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 16:27:07 +0000 Subject: [PATCH 406/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5a47c244d..1d7b869ec 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -25,6 +25,7 @@ hide: ### Internal +* ✅ Simplify tests for response_model. PR [#14062](https://github.com/fastapi/fastapi/pull/14062) by [@dynamicy](https://github.com/dynamicy). * 🚨 Install pydantic.mypy plugin. PR [#14081](https://github.com/fastapi/fastapi/pull/14081) by [@svlandeg](https://github.com/svlandeg). * ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). * 🔨 Update translations script. PR [#13968](https://github.com/fastapi/fastapi/pull/13968) by [@YuriiMotov](https://github.com/YuriiMotov). From 744736af9c5c4d422c8f46f5b6f289abded0d11b Mon Sep 17 00:00:00 2001 From: Sofie Van Landeghem Date: Sat, 20 Sep 2025 18:27:21 +0200 Subject: [PATCH 407/455] =?UTF-8?q?=F0=9F=93=9D=20Remove=20outdated=20form?= =?UTF-8?q?atting=20from=20`path-params-numeric-validations.md`=20for=20la?= =?UTF-8?q?nguages=20`en`,=20`es`=20and=20`uk`.=20(#14059)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../docs/tutorial/path-params-numeric-validations.md | 10 ---------- .../docs/tutorial/path-params-numeric-validations.md | 10 ---------- .../docs/tutorial/path-params-numeric-validations.md | 10 ---------- 3 files changed, 30 deletions(-) diff --git a/docs/en/docs/tutorial/path-params-numeric-validations.md b/docs/en/docs/tutorial/path-params-numeric-validations.md index ef1caea42..f7f2d6ceb 100644 --- a/docs/en/docs/tutorial/path-params-numeric-validations.md +++ b/docs/en/docs/tutorial/path-params-numeric-validations.md @@ -54,18 +54,8 @@ It doesn't matter for **FastAPI**. It will detect the parameters by their names, So, you can declare your function as: -//// tab | Python 3.8 non-Annotated - -/// tip - -Prefer to use the `Annotated` version if possible. - -/// - {* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} -//// - But keep in mind that if you use `Annotated`, you won't have this problem, it won't matter as you're not using the function parameter default values for `Query()` or `Path()`. {* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} diff --git a/docs/es/docs/tutorial/path-params-numeric-validations.md b/docs/es/docs/tutorial/path-params-numeric-validations.md index 44d73b5ed..4ea01753b 100644 --- a/docs/es/docs/tutorial/path-params-numeric-validations.md +++ b/docs/es/docs/tutorial/path-params-numeric-validations.md @@ -54,18 +54,8 @@ No importa para **FastAPI**. Detectará los parámetros por sus nombres, tipos y Así que puedes declarar tu función como: -//// tab | Python 3.8 non-Annotated - -/// tip | Consejo - -Prefiere usar la versión `Annotated` si es posible. - -/// - {* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} -//// - Pero ten en cuenta que si usas `Annotated`, no tendrás este problema, no importará ya que no estás usando los valores por defecto de los parámetros de la función para `Query()` o `Path()`. {* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} diff --git a/docs/uk/docs/tutorial/path-params-numeric-validations.md b/docs/uk/docs/tutorial/path-params-numeric-validations.md index 281ee183c..8ee4f480f 100644 --- a/docs/uk/docs/tutorial/path-params-numeric-validations.md +++ b/docs/uk/docs/tutorial/path-params-numeric-validations.md @@ -55,18 +55,8 @@ Python видасть помилку, якщо розмістити значен Тому Ви можете оголосити Вашу функцію так: -//// tab | Python 3.8 non-Annotated - -/// tip | Підказка - -За можливості віддавайте перевагу версії з використанням `Annotated`. - -/// - {* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} -//// - Але майте на увазі, що якщо Ви використовуєте `Annotated`, ця проблема не виникне, оскільки Ви не використовуєте значення за замовчуванням для параметрів `Query()` або `Path()`. {* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} From 73841b9976ded9858e4a2e1c8f0584e47c8e7dcb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 16:28:18 +0000 Subject: [PATCH 408/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1d7b869ec..3bf0899fc 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -17,6 +17,7 @@ hide: ### Docs +* 📝 Remove outdated formatting from `path-params-numeric-validations.md` for languages `en`, `es` and `uk`.. PR [#14059](https://github.com/fastapi/fastapi/pull/14059) by [@svlandeg](https://github.com/svlandeg). * 📝 Fix and Improve English Documentation. PR [#14048](https://github.com/fastapi/fastapi/pull/14048) by [@nilslindemann](https://github.com/nilslindemann). ### Translations From c831cdbde22e2dbaae8bcac4544a5556a5a04b5e Mon Sep 17 00:00:00 2001 From: secrett2633 <65999962+secrett2633@users.noreply.github.com> Date: Sun, 21 Sep 2025 01:30:34 +0900 Subject: [PATCH 409/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20`inspect.getcorout?= =?UTF-8?q?inefunction()`=20can=20break=20testing=20with=20`unittest.mock.?= =?UTF-8?q?patch()`=20(#14022)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 10 ++++++++-- fastapi/routing.py | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 081b63a8b..1b15e6459 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -1,4 +1,5 @@ import inspect +import sys from contextlib import AsyncExitStack, contextmanager from copy import copy, deepcopy from dataclasses import dataclass @@ -73,6 +74,11 @@ from starlette.responses import Response from starlette.websockets import WebSocket from typing_extensions import Annotated, get_args, get_origin +if sys.version_info >= (3, 13): # pragma: no cover + from inspect import iscoroutinefunction +else: # pragma: no cover + from asyncio import iscoroutinefunction + multipart_not_installed_error = ( 'Form data requires "python-multipart" to be installed. \n' 'You can install "python-multipart" with: \n\n' @@ -529,11 +535,11 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: def is_coroutine_callable(call: Callable[..., Any]) -> bool: if inspect.isroutine(call): - return inspect.iscoroutinefunction(call) + return iscoroutinefunction(call) if inspect.isclass(call): return False dunder_call = getattr(call, "__call__", None) # noqa: B004 - return inspect.iscoroutinefunction(dunder_call) + return iscoroutinefunction(dunder_call) def is_async_gen_callable(call: Callable[..., Any]) -> bool: diff --git a/fastapi/routing.py b/fastapi/routing.py index 5418ad982..f620ced5f 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1,8 +1,8 @@ -import asyncio import dataclasses import email.message import inspect import json +import sys from contextlib import AsyncExitStack, asynccontextmanager from enum import Enum, IntEnum from typing import ( @@ -76,6 +76,11 @@ from starlette.types import AppType, ASGIApp, Lifespan, Scope from starlette.websockets import WebSocket from typing_extensions import Annotated, Doc, deprecated +if sys.version_info >= (3, 13): # pragma: no cover + from inspect import iscoroutinefunction +else: # pragma: no cover + from asyncio import iscoroutinefunction + def _prepare_response_content( res: Any, @@ -232,7 +237,7 @@ def get_request_handler( embed_body_fields: bool = False, ) -> Callable[[Request], Coroutine[Any, Any, Response]]: assert dependant.call is not None, "dependant.call must be a function" - is_coroutine = asyncio.iscoroutinefunction(dependant.call) + is_coroutine = iscoroutinefunction(dependant.call) is_body_form = body_field and isinstance(body_field.field_info, params.Form) if isinstance(response_class, DefaultPlaceholder): actual_response_class: Type[Response] = response_class.value From d2f6b92a83eda19c3a070fd834a773cd0ba27e6a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 16:31:01 +0000 Subject: [PATCH 410/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3bf0899fc..e3546df4e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Fix `inspect.getcoroutinefunction()` can break testing with `unittest.mock.patch()`. PR [#14022](https://github.com/fastapi/fastapi/pull/14022) by [@secrett2633](https://github.com/secrett2633). + ### Refactors * 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). From 5fef4d199b30d53057fd3cd6f78e149bd857d1bc Mon Sep 17 00:00:00 2001 From: Amogha Rao <63849274+Amogha-ark@users.noreply.github.com> Date: Sat, 20 Sep 2025 22:27:53 +0530 Subject: [PATCH 411/455] =?UTF-8?q?=E2=9C=85=20Enable=20test=20case=20for?= =?UTF-8?q?=20duplicated=20headers=20in=20`test=5Ftutorial/test=5Fheader?= =?UTF-8?q?=5Fparams/test=5Ftutorial003.py`=20(#13864)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: amogha-rao Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../test_tutorial/test_header_params/test_tutorial003.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_tutorial/test_header_params/test_tutorial003.py b/tests/test_tutorial/test_header_params/test_tutorial003.py index 0b58227f6..473b96123 100644 --- a/tests/test_tutorial/test_header_params/test_tutorial003.py +++ b/tests/test_tutorial/test_header_params/test_tutorial003.py @@ -29,8 +29,12 @@ def get_client(request: pytest.FixtureRequest): [ ("/items", None, 200, {"X-Token values": None}), ("/items", {"x-token": "foo"}, 200, {"X-Token values": ["foo"]}), - # TODO: fix this, is it a bug? - # ("/items", [("x-token", "foo"), ("x-token", "bar")], 200, {"X-Token values": ["foo", "bar"]}), + ( + "/items", + [("x-token", "foo"), ("x-token", "bar")], + 200, + {"X-Token values": ["foo", "bar"]}, + ), ], ) def test(path, headers, expected_status, expected_response, client: TestClient): From 14168b43eb9342adcaa77f156a4e0600bcabb4f5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 16:58:15 +0000 Subject: [PATCH 412/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index e3546df4e..c13fcdd5f 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Refactors +* ✅ Enable test case for duplicated headers in `test_tutorial/test_header_params/test_tutorial003.py`. PR [#13864](https://github.com/fastapi/fastapi/pull/13864) by [@Amogha-ark](https://github.com/Amogha-ark). * 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). ### Upgrades From bc5013cd56c1be81aca9b60f43c189c1d05b499a Mon Sep 17 00:00:00 2001 From: Carlos Mario Toro <41237977+cmtoro@users.noreply.github.com> Date: Sat, 20 Sep 2025 12:11:46 -0500 Subject: [PATCH 413/455] =?UTF-8?q?=E2=9C=A8=20Add=20OpenAPI=20`external?= =?UTF-8?q?=5Fdocs`=20parameter=20to=20`FastAPI`=20(#13713)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- fastapi/applications.py | 28 ++++++++++++++++++++++++++++ fastapi/openapi/utils.py | 3 +++ tests/main.py | 7 ++++++- tests/test_application.py | 4 ++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/fastapi/applications.py b/fastapi/applications.py index 05c7bd2be..b3424efcc 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -810,6 +810,32 @@ class FastAPI(Starlette): """ ), ] = True, + openapi_external_docs: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + This field allows you to provide additional external documentation links. + If provided, it must be a dictionary containing: + + * `description`: A brief description of the external documentation. + * `url`: The URL pointing to the external documentation. The value **MUST** + be a valid URL format. + + **Example**: + + ```python + from fastapi import FastAPI + + external_docs = { + "description": "Detailed API Reference", + "url": "https://example.com/api-docs", + } + + app = FastAPI(openapi_external_docs=external_docs) + ``` + """ + ), + ] = None, **extra: Annotated[ Any, Doc( @@ -838,6 +864,7 @@ class FastAPI(Starlette): self.swagger_ui_parameters = swagger_ui_parameters self.servers = servers or [] self.separate_input_output_schemas = separate_input_output_schemas + self.openapi_external_docs = openapi_external_docs self.extra = extra self.openapi_version: Annotated[ str, @@ -992,6 +1019,7 @@ class FastAPI(Starlette): tags=self.openapi_tags, servers=self.servers, separate_input_output_schemas=self.separate_input_output_schemas, + external_docs=self.openapi_external_docs, ) return self.openapi_schema diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index eda64a999..21105cf65 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -488,6 +488,7 @@ def get_openapi( contact: Optional[Dict[str, Union[str, Any]]] = None, license_info: Optional[Dict[str, Union[str, Any]]] = None, separate_input_output_schemas: bool = True, + external_docs: Optional[Dict[str, Any]] = None, ) -> Dict[str, Any]: info: Dict[str, Any] = {"title": title, "version": version} if summary: @@ -565,4 +566,6 @@ def get_openapi( output["webhooks"] = webhook_paths if tags: output["tags"] = tags + if external_docs: + output["externalDocs"] = external_docs return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore diff --git a/tests/main.py b/tests/main.py index 6927eab61..2f1d61711 100644 --- a/tests/main.py +++ b/tests/main.py @@ -3,7 +3,12 @@ from typing import FrozenSet, List, Optional from fastapi import FastAPI, Path, Query -app = FastAPI() +external_docs = { + "description": "External API documentation.", + "url": "https://docs.example.com/api-general", +} + +app = FastAPI(openapi_external_docs=external_docs) @app.api_route("/api_route") diff --git a/tests/test_application.py b/tests/test_application.py index a7d50ea72..8f1b0a18d 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -58,6 +58,10 @@ def test_openapi_schema(): assert response.json() == { "openapi": "3.1.0", "info": {"title": "FastAPI", "version": "0.1.0"}, + "externalDocs": { + "description": "External API documentation.", + "url": "https://docs.example.com/api-general", + }, "paths": { "/api_route": { "get": { From 243f012fd0b3c52e4b6505f04bcfc9f7532c1444 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 17:12:09 +0000 Subject: [PATCH 414/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c13fcdd5f..443ae7111 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Features + +* ✨ Add OpenAPI `external_docs` parameter to `FastAPI`. PR [#13713](https://github.com/fastapi/fastapi/pull/13713) by [@cmtoro](https://github.com/cmtoro). + ### Fixes * 🐛 Fix `inspect.getcoroutinefunction()` can break testing with `unittest.mock.patch()`. PR [#14022](https://github.com/fastapi/fastapi/pull/14022) by [@secrett2633](https://github.com/secrett2633). From 9ac56c70f214fd02fc82eccaf4c7da3dfa380f9c Mon Sep 17 00:00:00 2001 From: rmawatson Date: Sat, 20 Sep 2025 19:25:53 +0200 Subject: [PATCH 415/455] =?UTF-8?q?=F0=9F=90=9B=20Reenable=20`allow=5Farbi?= =?UTF-8?q?trary=5Ftypes`=20when=20only=201=20argument=20is=20used=20on=20?= =?UTF-8?q?the=20API=20endpoint=20(#13694)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sofie Van Landeghem Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- fastapi/dependencies/utils.py | 6 ++++- tests/test_compat.py | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 1b15e6459..d9f6bf2d7 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -922,7 +922,11 @@ async def request_body_to_args( fields_to_extract: List[ModelField] = body_fields - if single_not_embedded_field and lenient_issubclass(first_field.type_, BaseModel): + if ( + single_not_embedded_field + and lenient_issubclass(first_field.type_, BaseModel) + and isinstance(received_body, FormData) + ): fields_to_extract = get_cached_model_fields(first_field.type_) if isinstance(received_body, FormData): diff --git a/tests/test_compat.py b/tests/test_compat.py index f4a3093c5..43c686489 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -80,6 +80,51 @@ def test_complex(): assert response2.json() == [1, 2] +@needs_pydanticv2 +def test_propagates_pydantic2_model_config(): + app = FastAPI() + + class Missing: + def __bool__(self): + return False + + class EmbeddedModel(BaseModel): + model_config = ConfigDict(arbitrary_types_allowed=True) + value: Union[str, Missing] = Missing() + + class Model(BaseModel): + model_config = ConfigDict( + arbitrary_types_allowed=True, + ) + value: Union[str, Missing] = Missing() + embedded_model: EmbeddedModel = EmbeddedModel() + + @app.post("/") + def foo(req: Model) -> Dict[str, Union[str, None]]: + return { + "value": req.value or None, + "embedded_value": req.embedded_model.value or None, + } + + client = TestClient(app) + + response = client.post("/", json={}) + assert response.status_code == 200, response.text + assert response.json() == { + "value": None, + "embedded_value": None, + } + + response2 = client.post( + "/", json={"value": "foo", "embedded_model": {"value": "bar"}} + ) + assert response2.status_code == 200, response2.text + assert response2.json() == { + "value": "foo", + "embedded_value": "bar", + } + + def test_is_bytes_sequence_annotation_union(): # For coverage # TODO: in theory this would allow declaring types that could be lists of bytes From 21aa9d3719ccd4685844e86a58d162db09a2f415 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 17:26:18 +0000 Subject: [PATCH 416/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 443ae7111..353788c76 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Fixes +* 🐛 Reenable `allow_arbitrary_types` when only 1 argument is used on the API endpoint. PR [#13694](https://github.com/fastapi/fastapi/pull/13694) by [@rmawatson](https://github.com/rmawatson). * 🐛 Fix `inspect.getcoroutinefunction()` can break testing with `unittest.mock.patch()`. PR [#14022](https://github.com/fastapi/fastapi/pull/14022) by [@secrett2633](https://github.com/secrett2633). ### Refactors From c2c6049b8f021a5a0576599ed36af930490173b2 Mon Sep 17 00:00:00 2001 From: Evgeny Bokshitsky Date: Sat, 20 Sep 2025 21:37:18 +0400 Subject: [PATCH 417/455] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Create=20`dependen?= =?UTF-8?q?cy-cache`=20dict=20in=20`solve=5Fdependencies`=20only=20if=20`N?= =?UTF-8?q?one`=20(don't=20re-create=20if=20empty)=20(#13689)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index d9f6bf2d7..8dd0a14c8 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -593,7 +593,8 @@ async def solve_dependencies( response = Response() del response.headers["content-length"] response.status_code = None # type: ignore - dependency_cache = dependency_cache or {} + if dependency_cache is None: + dependency_cache = {} sub_dependant: Dependant for sub_dependant in dependant.dependencies: sub_dependant.call = cast(Callable[..., Any], sub_dependant.call) @@ -630,7 +631,6 @@ async def solve_dependencies( embed_body_fields=embed_body_fields, ) background_tasks = solved_result.background_tasks - dependency_cache.update(solved_result.dependency_cache) if solved_result.errors: errors.extend(solved_result.errors) continue From 0358d3eab5bd27c4d71f9adb6a8e91184e936f5e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 17:37:45 +0000 Subject: [PATCH 418/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 353788c76..c8776890e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -18,6 +18,7 @@ hide: ### Refactors +* ♻️ Create `dependency-cache` dict in `solve_dependencies` only if `None` (don't re-create if empty). PR [#13689](https://github.com/fastapi/fastapi/pull/13689) by [@bokshitsky](https://github.com/bokshitsky). * ✅ Enable test case for duplicated headers in `test_tutorial/test_header_params/test_tutorial003.py`. PR [#13864](https://github.com/fastapi/fastapi/pull/13864) by [@Amogha-ark](https://github.com/Amogha-ark). * 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). From 8ede27223e48386b4cc97302eea0818e2e767187 Mon Sep 17 00:00:00 2001 From: sammasak Date: Sat, 20 Sep 2025 19:47:24 +0200 Subject: [PATCH 419/455] =?UTF-8?q?=E2=9C=A8=20Allow=20array=20values=20fo?= =?UTF-8?q?r=20OpenAPI=20schema=20`type`=20field=20(#13639)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lukas Rajala Co-authored-by: dlax Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- fastapi/openapi/models.py | 10 ++++++++-- tests/test_custom_schema_fields.py | 19 +++++++++++++++++-- tests/test_openapi_schema_type.py | 26 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 tests/test_openapi_schema_type.py diff --git a/fastapi/openapi/models.py b/fastapi/openapi/models.py index ed07b40f5..81d276aed 100644 --- a/fastapi/openapi/models.py +++ b/fastapi/openapi/models.py @@ -121,6 +121,12 @@ class ExternalDocumentation(BaseModelWithConfig): url: AnyUrl +# Ref JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation#name-type +SchemaType = Literal[ + "array", "boolean", "integer", "null", "number", "object", "string" +] + + class Schema(BaseModelWithConfig): # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu # Core Vocabulary @@ -145,7 +151,7 @@ class Schema(BaseModelWithConfig): dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None prefixItems: Optional[List["SchemaOrBool"]] = None # TODO: uncomment and remove below when deprecating Pydantic v1 - # It generales a list of schemas for tuples, before prefixItems was available + # It generates a list of schemas for tuples, before prefixItems was available # items: Optional["SchemaOrBool"] = None items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None contains: Optional["SchemaOrBool"] = None @@ -157,7 +163,7 @@ class Schema(BaseModelWithConfig): unevaluatedProperties: Optional["SchemaOrBool"] = None # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural # A Vocabulary for Structural Validation - type: Optional[str] = None + type: Optional[Union[SchemaType, List[SchemaType]]] = None enum: Optional[List[Any]] = None const: Optional[Any] = None multipleOf: Optional[float] = Field(default=None, gt=0) diff --git a/tests/test_custom_schema_fields.py b/tests/test_custom_schema_fields.py index ee51fc7ff..d890291b1 100644 --- a/tests/test_custom_schema_fields.py +++ b/tests/test_custom_schema_fields.py @@ -1,7 +1,13 @@ +from typing import Optional + from fastapi import FastAPI from fastapi._compat import PYDANTIC_V2 from fastapi.testclient import TestClient from pydantic import BaseModel +from typing_extensions import Annotated + +if PYDANTIC_V2: + from pydantic import WithJsonSchema app = FastAPI() @@ -10,12 +16,17 @@ class Item(BaseModel): name: str if PYDANTIC_V2: + description: Annotated[ + Optional[str], WithJsonSchema({"type": ["string", "null"]}) + ] = None + model_config = { "json_schema_extra": { "x-something-internal": {"level": 4}, } } else: + description: Optional[str] = None # type: ignore[no-redef] class Config: schema_extra = { @@ -42,7 +53,11 @@ item_schema = { "name": { "title": "Name", "type": "string", - } + }, + "description": { + "title": "Description", + "type": ["string", "null"] if PYDANTIC_V2 else "string", + }, }, } @@ -57,4 +72,4 @@ def test_response(): # For coverage response = client.get("/foo") assert response.status_code == 200, response.text - assert response.json() == {"name": "Foo item"} + assert response.json() == {"name": "Foo item", "description": None} diff --git a/tests/test_openapi_schema_type.py b/tests/test_openapi_schema_type.py new file mode 100644 index 000000000..a45ea20c8 --- /dev/null +++ b/tests/test_openapi_schema_type.py @@ -0,0 +1,26 @@ +from typing import List, Optional, Union + +import pytest +from fastapi.openapi.models import Schema, SchemaType + + +@pytest.mark.parametrize( + "type_value", + [ + "array", + ["string", "null"], + None, + ], +) +def test_allowed_schema_type( + type_value: Optional[Union[SchemaType, List[SchemaType]]], +) -> None: + """Test that Schema accepts SchemaType, List[SchemaType] and None for type field.""" + schema = Schema(type=type_value) + assert schema.type == type_value + + +def test_invalid_type_value() -> None: + """Test that Schema raises ValueError for invalid type values.""" + with pytest.raises(ValueError, match="2 validation errors for Schema"): + Schema(type=True) # type: ignore[arg-type] From 60213f5a31f9af8685d6dc33c547c0828d2bbcab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 17:47:45 +0000 Subject: [PATCH 420/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c8776890e..44a71b436 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Features +* ✨ Allow array values for OpenAPI schema `type` field. PR [#13639](https://github.com/fastapi/fastapi/pull/13639) by [@sammasak](https://github.com/sammasak). * ✨ Add OpenAPI `external_docs` parameter to `FastAPI`. PR [#13713](https://github.com/fastapi/fastapi/pull/13713) by [@cmtoro](https://github.com/cmtoro). ### Fixes From cd2e1e43bd6d6e1cb7226c8210191e1b55cd0e6a Mon Sep 17 00:00:00 2001 From: Marcelo Trylesinski Date: Sat, 20 Sep 2025 19:49:27 +0200 Subject: [PATCH 421/455] =?UTF-8?q?=F0=9F=93=9D=20Add=20note=20about=20Coo?= =?UTF-8?q?kies=20and=20JavaScript=20on=20`tutorial/cookie-params.md`=20(#?= =?UTF-8?q?13510)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: svlandeg --- docs/en/docs/tutorial/cookie-params.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/en/docs/tutorial/cookie-params.md b/docs/en/docs/tutorial/cookie-params.md index 7680f21f4..f44fd41bd 100644 --- a/docs/en/docs/tutorial/cookie-params.md +++ b/docs/en/docs/tutorial/cookie-params.md @@ -30,6 +30,16 @@ To declare cookies, you need to use `Cookie`, because otherwise the parameters w /// +/// info + +Have in mind that, as **browsers handle cookies** in special ways and behind the scenes, they **don't** easily allow **JavaScript** to touch them. + +If you go to the **API docs UI** at `/docs` you will be able to see the **documentation** for cookies for your *path operations*. + +But even if you **fill the data** and click "Execute", because the docs UI works with **JavaScript**, the cookies won't be sent, and you will see an **error** message as if you didn't write any values. + +/// + ## Recap { #recap } Declare cookies with `Cookie`, using the same common pattern as `Query` and `Path`. From 606a6828e713399ee8ee833d45add202081f90e0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 17:49:50 +0000 Subject: [PATCH 422/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 44a71b436..5dd17a263 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -29,6 +29,7 @@ hide: ### Docs +* 📝 Add note about Cookies and JavaScript on `tutorial/cookie-params.md`. PR [#13510](https://github.com/fastapi/fastapi/pull/13510) by [@Kludex](https://github.com/Kludex). * 📝 Remove outdated formatting from `path-params-numeric-validations.md` for languages `en`, `es` and `uk`.. PR [#14059](https://github.com/fastapi/fastapi/pull/14059) by [@svlandeg](https://github.com/svlandeg). * 📝 Fix and Improve English Documentation. PR [#14048](https://github.com/fastapi/fastapi/pull/14048) by [@nilslindemann](https://github.com/nilslindemann). From 2dc769b12174b0f7ad5c2ac16419fc4027ad8372 Mon Sep 17 00:00:00 2001 From: Salim Aboubacar Date: Sat, 20 Sep 2025 19:57:18 +0200 Subject: [PATCH 423/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20`jsonable=5Fencode?= =?UTF-8?q?r`=20alters=20`json=5Fencoders`=20of=20Pydantic=20v1=20objects?= =?UTF-8?q?=20(#4972)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez Co-authored-by: Yurii Motov --- fastapi/encoders.py | 2 +- tests/test_jsonable_encoder.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 0ad548b94..b037f8bb5 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -219,7 +219,7 @@ def jsonable_encoder( if not PYDANTIC_V2: encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined] if custom_encoder: - encoders.update(custom_encoder) + encoders = {**encoders, **custom_encoder} obj_dict = _model_dump( obj, mode="json", diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index 1906d6bf1..447c5b4d6 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -216,9 +216,12 @@ def test_custom_encoders(): instance = MyModel(dt_field=safe_datetime.now()) encoded_instance = jsonable_encoder( - instance, custom_encoder={safe_datetime: lambda o: o.isoformat()} + instance, custom_encoder={safe_datetime: lambda o: o.strftime("%H:%M:%S")} ) - assert encoded_instance["dt_field"] == instance.dt_field.isoformat() + assert encoded_instance["dt_field"] == instance.dt_field.strftime("%H:%M:%S") + + encoded_instance2 = jsonable_encoder(instance) + assert encoded_instance2["dt_field"] == instance.dt_field.isoformat() def test_custom_enum_encoders(): From 03123c00f1a91586b3db7f379ac69b359fa002e1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 17:57:42 +0000 Subject: [PATCH 424/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5dd17a263..fb8c901be 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Fixes +* 🐛 Fix `jsonable_encoder` alters `json_encoders` of Pydantic v1 objects. PR [#4972](https://github.com/fastapi/fastapi/pull/4972) by [@aboubacs](https://github.com/aboubacs). * 🐛 Reenable `allow_arbitrary_types` when only 1 argument is used on the API endpoint. PR [#13694](https://github.com/fastapi/fastapi/pull/13694) by [@rmawatson](https://github.com/rmawatson). * 🐛 Fix `inspect.getcoroutinefunction()` can break testing with `unittest.mock.patch()`. PR [#14022](https://github.com/fastapi/fastapi/pull/14022) by [@secrett2633](https://github.com/secrett2633). From 86e515784dd6ac6beaa1d0cc4c696c15d645cd41 Mon Sep 17 00:00:00 2001 From: Max McLennan Date: Sat, 20 Sep 2025 13:10:37 -0500 Subject: [PATCH 425/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20inconsistent=20pro?= =?UTF-8?q?cessing=20of=20model=20docstring=20formfeed=20char=20with=20Pyd?= =?UTF-8?q?antic=20V1=20(#6039)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Yurii Motov Co-authored-by: Sebastián Ramírez --- fastapi/_compat.py | 3 +- ...t_get_model_definitions_formfeed_escape.py | 180 ++++++++++++++++++ 2 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 tests/test_get_model_definitions_formfeed_escape.py diff --git a/fastapi/_compat.py b/fastapi/_compat.py index 227ad837d..26b6638c8 100644 --- a/fastapi/_compat.py +++ b/fastapi/_compat.py @@ -393,9 +393,10 @@ else: ) definitions.update(m_definitions) model_name = model_name_map[model] + definitions[model_name] = m_schema + for m_schema in definitions.values(): if "description" in m_schema: m_schema["description"] = m_schema["description"].split("\f")[0] - definitions[model_name] = m_schema return definitions def is_pv1_scalar_field(field: ModelField) -> bool: diff --git a/tests/test_get_model_definitions_formfeed_escape.py b/tests/test_get_model_definitions_formfeed_escape.py new file mode 100644 index 000000000..f77195dc5 --- /dev/null +++ b/tests/test_get_model_definitions_formfeed_escape.py @@ -0,0 +1,180 @@ +from typing import Any, Iterator, Set, Type + +import fastapi._compat +import fastapi.openapi.utils +import pydantic.schema +import pytest +from fastapi import FastAPI +from pydantic import BaseModel +from starlette.testclient import TestClient + +from .utils import needs_pydanticv1 + + +class Address(BaseModel): + """ + This is a public description of an Address + \f + You can't see this part of the docstring, it's private! + """ + + line_1: str + city: str + state_province: str + + +class Facility(BaseModel): + id: str + address: Address + + +app = FastAPI() + +client = TestClient(app) + + +@app.get("/facilities/{facility_id}") +def get_facility(facility_id: str) -> Facility: ... + + +openapi_schema = { + "components": { + "schemas": { + "Address": { + # NOTE: the description of this model shows only the public-facing text, before the `\f` in docstring + "description": "This is a public description of an Address\n", + "properties": { + "city": {"title": "City", "type": "string"}, + "line_1": {"title": "Line 1", "type": "string"}, + "state_province": {"title": "State Province", "type": "string"}, + }, + "required": ["line_1", "city", "state_province"], + "title": "Address", + "type": "object", + }, + "Facility": { + "properties": { + "address": {"$ref": "#/components/schemas/Address"}, + "id": {"title": "Id", "type": "string"}, + }, + "required": ["id", "address"], + "title": "Facility", + "type": "object", + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": {"$ref": "#/components/schemas/ValidationError"}, + "title": "Detail", + "type": "array", + } + }, + "title": "HTTPValidationError", + "type": "object", + }, + "ValidationError": { + "properties": { + "loc": { + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + "title": "Location", + "type": "array", + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + "required": ["loc", "msg", "type"], + "title": "ValidationError", + "type": "object", + }, + } + }, + "info": {"title": "FastAPI", "version": "0.1.0"}, + "openapi": "3.1.0", + "paths": { + "/facilities/{facility_id}": { + "get": { + "operationId": "get_facility_facilities__facility_id__get", + "parameters": [ + { + "in": "path", + "name": "facility_id", + "required": True, + "schema": {"title": "Facility Id", "type": "string"}, + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Facility"} + } + }, + "description": "Successful Response", + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + "description": "Validation Error", + }, + }, + "summary": "Get Facility", + } + } + }, +} + + +def test_openapi_schema(): + """ + Sanity check to ensure our app's openapi schema renders as we expect + """ + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == openapi_schema + + +class SortedTypeSet(set): + """ + Set of Types whose `__iter__()` method yields results sorted by the type names + """ + + def __init__(self, seq: Set[Type[Any]], *, sort_reversed: bool): + super().__init__(seq) + self.sort_reversed = sort_reversed + + def __iter__(self) -> Iterator[Type[Any]]: + members_sorted = sorted( + super().__iter__(), + key=lambda type_: type_.__name__, + reverse=self.sort_reversed, + ) + yield from members_sorted + + +@needs_pydanticv1 +@pytest.mark.parametrize("sort_reversed", [True, False]) +def test_model_description_escaped_with_formfeed(sort_reversed: bool): + """ + Regression test for bug fixed by https://github.com/fastapi/fastapi/pull/6039. + + Test `get_model_definitions` with models passed in different order. + """ + all_fields = fastapi.openapi.utils.get_fields_from_routes(app.routes) + + flat_models = fastapi._compat.get_flat_models_from_fields( + all_fields, known_models=set() + ) + model_name_map = pydantic.schema.get_model_name_map(flat_models) + + expected_address_description = "This is a public description of an Address\n" + + models = fastapi._compat.get_model_definitions( + flat_models=SortedTypeSet(flat_models, sort_reversed=sort_reversed), + model_name_map=model_name_map, + ) + assert models["Address"]["description"] == expected_address_description From 0bdc3ca3732e3742e094bea2b320e9774659ac38 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 18:10:57 +0000 Subject: [PATCH 426/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fb8c901be..8489e296c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -14,6 +14,7 @@ hide: ### Fixes +* 🐛 Fix inconsistent processing of model docstring formfeed char with Pydantic V1. PR [#6039](https://github.com/fastapi/fastapi/pull/6039) by [@MaxwellPayne](https://github.com/MaxwellPayne). * 🐛 Fix `jsonable_encoder` alters `json_encoders` of Pydantic v1 objects. PR [#4972](https://github.com/fastapi/fastapi/pull/4972) by [@aboubacs](https://github.com/aboubacs). * 🐛 Reenable `allow_arbitrary_types` when only 1 argument is used on the API endpoint. PR [#13694](https://github.com/fastapi/fastapi/pull/13694) by [@rmawatson](https://github.com/rmawatson). * 🐛 Fix `inspect.getcoroutinefunction()` can break testing with `unittest.mock.patch()`. PR [#14022](https://github.com/fastapi/fastapi/pull/14022) by [@secrett2633](https://github.com/secrett2633). From b51ec36f2e442495de5e4c22ae51a8f5c44917eb Mon Sep 17 00:00:00 2001 From: Robert Hofer <1058012+hofrob@users.noreply.github.com> Date: Sat, 20 Sep 2025 20:44:43 +0200 Subject: [PATCH 427/455] =?UTF-8?q?=E2=9C=A8=20=20Allow=20`None`=20as=20re?= =?UTF-8?q?turn=20type=20for=20bodiless=20responses=20(#9425)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- fastapi/dependencies/utils.py | 2 ++ .../test_return_none_stringified_annotations.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/test_return_none_stringified_annotations.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 8dd0a14c8..dc663f548 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -254,6 +254,8 @@ def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any: if isinstance(annotation, str): annotation = ForwardRef(annotation) annotation = evaluate_forwardref(annotation, globalns, globalns) + if annotation is type(None): + return None return annotation diff --git a/tests/test_return_none_stringified_annotations.py b/tests/test_return_none_stringified_annotations.py new file mode 100644 index 000000000..be052d532 --- /dev/null +++ b/tests/test_return_none_stringified_annotations.py @@ -0,0 +1,17 @@ +import http + +from fastapi import FastAPI +from fastapi.testclient import TestClient + + +def test_no_content(): + app = FastAPI() + + @app.get("/no-content", status_code=http.HTTPStatus.NO_CONTENT) + def return_no_content() -> "None": + return + + client = TestClient(app) + response = client.get("/no-content") + assert response.status_code == http.HTTPStatus.NO_CONTENT, response.text + assert not response.content From b01d5c97a09b8f4f95b9e9b0d6bc083a23cdea20 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 18:45:09 +0000 Subject: [PATCH 428/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 8489e296c..3632dac32 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Features +* ✨ Allow `None` as return type for bodiless responses. PR [#9425](https://github.com/fastapi/fastapi/pull/9425) by [@hofrob](https://github.com/hofrob). * ✨ Allow array values for OpenAPI schema `type` field. PR [#13639](https://github.com/fastapi/fastapi/pull/13639) by [@sammasak](https://github.com/sammasak). * ✨ Add OpenAPI `external_docs` parameter to `FastAPI`. PR [#13713](https://github.com/fastapi/fastapi/pull/13713) by [@cmtoro](https://github.com/cmtoro). From f1e6f978ce10a6f9b4c668350a79462e9ac330a8 Mon Sep 17 00:00:00 2001 From: vvanglro <947001731@qq.com> Date: Sun, 21 Sep 2025 02:51:40 +0800 Subject: [PATCH 429/455] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Fix=20`default=5Ff?= =?UTF-8?q?actory`=20for=20response=20model=20field=20with=20Pydantic=20V1?= =?UTF-8?q?=20(#9704)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- fastapi/utils.py | 1 + tests/test_response_model_default_factory.py | 47 ++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/test_response_model_default_factory.py diff --git a/fastapi/utils.py b/fastapi/utils.py index 4c7350fea..98725ff19 100644 --- a/fastapi/utils.py +++ b/fastapi/utils.py @@ -137,6 +137,7 @@ def create_cloned_field( new_field.alias = field.alias # type: ignore[misc] new_field.class_validators = field.class_validators # type: ignore[attr-defined] new_field.default = field.default # type: ignore[misc] + new_field.default_factory = field.default_factory # type: ignore[attr-defined] new_field.required = field.required # type: ignore[misc] new_field.model_config = field.model_config # type: ignore[attr-defined] new_field.field_info = field.field_info diff --git a/tests/test_response_model_default_factory.py b/tests/test_response_model_default_factory.py new file mode 100644 index 000000000..13c1f442b --- /dev/null +++ b/tests/test_response_model_default_factory.py @@ -0,0 +1,47 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel, Field + +app = FastAPI() + + +class ResponseModel(BaseModel): + code: int = 200 + message: str = Field(default_factory=lambda: "Successful operation.") + + +@app.get( + "/response_model_has_default_factory_return_dict", + response_model=ResponseModel, +) +async def response_model_has_default_factory_return_dict(): + return {"code": 200} + + +@app.get( + "/response_model_has_default_factory_return_model", + response_model=ResponseModel, +) +async def response_model_has_default_factory_return_model(): + return ResponseModel() + + +client = TestClient(app) + + +def test_response_model_has_default_factory_return_dict(): + response = client.get("/response_model_has_default_factory_return_dict") + + assert response.status_code == 200, response.text + + assert response.json()["code"] == 200 + assert response.json()["message"] == "Successful operation." + + +def test_response_model_has_default_factory_return_model(): + response = client.get("/response_model_has_default_factory_return_model") + + assert response.status_code == 200, response.text + + assert response.json()["code"] == 200 + assert response.json()["message"] == "Successful operation." From a7f2dbe976bf72703376f0cd04487bfc4a849f83 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 18:52:02 +0000 Subject: [PATCH 430/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3632dac32..d70b4e8ab 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -15,6 +15,7 @@ hide: ### Fixes +* ⚡️ Fix `default_factory` for response model field with Pydantic V1. PR [#9704](https://github.com/fastapi/fastapi/pull/9704) by [@vvanglro](https://github.com/vvanglro). * 🐛 Fix inconsistent processing of model docstring formfeed char with Pydantic V1. PR [#6039](https://github.com/fastapi/fastapi/pull/6039) by [@MaxwellPayne](https://github.com/MaxwellPayne). * 🐛 Fix `jsonable_encoder` alters `json_encoders` of Pydantic v1 objects. PR [#4972](https://github.com/fastapi/fastapi/pull/4972) by [@aboubacs](https://github.com/aboubacs). * 🐛 Reenable `allow_arbitrary_types` when only 1 argument is used on the API endpoint. PR [#13694](https://github.com/fastapi/fastapi/pull/13694) by [@rmawatson](https://github.com/rmawatson). From 382d083e26a28e95c731e85345c85c6dc99b08b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Sep 2025 21:34:05 +0200 Subject: [PATCH 431/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?7.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d70b4e8ab..6adfe5346 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.117.0 + ### Features * ✨ Allow `None` as return type for bodiless responses. PR [#9425](https://github.com/fastapi/fastapi/pull/9425) by [@hofrob](https://github.com/hofrob). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 9342f1add..d51e727d2 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.116.2" +__version__ = "0.117.0" from starlette import status as status From a84001000e59ff362e74f93b8d9a58a4309dac2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Sep 2025 21:35:43 +0200 Subject: [PATCH 432/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 6adfe5346..2dd8c9b99 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -29,10 +29,6 @@ hide: * ✅ Enable test case for duplicated headers in `test_tutorial/test_header_params/test_tutorial003.py`. PR [#13864](https://github.com/fastapi/fastapi/pull/13864) by [@Amogha-ark](https://github.com/Amogha-ark). * 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). -### Upgrades - -* ⬆️ Update mypy to 1.14.1. PR [#12970](https://github.com/fastapi/fastapi/pull/12970) by [@tamird](https://github.com/tamird). - ### Docs * 📝 Add note about Cookies and JavaScript on `tutorial/cookie-params.md`. PR [#13510](https://github.com/fastapi/fastapi/pull/13510) by [@Kludex](https://github.com/Kludex). @@ -50,6 +46,7 @@ hide: * ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). * 🔨 Update translations script. PR [#13968](https://github.com/fastapi/fastapi/pull/13968) by [@YuriiMotov](https://github.com/YuriiMotov). * 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆️ Update mypy to 1.14.1. PR [#12970](https://github.com/fastapi/fastapi/pull/12970) by [@tamird](https://github.com/tamird). ## 0.116.2 From 44fc67632bcdae4d078cb11b1a319ac122cbb06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=89VEIL?= Date: Sat, 20 Sep 2025 21:55:59 +0200 Subject: [PATCH 433/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20validation=20error?= =?UTF-8?q?=20when=20`File`=20is=20declared=20after=20`Form`=20parameter?= =?UTF-8?q?=20(#11194)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sebastián Ramírez --- fastapi/dependencies/utils.py | 7 +- tests/test_file_and_form_order_issue_9116.py | 90 ++++++++++++++++++++ 2 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 tests/test_file_and_form_order_issue_9116.py diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index dc663f548..e49380cb3 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -872,20 +872,19 @@ async def _extract_form_body( received_body: FormData, ) -> Dict[str, Any]: values = {} - first_field = body_fields[0] - first_field_info = first_field.field_info for field in body_fields: value = _get_multidict_value(field, received_body) + field_info = field.field_info if ( - isinstance(first_field_info, params.File) + isinstance(field_info, params.File) and is_bytes_field(field) and isinstance(value, UploadFile) ): value = await value.read() elif ( is_bytes_sequence_field(field) - and isinstance(first_field_info, params.File) + and isinstance(field_info, params.File) and value_is_sequence(value) ): # For types diff --git a/tests/test_file_and_form_order_issue_9116.py b/tests/test_file_and_form_order_issue_9116.py new file mode 100644 index 000000000..cb9a31d31 --- /dev/null +++ b/tests/test_file_and_form_order_issue_9116.py @@ -0,0 +1,90 @@ +""" +Regression test, Error 422 if Form is declared before File +See https://github.com/tiangolo/fastapi/discussions/9116 +""" + +from pathlib import Path +from typing import List + +import pytest +from fastapi import FastAPI, File, Form +from fastapi.testclient import TestClient +from typing_extensions import Annotated + +app = FastAPI() + + +@app.post("/file_before_form") +def file_before_form( + file: bytes = File(), + city: str = Form(), +): + return {"file_content": file, "city": city} + + +@app.post("/file_after_form") +def file_after_form( + city: str = Form(), + file: bytes = File(), +): + return {"file_content": file, "city": city} + + +@app.post("/file_list_before_form") +def file_list_before_form( + files: Annotated[List[bytes], File()], + city: Annotated[str, Form()], +): + return {"file_contents": files, "city": city} + + +@app.post("/file_list_after_form") +def file_list_after_form( + city: Annotated[str, Form()], + files: Annotated[List[bytes], File()], +): + return {"file_contents": files, "city": city} + + +client = TestClient(app) + + +@pytest.fixture +def tmp_file_1(tmp_path: Path) -> Path: + f = tmp_path / "example1.txt" + f.write_text("foo") + return f + + +@pytest.fixture +def tmp_file_2(tmp_path: Path) -> Path: + f = tmp_path / "example2.txt" + f.write_text("bar") + return f + + +@pytest.mark.parametrize("endpoint_path", ("/file_before_form", "/file_after_form")) +def test_file_form_order(endpoint_path: str, tmp_file_1: Path): + response = client.post( + url=endpoint_path, + data={"city": "Thimphou"}, + files={"file": (tmp_file_1.name, tmp_file_1.read_bytes())}, + ) + assert response.status_code == 200, response.text + assert response.json() == {"file_content": "foo", "city": "Thimphou"} + + +@pytest.mark.parametrize( + "endpoint_path", ("/file_list_before_form", "/file_list_after_form") +) +def test_file_list_form_order(endpoint_path: str, tmp_file_1: Path, tmp_file_2: Path): + response = client.post( + url=endpoint_path, + data={"city": "Thimphou"}, + files=( + ("files", (tmp_file_1.name, tmp_file_1.read_bytes())), + ("files", (tmp_file_2.name, tmp_file_2.read_bytes())), + ), + ) + assert response.status_code == 200, response.text + assert response.json() == {"file_contents": ["foo", "bar"], "city": "Thimphou"} From b5c05893b4c43c93ff94761270ea750c0bd9e30e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Sep 2025 19:56:30 +0000 Subject: [PATCH 434/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 2dd8c9b99..82e4167ef 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Fix validation error when `File` is declared after `Form` parameter. PR [#11194](https://github.com/fastapi/fastapi/pull/11194) by [@thomasleveil](https://github.com/thomasleveil). + ## 0.117.0 ### Features From 784f06cb9b7cc63f6a0cb2bc9cf238473eef93e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 20 Sep 2025 22:15:41 +0200 Subject: [PATCH 435/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?7.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 82e4167ef..25744044e 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.117.1 + ### Fixes * 🐛 Fix validation error when `File` is declared after `Form` parameter. PR [#11194](https://github.com/fastapi/fastapi/pull/11194) by [@thomasleveil](https://github.com/thomasleveil). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index d51e727d2..986fd200c 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.117.0" +__version__ = "0.117.1" from starlette import status as status From 2eca83fbda143678648934a787cf78f2410edd8b Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Sun, 21 Sep 2025 13:29:04 +0200 Subject: [PATCH 436/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20contributing=20?= =?UTF-8?q?guidelines=20for=20installing=20requirements=20(#14095)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/contributing.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 2583fd1fb..ae99059f4 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -10,10 +10,12 @@ If you already cloned the
`uv`: + +
+ +```console +$ uv pip install -r requirements.txt + +---> 100% +``` + +
+ +//// + It will install all the dependencies and your local FastAPI in your local environment. ### Using your local FastAPI From 8dfc651e1a2fa669bde1b9173805d8e4f2e5e7bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Sep 2025 11:29:24 +0000 Subject: [PATCH 437/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 25744044e..33abe86d2 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Docs + +* 📝 Update contributing guidelines for installing requirements. PR [#14095](https://github.com/fastapi/fastapi/pull/14095) by [@alejsdev](https://github.com/alejsdev). + ## 0.117.1 ### Fixes From 40f3ab18e078ff4c809f3ca63851673bba435a5b Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Sun, 21 Sep 2025 14:54:15 +0200 Subject: [PATCH 438/455] =?UTF-8?q?=F0=9F=90=9B=20Hide=20sponsor=20badge?= =?UTF-8?q?=20when=20sponsor=20image=20is=20not=20displayed=20(#14096)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/css/custom.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index b192f6123..05bfd0fe8 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -124,6 +124,11 @@ a.announce-link:hover { border-radius: 20px; } +/* Hide .sponsor-badge when .sponsor-image is display none */ +.announce-wrapper a:has(.sponsor-image[style*="display: none"]) .sponsor-badge { + display: none; +} + .announce-wrapper>div { min-height: 40px; display: flex; From 6b1e6c5efd6a708ba978c092e368d3dd18cfc542 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Sep 2025 12:54:37 +0000 Subject: [PATCH 439/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 33abe86d2..b68214d40 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📝 Update contributing guidelines for installing requirements. PR [#14095](https://github.com/fastapi/fastapi/pull/14095) by [@alejsdev](https://github.com/alejsdev). +### Internal + +* 🐛 Hide sponsor badge when sponsor image is not displayed. PR [#14096](https://github.com/fastapi/fastapi/pull/14096) by [@alejsdev](https://github.com/alejsdev). + ## 0.117.1 ### Fixes From f97524429d0062bede9158ecdf4cefeee3b47a61 Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Sun, 21 Sep 2025 16:11:11 +0200 Subject: [PATCH 440/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20sponsor=20display?= =?UTF-8?q?=20issue=20by=20hiding=20element=20on=20image=20error=20(#14097?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/css/custom.css | 5 ----- docs/en/docs/js/custom.js | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index 05bfd0fe8..b192f6123 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -124,11 +124,6 @@ a.announce-link:hover { border-radius: 20px; } -/* Hide .sponsor-badge when .sponsor-image is display none */ -.announce-wrapper a:has(.sponsor-image[style*="display: none"]) .sponsor-badge { - display: none; -} - .announce-wrapper>div { min-height: 40px; display: flex; diff --git a/docs/en/docs/js/custom.js b/docs/en/docs/js/custom.js index 4c0ada312..425b7fce7 100644 --- a/docs/en/docs/js/custom.js +++ b/docs/en/docs/js/custom.js @@ -135,10 +135,28 @@ async function showRandomAnnouncement(groupId, timeInterval) { } } +function hideSponsorOnImageError() { + const sponsorImages = document.querySelectorAll('.sponsor-image'); + const announceRight = document.getElementById('announce-right'); + + function hideAnnounceRight() { + if (announceRight) { + announceRight.style.display = 'none'; + } + } + + sponsorImages.forEach(function(img) { + img.addEventListener('error', function() { + hideAnnounceRight(); + }); + }); +} + async function main() { setupTermynal(); showRandomAnnouncement('announce-left', 5000) showRandomAnnouncement('announce-right', 10000) + hideSponsorOnImageError(); } document$.subscribe(() => { main() From f0da082dd3532384b2037bda7322eb9c33effa5f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Sep 2025 14:11:44 +0000 Subject: [PATCH 441/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index b68214d40..4f296c7b7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* 🐛 Fix sponsor display issue by hiding element on image error. PR [#14097](https://github.com/fastapi/fastapi/pull/14097) by [@alejsdev](https://github.com/alejsdev). * 🐛 Hide sponsor badge when sponsor image is not displayed. PR [#14096](https://github.com/fastapi/fastapi/pull/14096) by [@alejsdev](https://github.com/alejsdev). ## 0.117.1 From 81708603229951041eadb2437ce4aa810ef6898a Mon Sep 17 00:00:00 2001 From: Alejandra <90076947+alejsdev@users.noreply.github.com> Date: Mon, 22 Sep 2025 17:11:52 +0200 Subject: [PATCH 442/455] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20sponsor?= =?UTF-8?q?=20image=20handling=20(#14102)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/en/docs/css/custom.css | 12 ++++++++++-- docs/en/docs/js/custom.js | 39 +++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css index b192f6123..a38df772f 100644 --- a/docs/en/docs/css/custom.css +++ b/docs/en/docs/css/custom.css @@ -102,7 +102,15 @@ a.announce-link:hover { align-items: center; } -.announce-wrapper div.item { +.announce-wrapper #announce-left div.item { + display: none; +} + +.announce-wrapper #announce-right { + display: none; +} + +.announce-wrapper #announce-right div.item { display: none; } @@ -112,7 +120,7 @@ a.announce-link:hover { top: -10px; right: 0; font-size: 0.5rem; - color: #999; + color: #e6e6e6; background-color: #666; border-radius: 10px; padding: 0 10px; diff --git a/docs/en/docs/js/custom.js b/docs/en/docs/js/custom.js index 425b7fce7..48e95901d 100644 --- a/docs/en/docs/js/custom.js +++ b/docs/en/docs/js/custom.js @@ -135,28 +135,43 @@ async function showRandomAnnouncement(groupId, timeInterval) { } } -function hideSponsorOnImageError() { - const sponsorImages = document.querySelectorAll('.sponsor-image'); +function handleSponsorImages() { const announceRight = document.getElementById('announce-right'); + if(!announceRight) return; - function hideAnnounceRight() { - if (announceRight) { - announceRight.style.display = 'none'; - } - } + const sponsorImages = document.querySelectorAll('.sponsor-image'); - sponsorImages.forEach(function(img) { - img.addEventListener('error', function() { - hideAnnounceRight(); + const imagePromises = Array.from(sponsorImages).map(img => { + return new Promise((resolve, reject) => { + if (img.complete && img.naturalHeight !== 0) { + resolve(); + } else { + img.addEventListener('load', () => { + if (img.naturalHeight !== 0) { + resolve(); + } else { + reject(); + } + }); + img.addEventListener('error', reject); + } }); }); + + Promise.all(imagePromises) + .then(() => { + announceRight.style.display = 'block'; + showRandomAnnouncement('announce-right', 10000); + }) + .catch(() => { + // do nothing + }); } async function main() { setupTermynal(); showRandomAnnouncement('announce-left', 5000) - showRandomAnnouncement('announce-right', 10000) - hideSponsorOnImageError(); + handleSponsorImages(); } document$.subscribe(() => { main() From 9aa25fd6822de7504c739c4c2f3565627594353d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 22 Sep 2025 15:12:21 +0000 Subject: [PATCH 443/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 4f296c7b7..34b0a2886 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ♻️ Refactor sponsor image handling. PR [#14102](https://github.com/fastapi/fastapi/pull/14102) by [@alejsdev](https://github.com/alejsdev). * 🐛 Fix sponsor display issue by hiding element on image error. PR [#14097](https://github.com/fastapi/fastapi/pull/14097) by [@alejsdev](https://github.com/alejsdev). * 🐛 Hide sponsor badge when sponsor image is not displayed. PR [#14096](https://github.com/fastapi/fastapi/pull/14096) by [@alejsdev](https://github.com/alejsdev). From b40da4f0d54aa6a3bc4a0048016d7f20d1ba0560 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 21:30:27 +0200 Subject: [PATCH 444/455] =?UTF-8?q?=E2=AC=86=20[pre-commit.ci]=20pre-commi?= =?UTF-8?q?t=20autoupdate=20(#14103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.13.0 → v0.13.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.0...v0.13.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 94016ad31..8b24c8c0c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.13.0 + rev: v0.13.1 hooks: - id: ruff args: From f23550223475e0e173ef63b0d54236fc105a8867 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 22 Sep 2025 19:30:48 +0000 Subject: [PATCH 445/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 34b0a2886..1dd99a377 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -13,6 +13,7 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14103](https://github.com/fastapi/fastapi/pull/14103) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * ♻️ Refactor sponsor image handling. PR [#14102](https://github.com/fastapi/fastapi/pull/14102) by [@alejsdev](https://github.com/alejsdev). * 🐛 Fix sponsor display issue by hiding element on image error. PR [#14097](https://github.com/fastapi/fastapi/pull/14097) by [@alejsdev](https://github.com/alejsdev). * 🐛 Hide sponsor badge when sponsor image is not displayed. PR [#14096](https://github.com/fastapi/fastapi/pull/14096) by [@alejsdev](https://github.com/alejsdev). From cca3341cb93cb4d0267dd8e862db9235aeaac11c Mon Sep 17 00:00:00 2001 From: Nils-Hero Lindemann Date: Wed, 24 Sep 2025 10:10:28 +0200 Subject: [PATCH 446/455] =?UTF-8?q?=F0=9F=8C=90=20Sync=20German=20docs=20(?= =?UTF-8?q?#14098)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Sync German docs with #13510 * Sync German docs with #14059 --------- Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> --- docs/de/docs/tutorial/cookie-params.md | 10 ++++++++++ .../docs/tutorial/path-params-numeric-validations.md | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/de/docs/tutorial/cookie-params.md b/docs/de/docs/tutorial/cookie-params.md index 9f50c7ae5..81a753211 100644 --- a/docs/de/docs/tutorial/cookie-params.md +++ b/docs/de/docs/tutorial/cookie-params.md @@ -30,6 +30,16 @@ Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da die Parameter sons /// +/// info | Info + +Beachten Sie, dass **Browser Cookies auf besondere Weise und hinter den Kulissen handhaben** und **JavaScript** **nicht** ohne Weiteres erlauben, auf sie zuzugreifen. + +Wenn Sie zur **API-Dokumentations-UI** unter `/docs` gehen, können Sie die **Dokumentation** zu Cookies für Ihre *Pfadoperationen* sehen. + +Aber selbst wenn Sie die **Daten ausfüllen** und auf „Execute“ klicken, da die Dokumentations-UI mit **JavaScript** arbeitet, werden die Cookies nicht gesendet, und Sie sehen eine **Fehler**-Meldung, als hätten Sie keine Werte eingegeben. + +/// + ## Zusammenfassung { #recap } Deklarieren Sie Cookies mit `Cookie` und verwenden Sie dabei das gleiche allgemeine Muster wie bei `Query` und `Path`. diff --git a/docs/de/docs/tutorial/path-params-numeric-validations.md b/docs/de/docs/tutorial/path-params-numeric-validations.md index 36f466059..5b7474944 100644 --- a/docs/de/docs/tutorial/path-params-numeric-validations.md +++ b/docs/de/docs/tutorial/path-params-numeric-validations.md @@ -54,18 +54,8 @@ Für **FastAPI** spielt es keine Rolle. Es erkennt die Parameter anhand ihrer Na Sie können Ihre Funktion also so deklarieren: -//// tab | Python 3.8 nicht annotiert - -/// tip | Tipp - -Bevorzugen Sie die `Annotated`-Version, falls möglich. - -/// - {* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} -//// - Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da es nicht darauf ankommt, dass Sie keine Funktionsparameter-Defaultwerte für `Query()` oder `Path()` verwenden. {* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} From 287eb316df5b7c35dd1e5da27ca2a8d345bee8d1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 24 Sep 2025 08:10:57 +0000 Subject: [PATCH 447/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1dd99a377..c1e701877 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: * 📝 Update contributing guidelines for installing requirements. PR [#14095](https://github.com/fastapi/fastapi/pull/14095) by [@alejsdev](https://github.com/alejsdev). +### Translations + +* 🌐 Sync German docs. PR [#14098](https://github.com/fastapi/fastapi/pull/14098) by [@nilslindemann](https://github.com/nilslindemann). + ### Internal * ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14103](https://github.com/fastapi/fastapi/pull/14103) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). From 3eb2ee7510905447a36abe628708f102e09cfa59 Mon Sep 17 00:00:00 2001 From: alv2017 Date: Thu, 25 Sep 2025 09:45:24 +0300 Subject: [PATCH 448/455] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typos=20in?= =?UTF-8?q?=20OAuth2=20password=20request=20forms=20(#14112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed typos in OAuth2PasswordRequestForm and in OAuth2PasswordRequestFormStrict --- fastapi/security/oauth2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 88e394db1..fdedbc2da 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -89,7 +89,7 @@ class OAuth2PasswordRequestForm: Doc( """ `password` string. The OAuth2 spec requires the exact field name - `password". + `password`. """ ), ], @@ -243,7 +243,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): Doc( """ `password` string. The OAuth2 spec requires the exact field name - `password". + `password`. """ ), ], From 450a334253b1426aab08b4dea17b16ba8b4c098c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 25 Sep 2025 06:45:53 +0000 Subject: [PATCH 449/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index c1e701877..fe1fac8cf 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* ✏️ Fix typos in OAuth2 password request forms. PR [#14112](https://github.com/fastapi/fastapi/pull/14112) by [@alv2017](https://github.com/alv2017). * 📝 Update contributing guidelines for installing requirements. PR [#14095](https://github.com/fastapi/fastapi/pull/14095) by [@alejsdev](https://github.com/alejsdev). ### Translations From efdafa43613f084d198e51f6858e8610beddb5ed Mon Sep 17 00:00:00 2001 From: Neizvestnyj Date: Mon, 29 Sep 2025 05:57:38 +0300 Subject: [PATCH 450/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20`tutorial/secur?= =?UTF-8?q?ity/oauth2-jwt/`=20to=20use=20`pwdlib`=20with=20Argon2=20instea?= =?UTF-8?q?d=20of=20`passlib`=20(#13917)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Sebastián Ramírez --- docs/en/docs/how-to/conditional-openapi.md | 2 +- docs/en/docs/tutorial/security/oauth2-jwt.md | 24 ++++++++++---------- docs_src/security/tutorial004.py | 10 ++++---- docs_src/security/tutorial004_an.py | 10 ++++---- docs_src/security/tutorial004_an_py310.py | 10 ++++---- docs_src/security/tutorial004_an_py39.py | 10 ++++---- docs_src/security/tutorial004_py310.py | 10 ++++---- docs_src/security/tutorial005.py | 12 +++++----- docs_src/security/tutorial005_an.py | 12 +++++----- docs_src/security/tutorial005_an_py310.py | 12 +++++----- docs_src/security/tutorial005_an_py39.py | 12 +++++----- docs_src/security/tutorial005_py310.py | 12 +++++----- docs_src/security/tutorial005_py39.py | 12 +++++----- pyproject.toml | 2 -- requirements-tests.txt | 2 +- 15 files changed, 75 insertions(+), 77 deletions(-) diff --git a/docs/en/docs/how-to/conditional-openapi.md b/docs/en/docs/how-to/conditional-openapi.md index 833123e6a..e5893e584 100644 --- a/docs/en/docs/how-to/conditional-openapi.md +++ b/docs/en/docs/how-to/conditional-openapi.md @@ -17,7 +17,7 @@ If you want to secure your API, there are several better things you can do, for * Make sure you have well defined Pydantic models for your request bodies and responses. * Configure any required permissions and roles using dependencies. * Never store plaintext passwords, only password hashes. -* Implement and use well-known cryptographic tools, like Passlib and JWT tokens, etc. +* Implement and use well-known cryptographic tools, like pwdlib and JWT tokens, etc. * Add more granular permission controls with OAuth2 scopes where needed. * ...etc. diff --git a/docs/en/docs/tutorial/security/oauth2-jwt.md b/docs/en/docs/tutorial/security/oauth2-jwt.md index e9ae0db68..95baf871c 100644 --- a/docs/en/docs/tutorial/security/oauth2-jwt.md +++ b/docs/en/docs/tutorial/security/oauth2-jwt.md @@ -64,20 +64,20 @@ If your database is stolen, the thief won't have your users' plaintext passwords So, the thief won't be able to try to use that password in another system (as many users use the same password everywhere, this would be dangerous). -## Install `passlib` { #install-passlib } +## Install `pwdlib` { #install-pwdlib } -PassLib is a great Python package to handle password hashes. +pwdlib is a great Python package to handle password hashes. It supports many secure hashing algorithms and utilities to work with them. -The recommended algorithm is "Bcrypt". +The recommended algorithm is "Argon2". -Make sure you create a [virtual environment](../../virtual-environments.md){.internal-link target=_blank}, activate it, and then install PassLib with Bcrypt: +Make sure you create a [virtual environment](../../virtual-environments.md){.internal-link target=_blank}, activate it, and then install pwdlib with Argon2:
```console -$ pip install "passlib[bcrypt]" +$ pip install "pwdlib[argon2]" ---> 100% ``` @@ -86,7 +86,7 @@ $ pip install "passlib[bcrypt]" /// tip -With `passlib`, you could even configure it to be able to read passwords created by **Django**, a **Flask** security plug-in or many others. +With `pwdlib`, you could even configure it to be able to read passwords created by **Django**, a **Flask** security plug-in or many others. So, you would be able to, for example, share the same data from a Django application in a database with a FastAPI application. Or gradually migrate a Django application using the same database. @@ -96,15 +96,15 @@ And your users would be able to login from your Django app or from your **FastAP ## Hash and verify the passwords { #hash-and-verify-the-passwords } -Import the tools we need from `passlib`. +Import the tools we need from `pwdlib`. -Create a PassLib "context". This is what will be used to hash and verify passwords. +Create a PasswordHash instance with recommended settings - it will be used for hashing and verifying passwords. /// tip -The PassLib context also has functionality to use different hashing algorithms, including deprecated old ones only to allow verifying them, etc. +pwdlib also supports the bcrypt hashing algorithm but does not include legacy algorithms - for working with outdated hashes, it is recommended to use the passlib library. -For example, you could use it to read and verify passwords generated by another system (like Django) but hash any new passwords with a different algorithm like Bcrypt. +For example, you could use it to read and verify passwords generated by another system (like Django) but hash any new passwords with a different algorithm like Argon2 or Bcrypt. And be compatible with all of them at the same time. @@ -120,7 +120,7 @@ And another one to authenticate and return a user. /// note -If you check the new (fake) database `fake_users_db`, you will see how the hashed password looks like now: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`. +If you check the new (fake) database `fake_users_db`, you will see how the hashed password looks like now: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. /// @@ -264,7 +264,7 @@ Many packages that simplify it a lot have to make many compromises with the data It gives you all the flexibility to choose the ones that fit your project the best. -And you can use directly many well maintained and widely used packages like `passlib` and `PyJWT`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages. +And you can use directly many well maintained and widely used packages like `pwdlib` and `PyJWT`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages. But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security. diff --git a/docs_src/security/tutorial004.py b/docs_src/security/tutorial004.py index 222589618..130dc699a 100644 --- a/docs_src/security/tutorial004.py +++ b/docs_src/security/tutorial004.py @@ -5,7 +5,7 @@ import jwt from fastapi import Depends, FastAPI, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel # to get a string like this run: @@ -20,7 +20,7 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, } } @@ -46,7 +46,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") @@ -54,11 +54,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial004_an.py b/docs_src/security/tutorial004_an.py index e2221cd39..018234e30 100644 --- a/docs_src/security/tutorial004_an.py +++ b/docs_src/security/tutorial004_an.py @@ -5,7 +5,7 @@ import jwt from fastapi import Depends, FastAPI, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel from typing_extensions import Annotated @@ -21,7 +21,7 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, } } @@ -47,7 +47,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") @@ -55,11 +55,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial004_an_py310.py b/docs_src/security/tutorial004_an_py310.py index a3f74fc0e..18ea96bc5 100644 --- a/docs_src/security/tutorial004_an_py310.py +++ b/docs_src/security/tutorial004_an_py310.py @@ -5,7 +5,7 @@ import jwt from fastapi import Depends, FastAPI, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel # to get a string like this run: @@ -20,7 +20,7 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, } } @@ -46,7 +46,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") @@ -54,11 +54,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial004_an_py39.py b/docs_src/security/tutorial004_an_py39.py index b33d677ed..d3fd29e5a 100644 --- a/docs_src/security/tutorial004_an_py39.py +++ b/docs_src/security/tutorial004_an_py39.py @@ -5,7 +5,7 @@ import jwt from fastapi import Depends, FastAPI, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel # to get a string like this run: @@ -20,7 +20,7 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, } } @@ -46,7 +46,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") @@ -54,11 +54,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial004_py310.py b/docs_src/security/tutorial004_py310.py index d46ce26bf..cd1dcff46 100644 --- a/docs_src/security/tutorial004_py310.py +++ b/docs_src/security/tutorial004_py310.py @@ -4,7 +4,7 @@ import jwt from fastapi import Depends, FastAPI, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel # to get a string like this run: @@ -19,7 +19,7 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, } } @@ -45,7 +45,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") @@ -53,11 +53,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial005.py b/docs_src/security/tutorial005.py index 447dacb37..fdd73bcd8 100644 --- a/docs_src/security/tutorial005.py +++ b/docs_src/security/tutorial005.py @@ -9,7 +9,7 @@ from fastapi.security import ( SecurityScopes, ) from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel, ValidationError # to get a string like this run: @@ -24,14 +24,14 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, }, "alice": { "username": "alice", "full_name": "Alice Chains", "email": "alicechains@example.com", - "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", "disabled": True, }, } @@ -58,7 +58,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", @@ -69,11 +69,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial005_an.py b/docs_src/security/tutorial005_an.py index d2c4fe9b8..e1d7b4f62 100644 --- a/docs_src/security/tutorial005_an.py +++ b/docs_src/security/tutorial005_an.py @@ -9,7 +9,7 @@ from fastapi.security import ( SecurityScopes, ) from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel, ValidationError from typing_extensions import Annotated @@ -25,14 +25,14 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, }, "alice": { "username": "alice", "full_name": "Alice Chains", "email": "alicechains@example.com", - "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", "disabled": True, }, } @@ -59,7 +59,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", @@ -70,11 +70,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial005_an_py310.py b/docs_src/security/tutorial005_an_py310.py index e3527370d..df55951c0 100644 --- a/docs_src/security/tutorial005_an_py310.py +++ b/docs_src/security/tutorial005_an_py310.py @@ -9,7 +9,7 @@ from fastapi.security import ( SecurityScopes, ) from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel, ValidationError # to get a string like this run: @@ -24,14 +24,14 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, }, "alice": { "username": "alice", "full_name": "Alice Chains", "email": "alicechains@example.com", - "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", "disabled": True, }, } @@ -58,7 +58,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", @@ -69,11 +69,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial005_an_py39.py b/docs_src/security/tutorial005_an_py39.py index 3dc3140c3..983c1c22c 100644 --- a/docs_src/security/tutorial005_an_py39.py +++ b/docs_src/security/tutorial005_an_py39.py @@ -9,7 +9,7 @@ from fastapi.security import ( SecurityScopes, ) from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel, ValidationError # to get a string like this run: @@ -24,14 +24,14 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, }, "alice": { "username": "alice", "full_name": "Alice Chains", "email": "alicechains@example.com", - "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", "disabled": True, }, } @@ -58,7 +58,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", @@ -69,11 +69,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial005_py310.py b/docs_src/security/tutorial005_py310.py index 3fc15212b..d08e2c59f 100644 --- a/docs_src/security/tutorial005_py310.py +++ b/docs_src/security/tutorial005_py310.py @@ -8,7 +8,7 @@ from fastapi.security import ( SecurityScopes, ) from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel, ValidationError # to get a string like this run: @@ -23,14 +23,14 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, }, "alice": { "username": "alice", "full_name": "Alice Chains", "email": "alicechains@example.com", - "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", "disabled": True, }, } @@ -57,7 +57,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", @@ -68,11 +68,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/docs_src/security/tutorial005_py39.py b/docs_src/security/tutorial005_py39.py index f9aed0a42..5bde47ef4 100644 --- a/docs_src/security/tutorial005_py39.py +++ b/docs_src/security/tutorial005_py39.py @@ -9,7 +9,7 @@ from fastapi.security import ( SecurityScopes, ) from jwt.exceptions import InvalidTokenError -from passlib.context import CryptContext +from pwdlib import PasswordHash from pydantic import BaseModel, ValidationError # to get a string like this run: @@ -24,14 +24,14 @@ fake_users_db = { "username": "johndoe", "full_name": "John Doe", "email": "johndoe@example.com", - "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc", "disabled": False, }, "alice": { "username": "alice", "full_name": "Alice Chains", "email": "alicechains@example.com", - "hashed_password": "$2b$12$gSvqqUPvlXP2tfVFaWK1Be7DlH.PKZbv5H8KnzzVgXXbVxpva.pFm", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$g2/AV1zwopqUntPKJavBFw$BwpRGDCyUHLvHICnwijyX8ROGoiUPwNKZ7915MeYfCE", "disabled": True, }, } @@ -58,7 +58,7 @@ class UserInDB(User): hashed_password: str -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +password_hash = PasswordHash.recommended() oauth2_scheme = OAuth2PasswordBearer( tokenUrl="token", @@ -69,11 +69,11 @@ app = FastAPI() def verify_password(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) + return password_hash.verify(plain_password, hashed_password) def get_password_hash(password): - return pwd_context.hash(password) + return password_hash.hash(password) def get_user(db, username: str): diff --git a/pyproject.toml b/pyproject.toml index fbfdea79a..41ef1eb76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -172,8 +172,6 @@ junit_family = "xunit2" filterwarnings = [ "error", 'ignore:starlette.middleware.wsgi is deprecated and will be removed in a future release\..*:DeprecationWarning:starlette', - # For passlib - "ignore:'crypt' is deprecated and slated for removal in Python 3.13:DeprecationWarning", # see https://trio.readthedocs.io/en/stable/history.html#trio-0-22-0-2022-09-28 "ignore:You seem to already have a custom.*:RuntimeWarning:trio", # TODO: remove after upgrading SQLAlchemy to a version that includes the following changes diff --git a/requirements-tests.txt b/requirements-tests.txt index e87a42162..53ec28d2e 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -9,7 +9,7 @@ flask >=1.1.2,<4.0.0 anyio[trio] >=3.2.1,<5.0.0 PyJWT==2.9.0 pyyaml >=5.3.1,<7.0.0 -passlib[bcrypt] >=1.7.2,<2.0.0 +pwdlib[argon2] >=0.2.1 inline-snapshot>=0.21.1 # types types-ujson ==5.10.0.20240515 From 861b22c40897a03d2d7e5926923d962121ed5e2e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Sep 2025 02:58:20 +0000 Subject: [PATCH 451/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index fe1fac8cf..3eeb976d7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,7 @@ hide: ### Docs +* 📝 Update `tutorial/security/oauth2-jwt/` to use `pwdlib` with Argon2 instead of `passlib`. PR [#13917](https://github.com/fastapi/fastapi/pull/13917) by [@Neizvestnyj](https://github.com/Neizvestnyj). * ✏️ Fix typos in OAuth2 password request forms. PR [#14112](https://github.com/fastapi/fastapi/pull/14112) by [@alv2017](https://github.com/alv2017). * 📝 Update contributing guidelines for installing requirements. PR [#14095](https://github.com/fastapi/fastapi/pull/14095) by [@alejsdev](https://github.com/alejsdev). From e329d78f866a12893699f786f1209a666e1688e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 29 Sep 2025 12:29:38 +0900 Subject: [PATCH 452/455] =?UTF-8?q?=F0=9F=90=9B=20Fix=20support=20for=20`S?= =?UTF-8?q?treamingResponse`s=20with=20dependencies=20with=20`yield`=20or?= =?UTF-8?q?=20`UploadFile`s,=20close=20after=20the=20response=20is=20done?= =?UTF-8?q?=20(#14099)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../en/docs/advanced/advanced-dependencies.md | 88 +++++ .../dependencies/dependencies-with-yield.md | 53 +-- docs_src/dependencies/tutorial013_an_py310.py | 38 ++ docs_src/dependencies/tutorial014_an_py310.py | 39 ++ fastapi/applications.py | 53 ++- fastapi/middleware/asyncexitstack.py | 18 + fastapi/routing.py | 333 +++++++++++------- tests/test_dependency_after_yield_raise.py | 69 ++++ .../test_dependency_after_yield_streaming.py | 130 +++++++ .../test_dependency_after_yield_websockets.py | 79 +++++ tests/test_dependency_contextmanager.py | 11 +- ..._dependency_yield_except_httpexception.py} | 0 tests/test_route_scope.py | 2 +- .../test_dependencies/test_tutorial008c.py | 2 +- 14 files changed, 731 insertions(+), 184 deletions(-) create mode 100644 docs_src/dependencies/tutorial013_an_py310.py create mode 100644 docs_src/dependencies/tutorial014_an_py310.py create mode 100644 fastapi/middleware/asyncexitstack.py create mode 100644 tests/test_dependency_after_yield_raise.py create mode 100644 tests/test_dependency_after_yield_streaming.py create mode 100644 tests/test_dependency_after_yield_websockets.py rename tests/{test_dependency_normal_exceptions.py => test_dependency_yield_except_httpexception.py} (100%) diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index c71c11404..e0404b389 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -63,3 +63,91 @@ In the chapters about security, there are utility functions that are implemented If you understood all this, you already know how those utility tools for security work underneath. /// + +## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning + +You most probably don't need these technical details. + +These details are useful mainly if you had a FastAPI application older than 0.118.0 and you are facing issues with dependencies with `yield`. + +/// + +Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed. + +### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details } + +Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response. + +The intention was to avoid holding resources for longer than necessary, waiting for the response to travel through the network. + +This change also meant that if you returned a `StreamingResponse`, the exit code of the dependency with `yield` would have been already run. + +For example, if you had a database session in a dependency with `yield`, the `StreamingResponse` would not be able to use that session while streaming data because the session would have already been closed in the exit code after `yield`. + +This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent. + +/// info + +As you will see below, this is very similar to the behavior before version 0.106.0, but with several improvements and bug fixes for corner cases. + +/// + +#### Use Cases with Early Exit Code { #use-cases-with-early-exit-code } + +There are some use cases with specific conditions that could benefit from the old behavior of running the exit code of dependencies with `yield` before sending the response. + +For example, imagine you have code that uses a database session in a dependency with `yield` only to verify a user, but the database session is never used again in the *path operation function*, only in the dependency, **and** the response takes a long time to be sent, like a `StreamingResponse` that sends data slowly, but for some reason doesn't use the database. + +In this case, the database session would be held until the response is finished being sent, but if you don't use it, then it wouldn't be necessary to hold it. + +Here's how it could look like: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +The exit code, the automatic closing of the `Session` in: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...would be run after the the response finishes sending the slow data: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +But as `generate_stream()` doesn't use the database session, it is not really necessary to keep the session open while sending the response. + +If you have this specific use case using SQLModel (or SQLAlchemy), you could explicitly close the session after you don't need it anymore: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +That way the session would release the database connection, so other requests could use it. + +If you have a different use case that needs to exit early from a dependency with `yield`, please create a GitHub Discussion Question with your specific use case and why you would benefit from having early closing for dependencies with `yield`. + +If there are compelling use cases for early closing in dependencies with `yield`, I would consider adding a new way to opt in to early closing. + +### Dependencies with `yield` and `except`, Technical Details { #dependencies-with-yield-and-except-technical-details } + +Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler. + +This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code. + +### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details } + +Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run. + +This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished. + +This was changed in FastAPI 0.106.0 with the intention to not hold resources while waiting for the response to travel through the network. + +/// tip + +Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection). + +So, this way you will probably have cleaner code. + +/// + +If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`. + +For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function. diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index 2e2a6a8e3..adc1afa8d 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -35,7 +35,7 @@ The yielded value is what is injected into *path operations* and other dependenc {* ../../docs_src/dependencies/tutorial007.py hl[4] *} -The code following the `yield` statement is executed after creating the response but before sending it: +The code following the `yield` statement is executed after the response: {* ../../docs_src/dependencies/tutorial007.py hl[5:6] *} @@ -51,7 +51,7 @@ You can use `async` or regular functions. If you use a `try` block in a dependency with `yield`, you'll receive any exception that was thrown when using the dependency. -For example, if some code at some point in the middle, in another dependency or in a *path operation*, made a database transaction "rollback" or create any other error, you will receive the exception in your dependency. +For example, if some code at some point in the middle, in another dependency or in a *path operation*, made a database transaction "rollback" or created any other exception, you would receive the exception in your dependency. So, you can look for that specific exception inside the dependency with `except SomeException`. @@ -95,9 +95,11 @@ This works thanks to Python's ASGIApp: + # Duplicate/override from Starlette to add AsyncExitStackMiddleware + # inside of ExceptionMiddleware, inside of custom user middlewares + debug = self.debug + error_handler = None + exception_handlers: dict[Any, ExceptionHandler] = {} + + for key, value in self.exception_handlers.items(): + if key in (500, Exception): + error_handler = value + else: + exception_handlers[key] = value + + middleware = ( + [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] + + self.user_middleware + + [ + Middleware( + ExceptionMiddleware, handlers=exception_handlers, debug=debug + ), + # Add FastAPI-specific AsyncExitStackMiddleware for closing files. + # Before this was also used for closing dependencies with yield but + # those now have their own AsyncExitStack, to properly support + # streaming responses while keeping compatibility with the previous + # versions (as of writing 0.117.1) that allowed doing + # except HTTPException inside a dependency with yield. + # This needs to happen after user middlewares because those create a + # new contextvars context copy by using a new AnyIO task group. + # This AsyncExitStack preserves the context for contextvars, not + # strictly necessary for closing files but it was one of the original + # intentions. + # If the AsyncExitStack lived outside of the custom middlewares and + # contextvars were set, for example in a dependency with 'yield' + # in that internal contextvars context, the values would not be + # available in the outer context of the AsyncExitStack. + # By placing the middleware and the AsyncExitStack here, inside all + # user middlewares, the same context is used. + # This is currently not needed, only for closing files, but used to be + # important when dependencies with yield were closed here. + Middleware(AsyncExitStackMiddleware), + ] + ) + + app = self.router + for cls, args, kwargs in reversed(middleware): + app = cls(app, *args, **kwargs) + return app + def openapi(self) -> Dict[str, Any]: """ Generate the OpenAPI schema of the application. This is called by FastAPI diff --git a/fastapi/middleware/asyncexitstack.py b/fastapi/middleware/asyncexitstack.py new file mode 100644 index 000000000..4ce3f5a62 --- /dev/null +++ b/fastapi/middleware/asyncexitstack.py @@ -0,0 +1,18 @@ +from contextlib import AsyncExitStack + +from starlette.types import ASGIApp, Receive, Scope, Send + + +# Used mainly to close files after the request is done, dependencies are closed +# in their own AsyncExitStack +class AsyncExitStackMiddleware: + def __init__( + self, app: ASGIApp, context_name: str = "fastapi_middleware_astack" + ) -> None: + self.app = app + self.context_name = context_name + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + async with AsyncExitStack() as stack: + scope[self.context_name] = stack + await self.app(scope, receive, send) diff --git a/fastapi/routing.py b/fastapi/routing.py index f620ced5f..65f739d95 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1,5 +1,6 @@ import dataclasses import email.message +import functools import inspect import json import sys @@ -8,6 +9,7 @@ from enum import Enum, IntEnum from typing import ( Any, AsyncIterator, + Awaitable, Callable, Collection, Coroutine, @@ -59,6 +61,8 @@ from fastapi.utils import ( ) from pydantic import BaseModel from starlette import routing +from starlette._exception_handler import wrap_app_handling_exceptions +from starlette._utils import is_async_callable from starlette.concurrency import run_in_threadpool from starlette.exceptions import HTTPException from starlette.requests import Request @@ -68,11 +72,9 @@ from starlette.routing import ( Match, compile_path, get_name, - request_response, - websocket_session, ) from starlette.routing import Mount as Mount # noqa -from starlette.types import AppType, ASGIApp, Lifespan, Scope +from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send from starlette.websockets import WebSocket from typing_extensions import Annotated, Doc, deprecated @@ -82,6 +84,73 @@ else: # pragma: no cover from asyncio import iscoroutinefunction +# Copy of starlette.routing.request_response modified to include the +# dependencies' AsyncExitStack +def request_response( + func: Callable[[Request], Union[Awaitable[Response], Response]], +) -> ASGIApp: + """ + Takes a function or coroutine `func(request) -> response`, + and returns an ASGI application. + """ + f: Callable[[Request], Awaitable[Response]] = ( + func if is_async_callable(func) else functools.partial(run_in_threadpool, func) # type:ignore + ) + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + request = Request(scope, receive, send) + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + # Starts customization + response_awaited = False + async with AsyncExitStack() as stack: + scope["fastapi_inner_astack"] = stack + # Same as in Starlette + response = await f(request) + await response(scope, receive, send) + # Continues customization + response_awaited = True + if not response_awaited: + raise FastAPIError( + "Response not awaited. There's a high chance that the " + "application code is raising an exception and a dependency with yield " + "has a block with a bare except, or a block with except Exception, " + "and is not raising the exception again. Read more about it in the " + "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except" + ) + + # Same as in Starlette + await wrap_app_handling_exceptions(app, request)(scope, receive, send) + + return app + + +# Copy of starlette.routing.websocket_session modified to include the +# dependencies' AsyncExitStack +def websocket_session( + func: Callable[[WebSocket], Awaitable[None]], +) -> ASGIApp: + """ + Takes a coroutine `func(session)`, and returns an ASGI application. + """ + # assert asyncio.iscoroutinefunction(func), "WebSocket endpoints must be async" + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + session = WebSocket(scope, receive=receive, send=send) + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + # Starts customization + async with AsyncExitStack() as stack: + scope["fastapi_inner_astack"] = stack + # Same as in Starlette + await func(session) + + # Same as in Starlette + await wrap_app_handling_exceptions(app, session)(scope, receive, send) + + return app + + def _prepare_response_content( res: Any, *, @@ -246,119 +315,120 @@ def get_request_handler( async def app(request: Request) -> Response: response: Union[Response, None] = None - async with AsyncExitStack() as file_stack: - try: - body: Any = None - if body_field: - if is_body_form: - body = await request.form() - file_stack.push_async_callback(body.close) - else: - body_bytes = await request.body() - if body_bytes: - json_body: Any = Undefined - content_type_value = request.headers.get("content-type") - if not content_type_value: - json_body = await request.json() - else: - message = email.message.Message() - message["content-type"] = content_type_value - if message.get_content_maintype() == "application": - subtype = message.get_content_subtype() - if subtype == "json" or subtype.endswith("+json"): - json_body = await request.json() - if json_body != Undefined: - body = json_body - else: - body = body_bytes - except json.JSONDecodeError as e: - validation_error = RequestValidationError( - [ - { - "type": "json_invalid", - "loc": ("body", e.pos), - "msg": "JSON decode error", - "input": {}, - "ctx": {"error": e.msg}, - } - ], - body=e.doc, - ) - raise validation_error from e - except HTTPException: - # If a middleware raises an HTTPException, it should be raised again - raise - except Exception as e: - http_error = HTTPException( - status_code=400, detail="There was an error parsing the body" - ) - raise http_error from e - errors: List[Any] = [] - async with AsyncExitStack() as async_exit_stack: - solved_result = await solve_dependencies( - request=request, - dependant=dependant, - body=body, - dependency_overrides_provider=dependency_overrides_provider, - async_exit_stack=async_exit_stack, - embed_body_fields=embed_body_fields, - ) - errors = solved_result.errors - if not errors: - raw_response = await run_endpoint_function( - dependant=dependant, - values=solved_result.values, - is_coroutine=is_coroutine, - ) - if isinstance(raw_response, Response): - if raw_response.background is None: - raw_response.background = solved_result.background_tasks - response = raw_response - else: - response_args: Dict[str, Any] = { - "background": solved_result.background_tasks - } - # If status_code was set, use it, otherwise use the default from the - # response class, in the case of redirect it's 307 - current_status_code = ( - status_code - if status_code - else solved_result.response.status_code - ) - if current_status_code is not None: - response_args["status_code"] = current_status_code - if solved_result.response.status_code: - response_args["status_code"] = ( - solved_result.response.status_code - ) - content = await serialize_response( - field=response_field, - response_content=raw_response, - include=response_model_include, - exclude=response_model_exclude, - by_alias=response_model_by_alias, - exclude_unset=response_model_exclude_unset, - exclude_defaults=response_model_exclude_defaults, - exclude_none=response_model_exclude_none, - is_coroutine=is_coroutine, - ) - response = actual_response_class(content, **response_args) - if not is_body_allowed_for_status_code(response.status_code): - response.body = b"" - response.headers.raw.extend(solved_result.response.headers.raw) - if errors: - validation_error = RequestValidationError( - _normalize_errors(errors), body=body - ) - raise validation_error - if response is None: - raise FastAPIError( - "No response object was returned. There's a high chance that the " - "application code is raising an exception and a dependency with yield " - "has a block with a bare except, or a block with except Exception, " - "and is not raising the exception again. Read more about it in the " - "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except" + file_stack = request.scope.get("fastapi_middleware_astack") + assert isinstance(file_stack, AsyncExitStack), ( + "fastapi_middleware_astack not found in request scope" + ) + + # Read body and auto-close files + try: + body: Any = None + if body_field: + if is_body_form: + body = await request.form() + file_stack.push_async_callback(body.close) + else: + body_bytes = await request.body() + if body_bytes: + json_body: Any = Undefined + content_type_value = request.headers.get("content-type") + if not content_type_value: + json_body = await request.json() + else: + message = email.message.Message() + message["content-type"] = content_type_value + if message.get_content_maintype() == "application": + subtype = message.get_content_subtype() + if subtype == "json" or subtype.endswith("+json"): + json_body = await request.json() + if json_body != Undefined: + body = json_body + else: + body = body_bytes + except json.JSONDecodeError as e: + validation_error = RequestValidationError( + [ + { + "type": "json_invalid", + "loc": ("body", e.pos), + "msg": "JSON decode error", + "input": {}, + "ctx": {"error": e.msg}, + } + ], + body=e.doc, ) + raise validation_error from e + except HTTPException: + # If a middleware raises an HTTPException, it should be raised again + raise + except Exception as e: + http_error = HTTPException( + status_code=400, detail="There was an error parsing the body" + ) + raise http_error from e + + # Solve dependencies and run path operation function, auto-closing dependencies + errors: List[Any] = [] + async_exit_stack = request.scope.get("fastapi_inner_astack") + assert isinstance(async_exit_stack, AsyncExitStack), ( + "fastapi_inner_astack not found in request scope" + ) + solved_result = await solve_dependencies( + request=request, + dependant=dependant, + body=body, + dependency_overrides_provider=dependency_overrides_provider, + async_exit_stack=async_exit_stack, + embed_body_fields=embed_body_fields, + ) + errors = solved_result.errors + if not errors: + raw_response = await run_endpoint_function( + dependant=dependant, + values=solved_result.values, + is_coroutine=is_coroutine, + ) + if isinstance(raw_response, Response): + if raw_response.background is None: + raw_response.background = solved_result.background_tasks + response = raw_response + else: + response_args: Dict[str, Any] = { + "background": solved_result.background_tasks + } + # If status_code was set, use it, otherwise use the default from the + # response class, in the case of redirect it's 307 + current_status_code = ( + status_code if status_code else solved_result.response.status_code + ) + if current_status_code is not None: + response_args["status_code"] = current_status_code + if solved_result.response.status_code: + response_args["status_code"] = solved_result.response.status_code + content = await serialize_response( + field=response_field, + response_content=raw_response, + include=response_model_include, + exclude=response_model_exclude, + by_alias=response_model_by_alias, + exclude_unset=response_model_exclude_unset, + exclude_defaults=response_model_exclude_defaults, + exclude_none=response_model_exclude_none, + is_coroutine=is_coroutine, + ) + response = actual_response_class(content, **response_args) + if not is_body_allowed_for_status_code(response.status_code): + response.body = b"" + response.headers.raw.extend(solved_result.response.headers.raw) + if errors: + validation_error = RequestValidationError( + _normalize_errors(errors), body=body + ) + raise validation_error + + # Return response + assert response return response return app @@ -370,24 +440,23 @@ def get_websocket_app( embed_body_fields: bool = False, ) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: async def app(websocket: WebSocket) -> None: - async with AsyncExitStack() as async_exit_stack: - # TODO: remove this scope later, after a few releases - # This scope fastapi_astack is no longer used by FastAPI, kept for - # compatibility, just in case - websocket.scope["fastapi_astack"] = async_exit_stack - solved_result = await solve_dependencies( - request=websocket, - dependant=dependant, - dependency_overrides_provider=dependency_overrides_provider, - async_exit_stack=async_exit_stack, - embed_body_fields=embed_body_fields, + async_exit_stack = websocket.scope.get("fastapi_inner_astack") + assert isinstance(async_exit_stack, AsyncExitStack), ( + "fastapi_inner_astack not found in request scope" + ) + solved_result = await solve_dependencies( + request=websocket, + dependant=dependant, + dependency_overrides_provider=dependency_overrides_provider, + async_exit_stack=async_exit_stack, + embed_body_fields=embed_body_fields, + ) + if solved_result.errors: + raise WebSocketRequestValidationError( + _normalize_errors(solved_result.errors) ) - if solved_result.errors: - raise WebSocketRequestValidationError( - _normalize_errors(solved_result.errors) - ) - assert dependant.call is not None, "dependant.call must be a function" - await dependant.call(**solved_result.values) + assert dependant.call is not None, "dependant.call must be a function" + await dependant.call(**solved_result.values) return app diff --git a/tests/test_dependency_after_yield_raise.py b/tests/test_dependency_after_yield_raise.py new file mode 100644 index 000000000..b560dc36f --- /dev/null +++ b/tests/test_dependency_after_yield_raise.py @@ -0,0 +1,69 @@ +from typing import Any + +import pytest +from fastapi import Depends, FastAPI, HTTPException +from fastapi.testclient import TestClient +from typing_extensions import Annotated + + +class CustomError(Exception): + pass + + +def catching_dep() -> Any: + try: + yield "s" + except CustomError as err: + raise HTTPException(status_code=418, detail="Session error") from err + + +def broken_dep() -> Any: + yield "s" + raise ValueError("Broken after yield") + + +app = FastAPI() + + +@app.get("/catching") +def catching(d: Annotated[str, Depends(catching_dep)]) -> Any: + raise CustomError("Simulated error during streaming") + + +@app.get("/broken") +def broken(d: Annotated[str, Depends(broken_dep)]) -> Any: + return {"message": "all good?"} + + +client = TestClient(app) + + +def test_catching(): + response = client.get("/catching") + assert response.status_code == 418 + assert response.json() == {"detail": "Session error"} + + +def test_broken_raise(): + with pytest.raises(ValueError, match="Broken after yield"): + client.get("/broken") + + +def test_broken_no_raise(): + """ + When a dependency with yield raises after the yield (not in an except), the + response is already "successfully" sent back to the client, but there's still + an error in the server afterwards, an exception is raised and captured or shown + in the server logs. + """ + with TestClient(app, raise_server_exceptions=False) as client: + response = client.get("/broken") + assert response.status_code == 200 + assert response.json() == {"message": "all good?"} + + +def test_broken_return_finishes(): + client = TestClient(app, raise_server_exceptions=False) + response = client.get("/broken") + assert response.status_code == 200 + assert response.json() == {"message": "all good?"} diff --git a/tests/test_dependency_after_yield_streaming.py b/tests/test_dependency_after_yield_streaming.py new file mode 100644 index 000000000..7e1c8822b --- /dev/null +++ b/tests/test_dependency_after_yield_streaming.py @@ -0,0 +1,130 @@ +from contextlib import contextmanager +from typing import Any, Generator + +import pytest +from fastapi import Depends, FastAPI +from fastapi.responses import StreamingResponse +from fastapi.testclient import TestClient +from typing_extensions import Annotated + + +class Session: + def __init__(self) -> None: + self.data = ["foo", "bar", "baz"] + self.open = True + + def __iter__(self) -> Generator[str, None, None]: + for item in self.data: + if self.open: + yield item + else: + raise ValueError("Session closed") + + +@contextmanager +def acquire_session() -> Generator[Session, None, None]: + session = Session() + try: + yield session + finally: + session.open = False + + +def dep_session() -> Any: + with acquire_session() as s: + yield s + + +def broken_dep_session() -> Any: + with acquire_session() as s: + s.open = False + yield s + + +SessionDep = Annotated[Session, Depends(dep_session)] +BrokenSessionDep = Annotated[Session, Depends(broken_dep_session)] + +app = FastAPI() + + +@app.get("/data") +def get_data(session: SessionDep) -> Any: + data = list(session) + return data + + +@app.get("/stream-simple") +def get_stream_simple(session: SessionDep) -> Any: + def iter_data(): + yield from ["x", "y", "z"] + + return StreamingResponse(iter_data()) + + +@app.get("/stream-session") +def get_stream_session(session: SessionDep) -> Any: + def iter_data(): + yield from session + + return StreamingResponse(iter_data()) + + +@app.get("/broken-session-data") +def get_broken_session_data(session: BrokenSessionDep) -> Any: + return list(session) + + +@app.get("/broken-session-stream") +def get_broken_session_stream(session: BrokenSessionDep) -> Any: + def iter_data(): + yield from session + + return StreamingResponse(iter_data()) + + +client = TestClient(app) + + +def test_regular_no_stream(): + response = client.get("/data") + assert response.json() == ["foo", "bar", "baz"] + + +def test_stream_simple(): + response = client.get("/stream-simple") + assert response.text == "xyz" + + +def test_stream_session(): + response = client.get("/stream-session") + assert response.text == "foobarbaz" + + +def test_broken_session_data(): + with pytest.raises(ValueError, match="Session closed"): + client.get("/broken-session-data") + + +def test_broken_session_data_no_raise(): + client = TestClient(app, raise_server_exceptions=False) + response = client.get("/broken-session-data") + assert response.status_code == 500 + assert response.text == "Internal Server Error" + + +def test_broken_session_stream_raise(): + # Can raise ValueError on Pydantic v2 and ExceptionGroup on Pydantic v1 + with pytest.raises((ValueError, Exception)): + client.get("/broken-session-stream") + + +def test_broken_session_stream_no_raise(): + """ + When a dependency with yield raises after the streaming response already started + the 200 status code is already sent, but there's still an error in the server + afterwards, an exception is raised and captured or shown in the server logs. + """ + with TestClient(app, raise_server_exceptions=False) as client: + response = client.get("/broken-session-stream") + assert response.status_code == 200 + assert response.text == "" diff --git a/tests/test_dependency_after_yield_websockets.py b/tests/test_dependency_after_yield_websockets.py new file mode 100644 index 000000000..7c323c338 --- /dev/null +++ b/tests/test_dependency_after_yield_websockets.py @@ -0,0 +1,79 @@ +from contextlib import contextmanager +from typing import Any, Generator + +import pytest +from fastapi import Depends, FastAPI, WebSocket +from fastapi.testclient import TestClient +from typing_extensions import Annotated + + +class Session: + def __init__(self) -> None: + self.data = ["foo", "bar", "baz"] + self.open = True + + def __iter__(self) -> Generator[str, None, None]: + for item in self.data: + if self.open: + yield item + else: + raise ValueError("Session closed") + + +@contextmanager +def acquire_session() -> Generator[Session, None, None]: + session = Session() + try: + yield session + finally: + session.open = False + + +def dep_session() -> Any: + with acquire_session() as s: + yield s + + +def broken_dep_session() -> Any: + with acquire_session() as s: + s.open = False + yield s + + +SessionDep = Annotated[Session, Depends(dep_session)] +BrokenSessionDep = Annotated[Session, Depends(broken_dep_session)] + +app = FastAPI() + + +@app.websocket("/ws") +async def websocket_endpoint(websocket: WebSocket, session: SessionDep): + await websocket.accept() + for item in session: + await websocket.send_text(f"{item}") + + +@app.websocket("/ws-broken") +async def websocket_endpoint_broken(websocket: WebSocket, session: BrokenSessionDep): + await websocket.accept() + for item in session: + await websocket.send_text(f"{item}") # pragma no cover + + +client = TestClient(app) + + +def test_websocket_dependency_after_yield(): + with client.websocket_connect("/ws") as websocket: + data = websocket.receive_text() + assert data == "foo" + data = websocket.receive_text() + assert data == "bar" + data = websocket.receive_text() + assert data == "baz" + + +def test_websocket_dependency_after_yield_broken(): + with pytest.raises(ValueError, match="Session closed"): + with client.websocket_connect("/ws-broken"): + pass # pragma no cover diff --git a/tests/test_dependency_contextmanager.py b/tests/test_dependency_contextmanager.py index 039c423b9..02c10458c 100644 --- a/tests/test_dependency_contextmanager.py +++ b/tests/test_dependency_contextmanager.py @@ -286,12 +286,12 @@ def test_background_tasks(): assert data["context_a"] == "started a" assert data["bg"] == "not set" middleware_state = json.loads(response.headers["x-state"]) - assert middleware_state["context_b"] == "finished b with a: started a" - assert middleware_state["context_a"] == "finished a" + assert middleware_state["context_b"] == "started b" + assert middleware_state["context_a"] == "started a" assert middleware_state["bg"] == "not set" assert state["context_b"] == "finished b with a: started a" assert state["context_a"] == "finished a" - assert state["bg"] == "bg set - b: finished b with a: started a - a: finished a" + assert state["bg"] == "bg set - b: started b - a: started a" def test_sync_raise_raises(): @@ -397,7 +397,4 @@ def test_sync_background_tasks(): assert data["sync_bg"] == "not set" assert state["context_b"] == "finished b with a: started a" assert state["context_a"] == "finished a" - assert ( - state["sync_bg"] - == "sync_bg set - b: finished b with a: started a - a: finished a" - ) + assert state["sync_bg"] == "sync_bg set - b: started b - a: started a" diff --git a/tests/test_dependency_normal_exceptions.py b/tests/test_dependency_yield_except_httpexception.py similarity index 100% rename from tests/test_dependency_normal_exceptions.py rename to tests/test_dependency_yield_except_httpexception.py diff --git a/tests/test_route_scope.py b/tests/test_route_scope.py index 2021c828f..792ea66c3 100644 --- a/tests/test_route_scope.py +++ b/tests/test_route_scope.py @@ -47,4 +47,4 @@ def test_websocket(): def test_websocket_invalid_path_doesnt_match(): with pytest.raises(WebSocketDisconnect): with client.websocket_connect("/itemsx/portal-gun"): - pass + pass # pragma: no cover diff --git a/tests/test_tutorial/test_dependencies/test_tutorial008c.py b/tests/test_tutorial/test_dependencies/test_tutorial008c.py index 11e96bf46..369b0a221 100644 --- a/tests/test_tutorial/test_dependencies/test_tutorial008c.py +++ b/tests/test_tutorial/test_dependencies/test_tutorial008c.py @@ -40,7 +40,7 @@ def test_fastapi_error(mod: ModuleType): client = TestClient(mod.app) with pytest.raises(FastAPIError) as exc_info: client.get("/items/portal-gun") - assert "No response object was returned" in exc_info.value.args[0] + assert "raising an exception and a dependency with yield" in exc_info.value.args[0] def test_internal_server_error(mod: ModuleType): From bfa54b406d298155edbdfe8fdd173479857d5ad6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Sep 2025 03:31:17 +0000 Subject: [PATCH 453/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [skip ci] --- docs/en/docs/release-notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 3eeb976d7..5ba550dbb 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,10 @@ hide: ## Latest Changes +### Fixes + +* 🐛 Fix support for `StreamingResponse`s with dependencies with `yield` or `UploadFile`s, close after the response is done. PR [#14099](https://github.com/fastapi/fastapi/pull/14099) by [@tiangolo](https://github.com/tiangolo). + ### Docs * 📝 Update `tutorial/security/oauth2-jwt/` to use `pwdlib` with Argon2 instead of `passlib`. PR [#13917](https://github.com/fastapi/fastapi/pull/13917) by [@Neizvestnyj](https://github.com/Neizvestnyj). From 1d5168a4a1293fbc44799fbab615a120c6fdb85e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 29 Sep 2025 05:33:39 +0200 Subject: [PATCH 454/455] =?UTF-8?q?=F0=9F=93=9D=20Update=20release=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 5ba550dbb..684100693 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,16 @@ hide: * 🐛 Fix support for `StreamingResponse`s with dependencies with `yield` or `UploadFile`s, close after the response is done. PR [#14099](https://github.com/fastapi/fastapi/pull/14099) by [@tiangolo](https://github.com/tiangolo). +Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response. + +This change also meant that if you returned a `StreamingResponse`, the exit code of the dependency with `yield` would have been already run. + +For example, if you had a database session in a dependency with `yield`, the `StreamingResponse` would not be able to use that session while streaming data because the session would have already been closed in the exit code after `yield`. + +This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent. + +You can read more about it in the docs for [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](https://fastapi.tiangolo.com/advanced/advanced-dependencies#dependencies-with-yield-httpexception-except-and-background-tasks). Including what you could do if you wanted to close a database session earlier, before returning the response to the client. + ### Docs * 📝 Update `tutorial/security/oauth2-jwt/` to use `pwdlib` with Argon2 instead of `passlib`. PR [#13917](https://github.com/fastapi/fastapi/pull/13917) by [@Neizvestnyj](https://github.com/Neizvestnyj). From 333f1ba737be6507fc707278f6b69cf1f81efdc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Mon, 29 Sep 2025 05:34:21 +0200 Subject: [PATCH 455/455] =?UTF-8?q?=F0=9F=94=96=20Release=20version=200.11?= =?UTF-8?q?8.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/release-notes.md | 2 ++ fastapi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 684100693..29112649c 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,6 +7,8 @@ hide: ## Latest Changes +## 0.118.0 + ### Fixes * 🐛 Fix support for `StreamingResponse`s with dependencies with `yield` or `UploadFile`s, close after the response is done. PR [#14099](https://github.com/fastapi/fastapi/pull/14099) by [@tiangolo](https://github.com/tiangolo). diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 986fd200c..03a5aaad5 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.117.1" +__version__ = "0.118.0" from starlette import status as status